-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.py
111 lines (87 loc) · 3.8 KB
/
common.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from flask import abort, Response
import os
import time
# Names for secrets
from iconik import Iconik
AUTH_TOKEN_NAME = "iconik-token"
SHARED_SECRET_NAME = "bz-shared-secret"
X_BZ_SHARED_SECRET = "x-bz-secret"
def iconik_handler(req, logger, processor, bz_shared_secret):
"""
Handles iconik custom action.
"/add" route copies specified assets to LucidLink
"/remove" route copies specified assets to B2, then deletes
those assets' files from LucidLink
"""
start_time = time.perf_counter()
logger.log("DEBUG", "Handler started")
logger.log("DEBUG", req.get_data(as_text=True), req)
# Authenticate caller via shared secret
if req.headers.get(X_BZ_SHARED_SECRET) != bz_shared_secret:
logger.log("ERROR", f"Invalid {X_BZ_SHARED_SECRET} header")
# 401 should always return a WWW-Authenticate header
abort(
401,
response=Response(
status=401,
headers={"WWW-Authenticate": X_BZ_SHARED_SECRET}))
# Only POST is allowed
if req.method != "POST":
logger.log("ERROR", f"Invalid method: {req.method}")
abort(405)
# Parse the request body as JSON; return None on any errors rather than
# raising an exception
request = req.get_json(silent=True)
# Is JSON body missing or badly formed?
if not request:
logger.log("ERROR", f"Invalid JSON body: {req.get_data(as_text=True)}")
abort(400)
# Create an iconic API client
iconik = Iconik(os.environ['ICONIK_ID'], request.get("auth_token"))
# The LucidLink storage
ll_storage = iconik.get_storage(id_=req.args.get('ll_storage_id'))
if not ll_storage:
logger.log("ERROR", f"Can't find configured storage: {req.args.get('ll_storage_id')}")
abort(500)
# The B2 storage
b2_storage = iconik.get_storage(id_=req.args.get("b2_storage_id"))
if not b2_storage:
logger.log("ERROR", f"Can't find configured storage: {req.args.get('b2_storage_id')}")
abort(500)
# Check that context is as expected
if request.get("context") not in ["ASSET", "COLLECTION", "BULK"]:
logger.log("ERROR", f"Invalid context: {request.get('context')}")
abort(400)
# Perform the requested operation
if req.path in ["/add", "/remove"]:
request["action"] = req.path[1:]
processor(process_request, request, logger, iconik, b2_storage, ll_storage)
else:
logger.log("ERROR", f"Invalid path: {req.path}")
abort(404)
logger.log("DEBUG", f"Handler complete in {(time.perf_counter() - start_time):.3f} seconds")
return "OK"
def process_request(request, logger, iconik, b2_storage, ll_storage):
start_time = time.perf_counter()
logger.log("DEBUG", "Processor started")
# The formats that we're going to copy
format_names = os.environ.get("FORMAT_NAMES", "ORIGINAL,PPRO_PROXY").split(',')
if request["action"] == "add":
# Copy files to LucidLink
iconik.copy_files(request=request,
format_names=format_names,
target_storage_id=ll_storage["id"])
elif request["action"] == "remove":
# Copy any original files to B2, waiting for job(s) to complete
if iconik.copy_files(request=request,
format_names=[format_names[0]],
target_storage_id=b2_storage["id"],
sync=True):
# Delete files from LucidLink
iconik.delete_files(request=request,
format_names=format_names,
storage_id=ll_storage["id"])
logger.log("DEBUG", f"Processor complete in {(time.perf_counter() - start_time):.3f} seconds")
def get_version():
version = open('version.txt', 'r').read().strip()
return version