Fixed merge issues
This commit is contained in:
+357
-101
@@ -22,6 +22,7 @@ class AppBase:
|
||||
|
||||
# apikey is for the user / org
|
||||
# authorization is for the specific workflow
|
||||
|
||||
self.url = os.getenv("CALLBACK_URL", "https://shuffler.io")
|
||||
self.base_url = os.getenv("BASE_URL", "https://shuffler.io")
|
||||
self.action = os.getenv("ACTION", "")
|
||||
@@ -54,7 +55,7 @@ class AppBase:
|
||||
# for action["parameters"]
|
||||
# print("AUTH: ", key, value)
|
||||
# params[item["key"]] = item["value"]
|
||||
#except KeyError:
|
||||
#except KeyError:
|
||||
# print("No authentication specified!")
|
||||
# pass
|
||||
|
||||
@@ -513,10 +514,31 @@ class AppBase:
|
||||
# return
|
||||
|
||||
print("[INFO] Multiplier length: %d" % len(param_multiplier))
|
||||
#tmp = ""
|
||||
for subparams in param_multiplier:
|
||||
print(f"SUBPARAMS IN MULTI: {subparams}")
|
||||
try:
|
||||
tmp = await func(**subparams)
|
||||
#tmp = await func(**subparams)
|
||||
|
||||
while True:
|
||||
try:
|
||||
tmp = await func(**subparams)
|
||||
break
|
||||
except TypeError as e:
|
||||
errorstring = "%s" % e
|
||||
if "got an unexpected keyword argument" in errorstring:
|
||||
fieldsplit = errorstring.split("'")
|
||||
if len(fieldsplit) > 1:
|
||||
field = fieldsplit[1]
|
||||
|
||||
try:
|
||||
del subparams[field]
|
||||
print("Removed field invalid field %s" % field)
|
||||
except KeyError:
|
||||
break
|
||||
else:
|
||||
raise e
|
||||
|
||||
except:
|
||||
e = ""
|
||||
try:
|
||||
@@ -661,6 +683,59 @@ class AppBase:
|
||||
else:
|
||||
return returns
|
||||
|
||||
def set_cache(self, key, value):
|
||||
org_id = self.full_execution["workflow"]["execution_org"]["id"]
|
||||
url = "%s/api/v1/orgs/%s/set_cache" % (self.url, org_id)
|
||||
data = {
|
||||
"workflow_id": self.full_execution["workflow"]["id"],
|
||||
"execution_id": self.current_execution_id,
|
||||
"authorization": self.authorization,
|
||||
"org_id": org_id,
|
||||
"key": key,
|
||||
"value": str(value),
|
||||
}
|
||||
|
||||
response = requests.post(url, json=data)
|
||||
try:
|
||||
allvalues = response.json()
|
||||
allvalues["key"] = key
|
||||
allvalues["value"] = str(value)
|
||||
return allvalues
|
||||
except:
|
||||
print("Value couldn't be parsed")
|
||||
#return response.json()
|
||||
return {"success": False}
|
||||
|
||||
def get_cache(self, key):
|
||||
org_id = self.full_execution["workflow"]["execution_org"]["id"]
|
||||
url = "%s/api/v1/orgs/%s/get_cache" % (self.url, org_id)
|
||||
data = {
|
||||
"workflow_id": self.full_execution["workflow"]["id"],
|
||||
"execution_id": self.current_execution_id,
|
||||
"authorization": self.authorization,
|
||||
"org_id": org_id,
|
||||
"key": key,
|
||||
}
|
||||
|
||||
value = requests.post(url, json=data)
|
||||
try:
|
||||
allvalues = value.json()
|
||||
print("VAL1: ", allvalues)
|
||||
allvalues["key"] = key
|
||||
print("VAL2: ", allvalues)
|
||||
|
||||
try:
|
||||
parsedvalue = json.loads(allvalues["value"])
|
||||
allvalues["value"] = parsedvalue
|
||||
except:
|
||||
print("Parsing of value as JSON failed. Continue anyway!")
|
||||
|
||||
return allvalues
|
||||
except:
|
||||
print("Value couldn't be parsed, or json dump of value failed")
|
||||
#return value.json()
|
||||
return {"success": False}
|
||||
|
||||
# Sets files in the backend
|
||||
def set_files(self, infiles):
|
||||
full_execution = self.full_execution
|
||||
@@ -859,7 +934,6 @@ class AppBase:
|
||||
return parse_nested_param(string + ')', level)
|
||||
elif len(re.findall("\(", string)) < len(re.findall("\)", string)):
|
||||
return parse_nested_param('(' + string, level)
|
||||
|
||||
else:
|
||||
return 'Failed to parse params'
|
||||
|
||||
@@ -950,23 +1024,25 @@ class AppBase:
|
||||
print(f"JSON ERROR in join(): {e}")
|
||||
|
||||
if "len" in thistype or "length" in thistype or "lenght" in thistype:
|
||||
tmp = ""
|
||||
print(f"Trying to length-parse: {data}")
|
||||
try:
|
||||
tmp = json.loads(tmpdata)
|
||||
except:
|
||||
tmp_len = json.loads(data, parse_float=str, parse_int=str, parse_constant=str)
|
||||
except (NameError, KeyError, TypeError, json.decoder.JSONDecodeError) as e:
|
||||
try:
|
||||
tmpdata = data.replace("\'", "\"")
|
||||
tmp = json.loads(tmpdata)
|
||||
except:
|
||||
print("[ERROR] Parsing bug for length in app sdk")
|
||||
pass
|
||||
print(f"[WARNING] INITIAL Parsing bug for length in app sdk: {e}")
|
||||
# data = data.replace("\'", "\"")
|
||||
data = data.replace("True", "true")
|
||||
data = data.replace("False", "false")
|
||||
data = data.replace("None", "null")
|
||||
data = data.replace("\"", "\\\"")
|
||||
data = data.replace("'", "\"")
|
||||
|
||||
if isinstance(tmp, list):
|
||||
return str(len(tmp))
|
||||
elif isinstance(tmp, object):
|
||||
return str(len(tmp))
|
||||
tmp_len = json.loads(data, parse_float=str, parse_int=str, parse_constant=str)
|
||||
except (NameError, KeyError, TypeError, json.decoder.JSONDecodeError) as e:
|
||||
tmp_len = str(data)
|
||||
|
||||
return str(len(tmp_len))
|
||||
|
||||
return str(len(data))
|
||||
if "parse" in thistype:
|
||||
splitvalues = []
|
||||
default_error = """Error. Expected syntax: parse(["hello","test1"],0:1)"""
|
||||
@@ -1003,49 +1079,65 @@ class AppBase:
|
||||
def parse_wrapper(data):
|
||||
try:
|
||||
if "(" not in data or ")" not in data:
|
||||
return (data, False)
|
||||
return data, False
|
||||
except TypeError:
|
||||
return (data, False)
|
||||
|
||||
#print("Running %s" % data)
|
||||
|
||||
# Look for the INNER wrapper first, then move out
|
||||
wrappers = ["int", "number", "lower", "upper", "trim", "strip", "split", "parse", "len", "length", "lenght", "join"]
|
||||
found = False
|
||||
for wrapper in wrappers:
|
||||
if wrapper not in data.lower():
|
||||
continue
|
||||
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
return (data, False)
|
||||
|
||||
return data, False
|
||||
|
||||
wrappers = ["int", "number", "lower", "upper", "trim", "strip", "split", "parse", "len", "length", "lenght",
|
||||
"join"]
|
||||
|
||||
if not any(wrapper in data for wrapper in wrappers):
|
||||
return data, False
|
||||
|
||||
# Do stuff here.
|
||||
innervalue = parse_nested_param(data, maxDepth(data)-0)
|
||||
outervalue = parse_nested_param(data, maxDepth(data)-1)
|
||||
print("INNER: ", innervalue)
|
||||
print("OUTER: ", outervalue)
|
||||
|
||||
if outervalue != innervalue:
|
||||
#print("Outer: ", outervalue, " inner: ", innervalue)
|
||||
for key in range(len(innervalue)):
|
||||
# Replace OUTERVALUE[key] with INNERVALUE[key] in data.
|
||||
print("Replace %s with %s in %s" % (outervalue[key], innervalue[key], data))
|
||||
data = data.replace(outervalue[key], innervalue[key])
|
||||
else:
|
||||
for thistype in wrappers:
|
||||
if thistype.lower() not in data.lower():
|
||||
inner_value = parse_nested_param(data, maxDepth(data) - 0)
|
||||
outer_value = parse_nested_param(data, maxDepth(data) - 1)
|
||||
|
||||
print("INNER: ", inner_value)
|
||||
print("OUTER: ", outer_value)
|
||||
|
||||
wrapper_group = "|".join(wrappers)
|
||||
parse_string = data
|
||||
max_depth = maxDepth(parse_string)
|
||||
|
||||
if outer_value != inner_value:
|
||||
for casting_items in reversed(range(max_depth + 1)):
|
||||
c_parentheses = parse_nested_param(parse_string, casting_items)[0]
|
||||
match_string = re.escape(c_parentheses)
|
||||
custom_casting = re.findall(fr"({wrapper_group})\({match_string}", parse_string)
|
||||
|
||||
# no matching ; go next group
|
||||
if len(custom_casting) == 0:
|
||||
continue
|
||||
|
||||
parsed_value = parse_type(innervalue[0], thistype.lower())
|
||||
print("Parsed value from %s: %s" % (thistype, parsed_value))
|
||||
return (parsed_value, True)
|
||||
|
||||
#print("DATA: %s\n" % data)
|
||||
return (parse_wrapper(data)[0], True)
|
||||
|
||||
|
||||
inner_result = parse_type(c_parentheses, custom_casting[0])
|
||||
|
||||
# if result is a string then parse else return
|
||||
if isinstance(inner_result, str):
|
||||
parse_string = parse_string.replace(f"{custom_casting[0]}({c_parentheses})", inner_result)
|
||||
elif isinstance(inner_result, list):
|
||||
parse_string = parse_string.replace(f"{custom_casting[0]}({c_parentheses})",
|
||||
json.dumps(inner_result))
|
||||
else:
|
||||
parse_string = inner_result
|
||||
break
|
||||
else:
|
||||
c_parentheses = parse_nested_param(parse_string, 0)[0]
|
||||
match_string = re.escape(c_parentheses)
|
||||
custom_casting = re.findall(fr"({wrapper_group})\({match_string}", parse_string)
|
||||
|
||||
# check if a wrapper was found
|
||||
if len(custom_casting) != 0:
|
||||
inner_result = parse_type(c_parentheses, custom_casting[0])
|
||||
if isinstance(inner_result, str):
|
||||
parse_string = parse_string.replace(f"{custom_casting[0]}({c_parentheses})", inner_result)
|
||||
elif isinstance(inner_result, list):
|
||||
parse_string = parse_string.replace(f"{custom_casting[0]}({c_parentheses})",
|
||||
json.dumps(inner_result))
|
||||
else:
|
||||
parse_string = inner_result
|
||||
|
||||
return parse_string, True
|
||||
|
||||
# Looks for parantheses to grab special cases within a string, e.g:
|
||||
# int(1) lower(HELLO) or length(what's the length)
|
||||
@@ -1121,15 +1213,19 @@ class AppBase:
|
||||
|
||||
# Parses JSON loops and such down to the item you're looking for
|
||||
def recurse_json(basejson, parsersplit):
|
||||
match = "#(\d+):?-?([0-9a-z]+)?#?"
|
||||
match = "#([0-9a-z]+):?-?([0-9a-z]+)?#?"
|
||||
#print("Split: %s\n%s" % (parsersplit, basejson))
|
||||
try:
|
||||
outercnt = 0
|
||||
|
||||
# Loops over split values
|
||||
for value in parsersplit:
|
||||
#if " " in value:
|
||||
# value = value.replace(" ", "_", -1)
|
||||
|
||||
#print("VALUE: %s\n" % value)
|
||||
actualitem = re.findall(match, value, re.MULTILINE)
|
||||
#print("ACTUAL RECURSE: (%s) %s" % (value, actualitem))
|
||||
if value == "#":
|
||||
newvalue = []
|
||||
for innervalue in basejson:
|
||||
@@ -1158,7 +1254,12 @@ class AppBase:
|
||||
|
||||
# Means it's a single item -> continue
|
||||
if seconditem == "":
|
||||
#print("[INFO] In first - handling %s" % firstitem)
|
||||
print("[INFO] In first - handling %s. Len: %d" % (firstitem, len(basejson)))
|
||||
if firstitem.lower() == "max" or firstitem.lower() == "last":
|
||||
firstitem = len(basejson)-1
|
||||
if firstitem.lower() == "min" or firstitem.lower() == "first":
|
||||
firstitem = 0
|
||||
|
||||
tmpitem = basejson[int(firstitem)]
|
||||
try:
|
||||
newvalue, is_loop = recurse_json(tmpitem, parsersplit[outercnt+1:])
|
||||
@@ -1166,16 +1267,23 @@ class AppBase:
|
||||
newvalue, is_loop = (tmpitem, parsersplit[outercnt+1:])
|
||||
else:
|
||||
print("[INFO] In ELSE - handling %s and %s" % (firstitem, seconditem))
|
||||
if seconditem == "max":
|
||||
seconditem = len(basejson)
|
||||
if seconditem == "min":
|
||||
if firstitem.lower() == "max" or firstitem.lower() == "last":
|
||||
firstitem = len(basejson)-1
|
||||
if firstitem.lower() == "min" or firstitem.lower() == "first":
|
||||
firstitem = 0
|
||||
if seconditem.lower() == "max" or seconditem.lower() == "last":
|
||||
seconditem = len(basejson)-1
|
||||
if seconditem.lower() == "min" or seconditem.lower() == "first":
|
||||
seconditem = 0
|
||||
|
||||
newvalue = []
|
||||
for i in range(int(firstitem), int(seconditem)):
|
||||
if int(seconditem) > len(basejson):
|
||||
seconditem = len(basejson)
|
||||
|
||||
for i in range(int(firstitem), int(seconditem)+1):
|
||||
# 1. Check the next item (message)
|
||||
# 2. Call this function again
|
||||
print("Base: %s" % basejson[i])
|
||||
#print("Base: %s" % basejson[i])
|
||||
|
||||
try:
|
||||
ret, is_loop = recurse_json(basejson[i], parsersplit[outercnt+1:])
|
||||
@@ -1184,10 +1292,11 @@ class AppBase:
|
||||
#ret = innervalue
|
||||
ret, is_loop = recurse_json(innervalue, parsersplit[outercnt:])
|
||||
|
||||
print(ret)
|
||||
#print("IN LIST: %s" % ret)
|
||||
#exit()
|
||||
newvalue.append(ret)
|
||||
|
||||
#print("Returning %s" % newvalue)
|
||||
return newvalue, is_loop
|
||||
|
||||
else:
|
||||
@@ -1195,16 +1304,43 @@ class AppBase:
|
||||
if len(value) == 0:
|
||||
return basejson, False
|
||||
|
||||
if isinstance(basejson[value], str):
|
||||
print(f"LOADING STRING '%s' AS JSON" % basejson[value])
|
||||
try:
|
||||
basejson = json.loads(basejson[value])
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("RETURNING BECAUSE '%s' IS A NORMAL STRING" % basejson[value])
|
||||
return basejson[value], False
|
||||
else:
|
||||
basejson = basejson[value]
|
||||
|
||||
try:
|
||||
if isinstance(basejson, list):
|
||||
print("[WARNING] VALUE IN ISINSTANCE IS NOT TO BE USED (list): %s" % value)
|
||||
return basejson, False
|
||||
elif isinstance(basejson[value], str):
|
||||
print(f"[INFO] LOADING STRING '%s' AS JSON" % basejson[value])
|
||||
try:
|
||||
basejson = json.loads(basejson[value])
|
||||
print("BASEJSON: %s" % basejson)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("RETURNING BECAUSE '%s' IS A NORMAL STRING" % basejson[value])
|
||||
return basejson[value], False
|
||||
else:
|
||||
basejson = basejson[value]
|
||||
except KeyError as e:
|
||||
print("[WARNING] Running secondary value check with replacement of underscore in %s: %s" % (value, e))
|
||||
if "_" in value:
|
||||
value = value.replace("_", " ", -1)
|
||||
elif " " in value:
|
||||
value = value.replace(" ", "_", -1)
|
||||
|
||||
if isinstance(basejson, list):
|
||||
print("[WARNING] VALUE IN ISINSTANCE IS NOT TO BE USED (list): %s" % value)
|
||||
return basejson, False
|
||||
elif isinstance(basejson[value], str):
|
||||
print(f"[INFO] LOADING STRING '%s' AS JSON" % basejson[value])
|
||||
try:
|
||||
basejson = json.loads(basejson[value])
|
||||
print("BASEJSON: %s" % basejson)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("RETURNING BECAUSE '%s' IS A NORMAL STRING" % basejson[value])
|
||||
return basejson[value], False
|
||||
else:
|
||||
basejson = basejson[value]
|
||||
|
||||
|
||||
#print("Parsed BASEJSON: %s" % basejson)
|
||||
outercnt += 1
|
||||
|
||||
except KeyError as e:
|
||||
@@ -1240,12 +1376,28 @@ class AppBase:
|
||||
appendresult += char
|
||||
|
||||
actionname_lower = "exec"
|
||||
elif actionname_lower.startswith("shuffle_cache "):
|
||||
actionname_lower = "shuffle_cache"
|
||||
|
||||
actionname_lower = actionname_lower.replace(" ", "_", -1)
|
||||
|
||||
try:
|
||||
if actionname_lower == "exec" or actionname_lower == "webhook" or actionname_lower == "schedule" or actionname_lower == "userinput" or actionname_lower == "email_trigger" or actionname_lower == "trigger":
|
||||
baseresult = execution_data["execution_argument"]
|
||||
elif actionname_lower == "shuffle_cache":
|
||||
print("SHOULD GET CACHE KEY: %s" % parsersplit)
|
||||
if len(parsersplit) > 1:
|
||||
actual_key = parsersplit[1]
|
||||
print("KEY: %s" % actual_key)
|
||||
cachedata = self.get_cache(actual_key)
|
||||
print("CACHE: %s" % cachedata)
|
||||
parsersplit.pop(1)
|
||||
try:
|
||||
baseresult = json.dumps(cachedata)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("Failed json dumping: %s" % e)
|
||||
|
||||
#returndata = str(baseresult)+str(appendresult)
|
||||
else:
|
||||
#print("Within execution data check. Execution data: %s", execution_data["results"])
|
||||
if execution_data["results"] != None:
|
||||
@@ -1302,7 +1454,9 @@ class AppBase:
|
||||
|
||||
print("[INFO] After second return")
|
||||
if len(parsersplit) == 1:
|
||||
return str(baseresult)+str(appendresult), False
|
||||
returndata = str(baseresult)+str(appendresult)
|
||||
print("RETURNING!")#: %s" % returndata)
|
||||
return returndata, False
|
||||
|
||||
baseresult = baseresult.replace(" True,", " true,")
|
||||
baseresult = baseresult.replace(" False", " false,")
|
||||
@@ -1320,9 +1474,17 @@ class AppBase:
|
||||
return str(baseresult)+str(appendresult), False
|
||||
|
||||
print("[INFO] After fourth parser return as JSON")
|
||||
|
||||
data, is_loop = recurse_json(basejson, parsersplit[1:])
|
||||
parseditem = data
|
||||
|
||||
if isinstance(parseditem, dict) or isinstance(parseditem, list):
|
||||
try:
|
||||
parseditem = json.dumps(parseditem)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("Parseditem issue: %s" % e)
|
||||
pass
|
||||
|
||||
print("DATA: (%s) %s" % (type(data), data))
|
||||
if is_loop:
|
||||
print("DATA IS A LOOP - SHOULD WRAP")
|
||||
if parsersplit[-1] == "#":
|
||||
@@ -1333,8 +1495,18 @@ class AppBase:
|
||||
print("SET DATA WRAPPER TO %s!" % parsersplit[-1])
|
||||
parseditem = "${%s%s}$" % (parsersplit[-1], json.dumps(data))
|
||||
|
||||
|
||||
print("Before last return with %s" % appendresult)
|
||||
return str(parseditem)+str(appendresult), is_loop
|
||||
returndata = str(parseditem)+str(appendresult)
|
||||
|
||||
# New in 0.8.97: Don't return items without lists
|
||||
print("RETURNDATA: %s" % returndata)
|
||||
#return returndata, is_loop
|
||||
try:
|
||||
return json.dumps(json.loads(returndata)), is_loop
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("Error in decoder: %s" % e)
|
||||
return returndata, is_loop
|
||||
|
||||
# Parses parameters sent to it and returns whether it did it successfully with the values found
|
||||
def parse_params(action, fullexecution, parameter):
|
||||
@@ -1362,12 +1534,24 @@ class AppBase:
|
||||
continue
|
||||
|
||||
# Handles for loops etc.
|
||||
value, is_loop = get_json_value(fullexecution, to_be_replaced)
|
||||
# FIXME: Should it dump to string here? Doesn't that defeat the purpose?
|
||||
# Trying without string dumping.
|
||||
|
||||
value, is_loop = get_json_value(fullexecution, to_be_replaced)
|
||||
#print("\n\nType of value: %s. Value: %s" % (type(value), value))
|
||||
print("\n\nType of value: %s" % type(value))
|
||||
if isinstance(value, str):
|
||||
parameter["value"] = parameter["value"].replace(to_be_replaced, value)
|
||||
elif isinstance(value, dict):
|
||||
elif isinstance(value, dict) or isinstance(value, list):
|
||||
# Changed from JSON dump to str() 28.05.2021
|
||||
# This makes it so the parameters gets lists and dicts straight up
|
||||
parameter["value"] = parameter["value"].replace(to_be_replaced, json.dumps(value))
|
||||
|
||||
#try:
|
||||
# parameter["value"] = parameter["value"].replace(to_be_replaced, str(value))
|
||||
#except:
|
||||
# parameter["value"] = parameter["value"].replace(to_be_replaced, json.dumps(value))
|
||||
# print("Failed parsing value as string?")
|
||||
else:
|
||||
print("Unknown type %s" % type(value))
|
||||
try:
|
||||
@@ -1375,6 +1559,7 @@ class AppBase:
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
parameter["value"] = parameter["value"].replace(to_be_replaced, value)
|
||||
|
||||
#print("VALUE: %s" % parameter["value"])
|
||||
|
||||
if parameter["variant"] == "WORKFLOW_VARIABLE":
|
||||
print("Handling workflow variable")
|
||||
@@ -1575,16 +1760,15 @@ class AppBase:
|
||||
"matches regex",
|
||||
]
|
||||
|
||||
# FIXME - what should I do here?
|
||||
if not condition["condition"]["value"] in available_checks:
|
||||
self.logger.warning("Skipping %s %s %s because %s is invalid." % (sourcevalue, condition["condition"]["value"], destinationvalue, condition["condition"]["value"]))
|
||||
continue
|
||||
|
||||
#print(destinationvalue)
|
||||
# NEGATE
|
||||
validation = run_validation(sourcevalue, condition["condition"]["value"], destinationvalue)
|
||||
|
||||
# Configuration = negated because of WorkflowAppActionParam..
|
||||
validation = run_validation(sourcevalue, condition["condition"]["value"], destinationvalue)
|
||||
try:
|
||||
if condition["condition"]["configuration"]:
|
||||
validation = not validation
|
||||
@@ -1602,9 +1786,18 @@ class AppBase:
|
||||
return True, ""
|
||||
|
||||
|
||||
|
||||
# THE START IS ACTUALLY RIGHT HERE :O
|
||||
# Checks whether conditions are met, otherwise set
|
||||
branchcheck, tmpresult = check_branch_conditions(action, fullexecution)
|
||||
if isinstance(tmpresult, object) or isinstance(tmpresult, list):
|
||||
print("Fixing branch return as object -> string")
|
||||
try:
|
||||
#tmpresult = tmpresult.replace("'", "\"")
|
||||
tmpresult = json.dumps(tmpresult)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print(f"[WARNING] Failed condition parsing {tmpresult} to string")
|
||||
|
||||
if not branchcheck:
|
||||
self.logger.info("Failed one or more branch conditions.")
|
||||
action_result["result"] = tmpresult
|
||||
@@ -1691,23 +1884,21 @@ class AppBase:
|
||||
if values != None:
|
||||
added = 0
|
||||
for val in values:
|
||||
#print(f"VAL: {val}")
|
||||
#parameter["value"].replace(val["key"], val["value"], -1)
|
||||
#print(f'PARAM1: {action["parameters"][counter]["value"]}')
|
||||
action["parameters"][counter]["value"] = action["parameters"][counter]["value"].replace(val["key"], val["value"], 1)
|
||||
#action["parameters"][counter]["value"].replace(r"${url}", r"$Find_URLs.valid.#.data", 1)
|
||||
#print(f'PARAM2: {action["parameters"][counter]["value"]}')
|
||||
#newparams.append({
|
||||
# "name": val["key"],
|
||||
# "value": val["value"],
|
||||
# "variant": "STATIC_VALUE",
|
||||
# "id": "body_replacement",
|
||||
# "schema": {
|
||||
# "type": "string",
|
||||
# },
|
||||
#})
|
||||
replace_value = val["value"]
|
||||
replace_key = val["key"]
|
||||
if (val["value"].startswith("{") and val["value"].endswith("}")) or (val["value"].startswith("[") and val["value"].endswith("]")):
|
||||
print(f"""Trying to parse as JSON: {val["value"]}""")
|
||||
try:
|
||||
value_replace = json.loads(val["value"])
|
||||
# If it gets here, remove the "" infront and behind the key as well since this is preventing the JSON from being loaded
|
||||
replace_key = f"\"{replace_key}\""
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("Failed JSON replacement for OpenAPI %s", val["key"])
|
||||
elif val["value"].lower() == "true" or val["value"].lower() == "false":
|
||||
replace_key = f"\"{replace_key}\""
|
||||
|
||||
action["parameters"][counter]["value"] = action["parameters"][counter]["value"].replace(replace_key, replace_value, 1)
|
||||
|
||||
#print(f'[INFO] Added param {val["key"]} for body with value {val["value"]} (using OpenAPI)')
|
||||
print(f'[INFO] Added param {val["key"]} for body (using OpenAPI)')
|
||||
added += 1
|
||||
|
||||
@@ -1718,6 +1909,34 @@ class AppBase:
|
||||
print("KeyError body OpenAPI: %s" % e)
|
||||
pass
|
||||
|
||||
try:
|
||||
newvalue = json.loads(action["parameters"][counter]["value"])
|
||||
deletekeys = []
|
||||
for key, value in newvalue.items():
|
||||
if isinstance(value, str) and len(value) == 0:
|
||||
deletekeys.append(key)
|
||||
continue
|
||||
|
||||
for deletekey in deletekeys:
|
||||
del newvalue[deletekey]
|
||||
|
||||
action["parameters"][counter]["value"] = json.dumps(newvalue)
|
||||
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print("Failed JSON replacement for OpenAPI keys (2) {e}")
|
||||
|
||||
#if "\n" in action["parameters"][counter]["value"]:
|
||||
# print("MODIFYING BODY!!")
|
||||
# newbody = ""
|
||||
# for line in action["parameters"][counter]["value"].split("\n"):
|
||||
# if ": \"\"" in line:
|
||||
# print("Skipping line %s" % line)
|
||||
# continue
|
||||
|
||||
# newbody += line
|
||||
|
||||
# print("New body: %s" % newbody)
|
||||
|
||||
break
|
||||
|
||||
#print(action["parameters"])
|
||||
@@ -1802,7 +2021,6 @@ class AppBase:
|
||||
|
||||
print("PRE new_replacement")
|
||||
|
||||
# FIXME: Only do this IF they want to loop
|
||||
new_replacement = []
|
||||
for i in range(len(json_replacement)):
|
||||
if isinstance(json_replacement[i], dict) or isinstance(json_replacement[i], list):
|
||||
@@ -1858,6 +2076,13 @@ class AppBase:
|
||||
params[parameter["name"]] = resultarray
|
||||
multi_parameters[parameter["name"]] = resultarray
|
||||
|
||||
#if len(resultarray) == 0:
|
||||
# print("[WARNING] Returning empty array because the array length to be looped is 0 (1)")
|
||||
# action_result["status"] = "SUCCESS"
|
||||
# action_result["result"] = "[]"
|
||||
# self.send_result(action_result, headers, stream_path)
|
||||
# return
|
||||
|
||||
multi_execution_lists.append(new_replacement)
|
||||
#print("MULTI finished: %s" % json_replacement)
|
||||
else:
|
||||
@@ -1942,6 +2167,13 @@ class AppBase:
|
||||
|
||||
# With this parameter ready, add it to... a greater list of parameters. Rofl
|
||||
print("LENGTH OF ARR: %d" % len(resultarray))
|
||||
if len(resultarray) == 0:
|
||||
print("[WARNING] Returning empty array because the array length to be looped is 0 (0)")
|
||||
action_result["status"] = "SUCCESS"
|
||||
action_result["result"] = "[]"
|
||||
self.send_result(action_result, headers, stream_path)
|
||||
return
|
||||
|
||||
#print("RESULTARRAY: %s" % resultarray)
|
||||
if resultarray not in multi_execution_lists:
|
||||
multi_execution_lists.append(resultarray)
|
||||
@@ -2086,8 +2318,33 @@ class AppBase:
|
||||
return
|
||||
|
||||
print("[INFO] Running normal execution\n")
|
||||
newres = await func(**params)
|
||||
print("\n[INFO] Returned from execution!")#, newres)
|
||||
|
||||
#newres = await func(**params)
|
||||
#print("PARAMS: %s" % params)
|
||||
#newres = ""
|
||||
while True:
|
||||
try:
|
||||
newres = await func(**params)
|
||||
break
|
||||
except TypeError as e:
|
||||
newres = ""
|
||||
errorstring = "%s" % e
|
||||
if "got an unexpected keyword argument" in errorstring:
|
||||
fieldsplit = errorstring.split("'")
|
||||
if len(fieldsplit) > 1:
|
||||
field = fieldsplit[1]
|
||||
|
||||
try:
|
||||
del params[field]
|
||||
print("Removed field invalid field %s" % field)
|
||||
except KeyError:
|
||||
break
|
||||
else:
|
||||
raise e
|
||||
#break
|
||||
|
||||
print("\n[INFO] Returned from execution with types %s" % type(newres))
|
||||
#print("\n[INFO] Returned from execution with %s of types %s" % (newres, type(newres)))#, newres)
|
||||
if isinstance(newres, tuple):
|
||||
print("[INFO] Handling return as tuple")
|
||||
# Handles files.
|
||||
@@ -2328,7 +2585,6 @@ class AppBase:
|
||||
# self.action = cls
|
||||
|
||||
app = cls(redis=None, logger=logger, console_logger=logger)
|
||||
|
||||
if isinstance(action, str):
|
||||
print("Normal execution. Action is a string.")
|
||||
elif isinstance(action, object):
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
### DEFAULT
|
||||
NAME=shuffle-app_sdk
|
||||
VERSION=0.8.64
|
||||
VERSION=0.8.104
|
||||
|
||||
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
||||
docker build . -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||
docker build . -f Dockerfile -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
#docker push frikky/$NAME:$VERSION
|
||||
#docker push docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION
|
||||
@@ -12,3 +15,21 @@ docker build . -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.
|
||||
|
||||
docker push frikky/shuffle:app_sdk
|
||||
docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
docker push ghcr.io/frikky/$NAME:nightly
|
||||
|
||||
#### BLACKARCH ###
|
||||
NAME=shuffle-app_sdk_kali
|
||||
docker build . -f Dockerfile_kali -t frikky/shuffle:app_sdk_kali -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
docker push frikky/shuffle:app_sdk_kali
|
||||
docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
docker push ghcr.io/frikky/$NAME:nightly
|
||||
|
||||
### BLACKARCH ###
|
||||
NAME=shuffle-app_sdk_blackarch
|
||||
docker build . -f Dockerfile_blackarch -t frikky/shuffle:app_sdk_blackarch -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
docker push frikky/shuffle:app_sdk_blackarch
|
||||
docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
docker push ghcr.io/frikky/$NAME:nightly
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
urllib3=1.25.9
|
||||
requests=2.25.1
|
||||
urllib3==1.25.9
|
||||
requests==2.25.1
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
FROM peterclemenko/blackarch as base
|
||||
|
||||
FROM base as builder
|
||||
|
||||
RUN /bin/pacman -Syu --noconfirm
|
||||
|
||||
RUN /bin/pacman -Sy --noconfirm base-devel libffi musl openssl python python-pip -y
|
||||
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
FROM base
|
||||
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY __init__.py /app/walkoff_app_sdk/__init__.py
|
||||
COPY app_base.py /app/walkoff_app_sdk/app_base.py
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Frikkylikeme
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,16 +0,0 @@
|
||||
# app_sdk.py
|
||||
This is the SDK used for apps to behave like they should.
|
||||
To change it in the backend, upload it to Buckets/shuffler.appspot.com/generated_apps/baseline.
|
||||
|
||||
# static_baseline.py
|
||||
It's used for python code generation and should be under MIT. Has to be located here because it's used by the backend.
|
||||
|
||||
## If you want to update apps.. PS: downloads from docker hub do overrides.. :)
|
||||
1. Write your code & check if runtime works
|
||||
2. Build app_base image
|
||||
3. docker rm $(docker ps -aq) # Remove all stopped containers
|
||||
4. Delete the specific app's Docker image (docker rmi frikky/shuffle:...)
|
||||
5. Rebuild the Docker image (click load in GUI?)
|
||||
|
||||
# LICENSE
|
||||
Everything in here is MIT, not AGPLv3 as indicated by the license.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
NAME=app_sdk_blackarch
|
||||
VERSION=0.7.3
|
||||
|
||||
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
||||
docker build . -t frikky/shuffle:$NAME -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
#docker push frikky/$NAME:$VERSION
|
||||
#docker push docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION
|
||||
#docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
docker push frikky/shuffle:$NAME
|
||||
docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
@@ -1,2 +0,0 @@
|
||||
requests
|
||||
urllib3
|
||||
@@ -1,76 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
import requests
|
||||
|
||||
# Goal here:
|
||||
# * Make an app from WALKOFF able to run without app_base.py from WALKOFF
|
||||
# # How:
|
||||
# * Make it rely 100% on INPUT throug HTTP invocations instead of redis READS
|
||||
# # But really, how?
|
||||
# * Make a WORKER that reads the queue, and reuses a function
|
||||
|
||||
# Here to get it global
|
||||
apikey = ""
|
||||
try:
|
||||
apikey = os.environ["FUNCTION_APIKEY"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# Authorize the execution
|
||||
def authorization(request):
|
||||
# This is basically my issue, but it enforces the use of an internal API key for execution
|
||||
try:
|
||||
apikey = os.environ["FUNCTION_APIKEY"]
|
||||
except KeyError:
|
||||
return f"Internal server error", 500
|
||||
|
||||
|
||||
# Check API key from ENV authentication
|
||||
authentication = request.headers.get("Authorization")
|
||||
if authentication == None: return f"Unauthorized", 401
|
||||
|
||||
apikey_split = authentication.split(" ")
|
||||
if apikey_split[0] != "Bearer" or len(apikey_split) != 2:
|
||||
return f"Apikey error", 401
|
||||
|
||||
if apikey != apikey_split[1]:
|
||||
return f"Unauthorized", 401
|
||||
|
||||
return run(request)
|
||||
|
||||
class AppBase:
|
||||
""" The base class for Python-based Walkoff applications, handles Redis and logging configurations. """
|
||||
__version__ = None
|
||||
app_name = None
|
||||
|
||||
def __init__(self, redis=None, logger=None, console_logger=None):#, docker_client=None):
|
||||
self.logger = logger if logger is not None else logging.getLogger("AppBaseLogger")
|
||||
self.redis=redis
|
||||
self.console_logger=console_logger
|
||||
self.current_execution_id = None
|
||||
self.url = "https://shuffler.io"
|
||||
self.apikey = apikey
|
||||
|
||||
@classmethod
|
||||
async def run(cls, action):
|
||||
""" Connect to Redis and HTTP session, await actions """
|
||||
logging.basicConfig(format="{asctime} - {name} - {levelname}:{message}", style='{')
|
||||
logger = logging.getLogger(f"{cls.__name__}")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
app = cls(redis=None, logger=logger, console_logger=logger)
|
||||
|
||||
# Authorization for the app/function to control the workflow
|
||||
# Function will crash if its wrong, which it probably should.
|
||||
|
||||
await app.execute_action(action)
|
||||
|
||||
async def execute_action(self, action):
|
||||
# FIXME - add request for the function STARTING here. Use "results stream" or something
|
||||
# PAUSED, AWAITING_DATA, PENDING, COMPLETED, ABORTED, EXECUTING, SUCCESS, FAILURE
|
||||
|
||||
self.authorization = action["authorization"]
|
||||
self.execution_id = action["execution_id"]
|
||||
self.current_execution_id = action["execution_id"]
|
||||
@@ -1,19 +0,0 @@
|
||||
FROM kalilinux/kali-rolling as base
|
||||
|
||||
FROM base as builder
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get dist-upgrade -y
|
||||
RUN apt install build-essential libffi-dev musl-dev openssl python3 python3-pip -y
|
||||
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
FROM base
|
||||
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY __init__.py /app/walkoff_app_sdk/__init__.py
|
||||
COPY app_base.py /app/walkoff_app_sdk/app_base.py
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Frikkylikeme
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,16 +0,0 @@
|
||||
# app_sdk.py
|
||||
This is the SDK used for apps to behave like they should.
|
||||
To change it in the backend, upload it to Buckets/shuffler.appspot.com/generated_apps/baseline.
|
||||
|
||||
# static_baseline.py
|
||||
It's used for python code generation and should be under MIT. Has to be located here because it's used by the backend.
|
||||
|
||||
## If you want to update apps.. PS: downloads from docker hub do overrides.. :)
|
||||
1. Write your code & check if runtime works
|
||||
2. Build app_base image
|
||||
3. docker rm $(docker ps -aq) # Remove all stopped containers
|
||||
4. Delete the specific app's Docker image (docker rmi frikky/shuffle:...)
|
||||
5. Rebuild the Docker image (click load in GUI?)
|
||||
|
||||
# LICENSE
|
||||
Everything in here is MIT, not AGPLv3 as indicated by the license.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
NAME=app_sdk_kali
|
||||
VERSION=0.7.3
|
||||
|
||||
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
||||
docker build . -t frikky/shuffle:$NAME -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
#docker push frikky/$NAME:$VERSION
|
||||
#docker push docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION
|
||||
#docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
|
||||
docker push frikky/shuffle:$NAME
|
||||
docker push ghcr.io/frikky/$NAME:$VERSION
|
||||
@@ -1,2 +0,0 @@
|
||||
requests
|
||||
urllib3
|
||||
@@ -1,76 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
import requests
|
||||
|
||||
# Goal here:
|
||||
# * Make an app from WALKOFF able to run without app_base.py from WALKOFF
|
||||
# # How:
|
||||
# * Make it rely 100% on INPUT throug HTTP invocations instead of redis READS
|
||||
# # But really, how?
|
||||
# * Make a WORKER that reads the queue, and reuses a function
|
||||
|
||||
# Here to get it global
|
||||
apikey = ""
|
||||
try:
|
||||
apikey = os.environ["FUNCTION_APIKEY"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# Authorize the execution
|
||||
def authorization(request):
|
||||
# This is basically my issue, but it enforces the use of an internal API key for execution
|
||||
try:
|
||||
apikey = os.environ["FUNCTION_APIKEY"]
|
||||
except KeyError:
|
||||
return f"Internal server error", 500
|
||||
|
||||
|
||||
# Check API key from ENV authentication
|
||||
authentication = request.headers.get("Authorization")
|
||||
if authentication == None: return f"Unauthorized", 401
|
||||
|
||||
apikey_split = authentication.split(" ")
|
||||
if apikey_split[0] != "Bearer" or len(apikey_split) != 2:
|
||||
return f"Apikey error", 401
|
||||
|
||||
if apikey != apikey_split[1]:
|
||||
return f"Unauthorized", 401
|
||||
|
||||
return run(request)
|
||||
|
||||
class AppBase:
|
||||
""" The base class for Python-based Walkoff applications, handles Redis and logging configurations. """
|
||||
__version__ = None
|
||||
app_name = None
|
||||
|
||||
def __init__(self, redis=None, logger=None, console_logger=None):#, docker_client=None):
|
||||
self.logger = logger if logger is not None else logging.getLogger("AppBaseLogger")
|
||||
self.redis=redis
|
||||
self.console_logger=console_logger
|
||||
self.current_execution_id = None
|
||||
self.url = "https://shuffler.io"
|
||||
self.apikey = apikey
|
||||
|
||||
@classmethod
|
||||
async def run(cls, action):
|
||||
""" Connect to Redis and HTTP session, await actions """
|
||||
logging.basicConfig(format="{asctime} - {name} - {levelname}:{message}", style='{')
|
||||
logger = logging.getLogger(f"{cls.__name__}")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
app = cls(redis=None, logger=logger, console_logger=logger)
|
||||
|
||||
# Authorization for the app/function to control the workflow
|
||||
# Function will crash if its wrong, which it probably should.
|
||||
|
||||
await app.execute_action(action)
|
||||
|
||||
async def execute_action(self, action):
|
||||
# FIXME - add request for the function STARTING here. Use "results stream" or something
|
||||
# PAUSED, AWAITING_DATA, PENDING, COMPLETED, ABORTED, EXECUTING, SUCCESS, FAILURE
|
||||
|
||||
self.authorization = action["authorization"]
|
||||
self.execution_id = action["execution_id"]
|
||||
self.current_execution_id = action["execution_id"]
|
||||
+153
-251
@@ -5,20 +5,24 @@ import (
|
||||
"github.com/frikky/shuffle-shared"
|
||||
|
||||
"archive/tar"
|
||||
//"bufio"
|
||||
"path/filepath"
|
||||
//"strconv"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
//"github.com/docker/docker"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
//"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
newdockerclient "github.com/fsouza/go-dockerclient"
|
||||
"github.com/go-git/go-billy/v5"
|
||||
|
||||
network "github.com/docker/docker/api/types/network"
|
||||
natting "github.com/docker/go-connections/nat"
|
||||
//network "github.com/docker/docker/api/types/network"
|
||||
//natting "github.com/docker/go-connections/nat"
|
||||
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -214,11 +218,28 @@ func buildImageMemory(fs billy.Filesystem, tags []string, dockerfileFolder strin
|
||||
|
||||
// Dockerfile is inside the TAR itself. Not local context
|
||||
// docker build --build-arg http_proxy=http://my.proxy.url
|
||||
// Attempt at setting name according to #359: https://github.com/frikky/Shuffle/issues/359
|
||||
labels := map[string]string{}
|
||||
target := ""
|
||||
if len(tags) > 0 {
|
||||
if strings.Contains(tags[0], ":") {
|
||||
version := strings.Split(tags[0], ":")
|
||||
if len(version) == 2 {
|
||||
target = fmt.Sprintf("shuffle-build-%s", version[1])
|
||||
tags = append(tags, target)
|
||||
labels["name"] = target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = labels
|
||||
buildOptions := types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
Tags: tags,
|
||||
BuildArgs: map[string]*string{},
|
||||
Labels: labels,
|
||||
}
|
||||
|
||||
// NetworkMode: "host",
|
||||
|
||||
httpProxy := os.Getenv("HTTP_PROXY")
|
||||
@@ -231,13 +252,14 @@ func buildImageMemory(fs billy.Filesystem, tags []string, dockerfileFolder strin
|
||||
}
|
||||
|
||||
// Build the actual image
|
||||
log.Printf("[INFO] Building %s. This may take up to a few minutes.", dockerfileFolder)
|
||||
log.Printf(`[INFO] Building %s with proxy "%s". Tags: "%s". This may take up to a few minutes.`, dockerfileFolder, httpsProxy, strings.Join(tags, ","))
|
||||
imageBuildResponse, err := client.ImageBuild(
|
||||
ctx,
|
||||
dockerFileTarReader,
|
||||
buildOptions,
|
||||
)
|
||||
|
||||
//log.Printf("RESPONSE: %#v", imageBuildResponse)
|
||||
//log.Printf("Response: %#v", imageBuildResponse.Body)
|
||||
//log.Printf("IMAGERESPONSE: %#v", imageBuildResponse.Body)
|
||||
|
||||
@@ -391,89 +413,6 @@ func stopWebhook(image string, identifier string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME - remember to set DOCKER_API_VERSION
|
||||
// FIXME - remove github.com/docker/docker/vendor
|
||||
// FIXME - Library dependencies for NAT is fucked..
|
||||
// https://docs.docker.com/develop/sdk/examples/
|
||||
func deployWebhook(image string, identifier string, path string, port string, callbackurl string, apikey string) error {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
fmt.Println("Unable to create docker client")
|
||||
return err
|
||||
}
|
||||
|
||||
newport, err := natting.NewPort("tcp", port)
|
||||
if err != nil {
|
||||
fmt.Println("Unable to create docker port")
|
||||
return err
|
||||
}
|
||||
|
||||
// FIXME - logging?
|
||||
|
||||
hostConfig := &container.HostConfig{
|
||||
PortBindings: natting.PortMap{
|
||||
newport: []natting.PortBinding{
|
||||
{
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: port,
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: container.RestartPolicy{
|
||||
Name: "always",
|
||||
},
|
||||
LogConfig: container.LogConfig{
|
||||
Type: "json-file",
|
||||
Config: map[string]string{},
|
||||
},
|
||||
}
|
||||
|
||||
//networkConfig := &network.NetworkSettings{}
|
||||
networkConfig := &network.NetworkingConfig{
|
||||
EndpointsConfig: map[string]*network.EndpointSettings{},
|
||||
}
|
||||
|
||||
test := &network.EndpointSettings{
|
||||
Gateway: "helo",
|
||||
}
|
||||
|
||||
networkConfig.EndpointsConfig["bridge"] = test
|
||||
|
||||
exposedPorts := map[natting.Port]struct{}{
|
||||
newport: struct{}{},
|
||||
}
|
||||
|
||||
config := &container.Config{
|
||||
Image: image,
|
||||
Env: []string{
|
||||
fmt.Sprintf("URIPATH=%s", path),
|
||||
fmt.Sprintf("HOOKPORT=%s", port),
|
||||
fmt.Sprintf("CALLBACKURL=%s", callbackurl),
|
||||
fmt.Sprintf("APIKEY=%s", apikey),
|
||||
fmt.Sprintf("HOOKID=%s", identifier),
|
||||
},
|
||||
ExposedPorts: exposedPorts,
|
||||
Hostname: fmt.Sprintf("%s-%s", image, identifier),
|
||||
}
|
||||
|
||||
cont, err := cli.ContainerCreate(
|
||||
context.Background(),
|
||||
config,
|
||||
hostConfig,
|
||||
networkConfig,
|
||||
fmt.Sprintf("%s-%s", image, identifier),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
|
||||
log.Printf("Container %s is created", cont.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Starts a new webhook
|
||||
func handleStopHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
@@ -501,7 +440,7 @@ func handleStopHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
hook, err := getHook(ctx, fileId)
|
||||
hook, err := shuffle.GetHook(ctx, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting hook %s (stop docker): %s", fileId, err)
|
||||
resp.WriteHeader(401)
|
||||
@@ -521,8 +460,8 @@ func handleStopHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
hook.Status = "stopped"
|
||||
hook.Running = false
|
||||
hook.Actions = []HookAction{}
|
||||
err = setHook(ctx, *hook)
|
||||
hook.Actions = []shuffle.HookAction{}
|
||||
err = shuffle.SetHook(ctx, *hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting hook: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
@@ -585,7 +524,7 @@ func handleDeleteHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err := DeleteKey(ctx, "hooks", fileId)
|
||||
err := shuffle.DeleteKey(ctx, "hooks", fileId)
|
||||
if err != nil {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "message": "Can't delete"}`))
|
||||
@@ -606,121 +545,6 @@ func handleDeleteHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
resp.Write([]byte(`{"success": true, "message": "Deleted webhook"}`))
|
||||
}
|
||||
|
||||
// Starts a new webhook
|
||||
func handleStartHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
location := strings.Split(request.URL.String(), "/")
|
||||
|
||||
var fileId string
|
||||
if location[1] == "api" {
|
||||
if len(location) <= 4 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
fileId = location[4]
|
||||
}
|
||||
|
||||
if len(fileId) != 32 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "message": "ID not valid"}`))
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
hook, err := getHook(ctx, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting hook %s (start docker): %s", fileId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
if len(hook.Info.Url) == 0 {
|
||||
log.Printf("Hook url can't be empty.")
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Status: %s", hook.Status)
|
||||
log.Printf("Running: %t", hook.Running)
|
||||
if hook.Running || hook.Status == "Running" {
|
||||
message := fmt.Sprintf("Error: %s is already running", hook.Id)
|
||||
log.Println(message)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "%s"}`, message)))
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME - verify?
|
||||
// FIXME - static port? Generate from available range.
|
||||
image := "webhook"
|
||||
filepath := "/webhook"
|
||||
baseUrl := "http://localhost"
|
||||
callbackUrl := "http://localhost:8001"
|
||||
|
||||
// This is here to force stop and remove the old webhook
|
||||
err = stopWebhook(image, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Container stop issue for %s-%s: %s", image, fileId, err)
|
||||
}
|
||||
|
||||
// Dynamic ish ports
|
||||
var startPort int64 = 5001
|
||||
var endPort int64 = 5010
|
||||
port := findAvailablePorts(startPort, endPort)
|
||||
if len(port) == 0 {
|
||||
message := fmt.Sprintf("Not ports available in the range %d-%d", startPort, endPort)
|
||||
log.Println(message)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "%s"}`, message)))
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
hook.Status = "running"
|
||||
hook.Running = true
|
||||
|
||||
// Set this for more than just hooks?
|
||||
if hook.Type == "webhook" {
|
||||
hook.Info.Url = fmt.Sprintf("%s:%s%s", baseUrl, port, filepath)
|
||||
}
|
||||
err = setHook(ctx, *hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting hook: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Cloud run? Let's make a generic webhook that can be deployed easily
|
||||
log.Printf("Should run a webhook with the following: \nUrl: %s\nId: %s\n", hook.Info.Url, hook.Id)
|
||||
|
||||
// FIXME - set port based on what the user specified / what was generated
|
||||
// FIXME - add nonstatic APIKEY
|
||||
apiKey := "ASD"
|
||||
|
||||
err = deployWebhook(image, fileId, filepath, port, callbackUrl, apiKey)
|
||||
if err != nil {
|
||||
log.Printf("Failed starting container %s-%s: %s", image, fileId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME - get some real data?
|
||||
log.Printf("[INFO] Successfully started %s-%s on port %s with filepath %s", image, fileId, port, filepath)
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true, "message": "Started webhook"}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Checks if an image exists
|
||||
func imageCheckBuilder(images []string) error {
|
||||
//log.Printf("[FIXME] ImageNames to check: %#v", images)
|
||||
@@ -767,7 +591,7 @@ func imageCheckBuilder(images []string) error {
|
||||
}
|
||||
|
||||
func hookTest() {
|
||||
var hook Hook
|
||||
var hook shuffle.Hook
|
||||
err := json.Unmarshal([]byte(webhook), &hook)
|
||||
log.Println(webhook)
|
||||
if err != nil {
|
||||
@@ -776,12 +600,12 @@ func hookTest() {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err = setHook(ctx, hook)
|
||||
err = shuffle.SetHook(ctx, hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting hook: %s", err)
|
||||
}
|
||||
|
||||
returnHook, err := getHook(ctx, hook.Id)
|
||||
returnHook, err := shuffle.GetHook(ctx, hook.Id)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting hook %s (test): %s", hook.Id, err)
|
||||
}
|
||||
@@ -799,13 +623,13 @@ func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
// Just here to verify that the user is logged in
|
||||
_, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
if err != nil {
|
||||
log.Printf("Api authentication failed in validate swagger: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
//_, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
//if err != nil {
|
||||
// log.Printf("[WARNING] Api authentication failed in DOWNLOAD IMAGE: %s", err)
|
||||
// resp.WriteHeader(401)
|
||||
// resp.Write([]byte(`{"success": false}`))
|
||||
// return
|
||||
//}
|
||||
|
||||
body, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
@@ -818,16 +642,6 @@ func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||
Name string `datastore:"name" json:"name" yaml:"name"`
|
||||
}
|
||||
|
||||
//body = []byte(`swagger: "2.0"`)
|
||||
//body = []byte(`swagger: '1.0'`)
|
||||
//newbody := string(body)
|
||||
//newbody = strings.TrimSpace(newbody)
|
||||
//body = []byte(newbody)
|
||||
//log.Println(string(body))
|
||||
//tmpbody, err := yaml.YAMLToJSON(body)
|
||||
//log.Println(err)
|
||||
//log.Println(string(tmpbody))
|
||||
|
||||
// This has to be done in a weird way because Datastore doesn't
|
||||
// support map[string]interface and similar (openapi3.Swagger)
|
||||
var version requestCheck
|
||||
@@ -839,16 +653,10 @@ func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Image to load: %s", version.Name)
|
||||
//cli, err := client.NewEnvClient()
|
||||
//if err != nil {
|
||||
// log.Println("Unable to create docker client")
|
||||
// return err
|
||||
//}
|
||||
|
||||
log.Printf("[DEBUG] Image to load: %s", version.Name)
|
||||
dockercli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
log.Printf("Unable to create docker client: %s", err)
|
||||
log.Printf("[WARNING] Unable to create docker client: %s", err)
|
||||
resp.WriteHeader(422)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed JSON marshalling: %s"}`, err)))
|
||||
return
|
||||
@@ -861,37 +669,131 @@ func getDockerImage(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
img := types.ImageSummary{}
|
||||
tagFound := ""
|
||||
|
||||
img2 := types.ImageSummary{}
|
||||
tagFound2 := ""
|
||||
|
||||
alternativeNameSplit := strings.Split(version.Name, "/")
|
||||
alternativeName := version.Name
|
||||
if len(alternativeNameSplit) == 3 {
|
||||
alternativeName = strings.Join(alternativeNameSplit[1:3], "/")
|
||||
}
|
||||
|
||||
for _, image := range images {
|
||||
for _, tag := range image.RepoTags {
|
||||
log.Printf("[INFO] Docker Image: %s", tag)
|
||||
|
||||
if strings.ToLower(tag) == strings.ToLower(version.Name) {
|
||||
img = image
|
||||
tagFound = tag
|
||||
break
|
||||
}
|
||||
|
||||
if strings.ToLower(tag) == strings.ToLower(alternativeName) {
|
||||
img2 = image
|
||||
tagFound2 = tag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// REBUILDS THE APP
|
||||
if len(img.ID) == 0 {
|
||||
if len(img2.ID) == 0 {
|
||||
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 0)
|
||||
log.Printf("[INFO] Getting workflowapps for a rebuild. Got %d with err %#v", len(workflowapps), err)
|
||||
if err == nil {
|
||||
imageName := ""
|
||||
imageVersion := ""
|
||||
newNameSplit := strings.Split(version.Name, ":")
|
||||
if len(newNameSplit) == 2 {
|
||||
log.Printf("[DEBUG] Found name %#v", newNameSplit)
|
||||
|
||||
findVersionSplit := strings.Split(newNameSplit[1], "_")
|
||||
log.Printf("[DEBUG] Found another split %#v", findVersionSplit)
|
||||
if len(findVersionSplit) == 2 {
|
||||
imageVersion = findVersionSplit[len(findVersionSplit)-1]
|
||||
imageName = findVersionSplit[0]
|
||||
} else if len(findVersionSplit) >= 2 {
|
||||
imageVersion = findVersionSplit[len(findVersionSplit)-1]
|
||||
imageName = strings.Join(findVersionSplit[0:len(findVersionSplit)-1], "_")
|
||||
} else {
|
||||
log.Printf("[DEBUG] Couldn't parse appname & version for %#v", findVersionSplit)
|
||||
}
|
||||
}
|
||||
|
||||
if len(imageName) > 0 && len(imageVersion) > 0 {
|
||||
foundApp := shuffle.WorkflowApp{}
|
||||
imageName = strings.ToLower(imageName)
|
||||
imageVersion = strings.ToLower(imageVersion)
|
||||
log.Printf("[DEBUG] Looking for appname %s with version %s", imageName, imageVersion)
|
||||
|
||||
for _, app := range workflowapps {
|
||||
if strings.ToLower(strings.Replace(app.Name, " ", "_", -1)) == imageName && app.AppVersion == imageVersion {
|
||||
if app.Generated {
|
||||
log.Printf("[DEBUG] Found matching app %s:%s - %s", imageName, imageVersion, app.ID)
|
||||
foundApp = app
|
||||
break
|
||||
} else {
|
||||
log.Printf("[WARNING] Trying to rebuild app that isn't generated - not allowed. Looking further.")
|
||||
}
|
||||
|
||||
//break
|
||||
}
|
||||
}
|
||||
|
||||
if len(foundApp.ID) > 0 {
|
||||
openApiApp, err := shuffle.GetOpenApiDatastore(ctx, foundApp.ID)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed getting OpenAPI app %s to database: %s", foundApp.ID, err)
|
||||
} else {
|
||||
log.Printf("[DEBUG] Found OpenAPI app for %s as generated - now building!", version.Name)
|
||||
user := shuffle.User{}
|
||||
|
||||
//img = version.Name
|
||||
if len(alternativeName) > 0 {
|
||||
tagFound = alternativeName
|
||||
} else {
|
||||
tagFound = version.Name
|
||||
}
|
||||
|
||||
buildSwaggerApp(resp, []byte(openApiApp.Body), user)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("[WARNING] Couldn't find an image with registry name %s and %s", version.Name, alternativeName)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "Couldn't find image %s"}`, version.Name)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(tagFound) == 0 && len(tagFound2) > 0 {
|
||||
img = img2
|
||||
tagFound = tagFound2
|
||||
}
|
||||
}
|
||||
|
||||
//log.Printf("[INFO] Img found (%s): %#v", tagFound, img)
|
||||
log.Printf("[INFO] Img found to be downloaded by client: %s", tagFound)
|
||||
|
||||
newClient, err := newdockerclient.NewClientFromEnv()
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed setting up docker env: %s", newClient)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "Couldn't find image %s"}`, version.Name)))
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "Couldn't make docker client"}`)))
|
||||
return
|
||||
}
|
||||
_ = tagFound
|
||||
|
||||
/*
|
||||
log.Printf("IMg: %#v", img)
|
||||
pullOptions := types.ImagePullOptions{}
|
||||
log.Printf("[INFO] Pulling image %s", image)
|
||||
reader, err := dockercli.ImagePull(ctx, tag, pullOptions)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed getting image %s: %s", image, err)
|
||||
}
|
||||
////https://github.com/fsouza/go-dockerclient/issues/600
|
||||
//defer fileReader.Close()
|
||||
opts := newdockerclient.ExportImageOptions{
|
||||
Name: tagFound,
|
||||
OutputStream: resp,
|
||||
}
|
||||
|
||||
io.Copy(os.Stdout, r)
|
||||
*/
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "message": "Downloading image %s"}`, version.Name)))
|
||||
if err := newClient.ExportImage(opts); err != nil {
|
||||
log.Printf("[WARNING] FAILED to save image to file: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "Couldn't export image"}`)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
+11
-6
@@ -2,7 +2,8 @@ module shuffle
|
||||
|
||||
go 1.13
|
||||
|
||||
//replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||
replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||
|
||||
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
|
||||
|
||||
require (
|
||||
@@ -10,15 +11,19 @@ require (
|
||||
cloud.google.com/go/datastore v1.4.0
|
||||
cloud.google.com/go/pubsub v1.3.1
|
||||
cloud.google.com/go/storage v1.12.0
|
||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/algolia/algoliasearch-client-go/v3 v3.18.1 // indirect
|
||||
github.com/basgys/goxml2json v1.1.0
|
||||
github.com/frikky/kin-openapi v0.38.0
|
||||
github.com/bradfitz/slice v0.0.0-20180809154707-2b758aa73013 // indirect
|
||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v1.13.1
|
||||
github.com/docker/docker v20.10.3-0.20210216175712-646072ed6524+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/frikky/shuffle-shared v0.0.23
|
||||
github.com/elastic/go-elasticsearch/v7 v7.13.1 // indirect
|
||||
github.com/frikky/kin-openapi v0.39.0
|
||||
github.com/frikky/shuffle-shared v0.0.69
|
||||
github.com/fsouza/go-dockerclient v1.7.2
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-git/go-billy/v5 v5.0.0
|
||||
github.com/go-git/go-git/v5 v5.0.0
|
||||
@@ -26,9 +31,9 @@ require (
|
||||
github.com/gorilla/handlers v1.4.2 // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/h2non/filetype v1.0.12
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
golang.org/x/oauth2 v0.0.0-20210113160501-8b1d76fa0423
|
||||
google.golang.org/api v0.36.0
|
||||
|
||||
@@ -1,604 +0,0 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.66.0/go.mod h1:dgqGAjKCDxyhGTtC9dAREQGUJpkceNm1yt590Qno0Ko=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.75.0 h1:XgtDnVJRCPEUG21gjFiRPz4zI1Mjg16R+NYQjfmU4XY=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.6.0/go.mod h1:hyFDG0qSGdHNz8Q6nDN8rYIkld0q/+5uBZaelxiDLfE=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/datastore v1.4.0 h1:CFDJm15RpYXeEblQ0TMDUrYtqmBmbAWTy536nA8JIc8=
|
||||
cloud.google.com/go/datastore v1.4.0/go.mod h1:d18825/a9bICdAIJy2EkHs9joU4RlIZ1t6l8WDdbdY0=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.7.0 h1:DzdLPI8Em+DEk7IzA2a10ivq3mxIEASC9GeNJ6FFt5Q=
|
||||
cloud.google.com/go/storage v1.7.0/go.mod h1:jGMIBwF+L/tL6WN/W5InNgYYu4HP0DvGB6rQ1mufWfs=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.12.0 h1:4y3gHptW1EHVtcPAVE0eBBlFuGqEejTTG3KdIE0lUX4=
|
||||
cloud.google.com/go/storage v1.12.0/go.mod h1:fFLk2dp2oAhDz8QFKwqrjdJvxSp/W2g7nillojlL5Ho=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
|
||||
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
|
||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82 h1:9bAydALqAjBfPHd/eAiJBHnMZUYov8m2PkXVr+YGQeI=
|
||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82/go.mod h1:tyA14J0sA3Hph4dt+AfCjPrYR13+vVodshQSM7km9qw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
|
||||
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/frikky/kin-openapi v0.38.0 h1:V7ttwIJS8Vks4KL+mZVj1ZSqhIcQtgaG8akeqXEQgsE=
|
||||
github.com/frikky/kin-openapi v0.38.0/go.mod h1:Fr28TtCHL4K0kIqtqui8HWxN1LG5uAh3z/tDfFyiA1s=
|
||||
github.com/frikky/shuffle-shared v0.0.12 h1:+0EIfThmK47Po+LogPYZR4XjbS4Ds19WNMFu2YUSjhw=
|
||||
github.com/frikky/shuffle-shared v0.0.12/go.mod h1:SEY432/xs4oBkOUnGwxiYKCZWZLRaheGInhAoW7N8ww=
|
||||
github.com/frikky/shuffle-shared v0.0.15 h1:508ceeEHfPBMCC8/K4Zve3kwRQqiXNJSw6+BDoq9X4E=
|
||||
github.com/frikky/shuffle-shared v0.0.15/go.mod h1:SEY432/xs4oBkOUnGwxiYKCZWZLRaheGInhAoW7N8ww=
|
||||
github.com/frikky/shuffle-shared v0.0.20 h1:y6JlPnQDq//elICWvVfUfJyU9gH3fSpQmPy+agqZ5sA=
|
||||
github.com/frikky/shuffle-shared v0.0.20/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/frikky/shuffle-shared v0.0.21 h1:xj/XPsXTa2rx41mm4nUc7+2K9RGkq2/mpjSPtIfpjE4=
|
||||
github.com/frikky/shuffle-shared v0.0.21/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/frikky/shuffle-shared v0.0.22 h1:TFMcJCNmOOSneMMWbg5dNzp2z6m0aZLROuL+bzVToRE=
|
||||
github.com/frikky/shuffle-shared v0.0.22/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/frikky/shuffle-shared v0.0.23 h1:Pnlc2M6fHnFRLFd5K1iLTVv4/t4P04Ri1GJ5CMxzq0U=
|
||||
github.com/frikky/shuffle-shared v0.0.23/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/getkin/kin-openapi v0.8.0 h1:a6TQjTqwkyscC4/hShJX7WhCVE+4bi9lzw61XHQW5hE=
|
||||
github.com/getkin/kin-openapi v0.8.0/go.mod h1:zZQMFkVgRHCdhgb6ihCTIo9dyDZFvX0k/xAKqw1FhPw=
|
||||
github.com/getkin/kin-openapi v0.52.0 h1:6WqsF5d6PfJ8AscdD+9Rtb2RP2iBWyC7V6GcjssWg7M=
|
||||
github.com/getkin/kin-openapi v0.52.0/go.mod h1:fRpo2Nw4Czgy0QnrIesRrEXs5+15N1F9mGZLP/aIomE=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy v4.2.0+incompatible h1:Z6QtVXd5tjxUtcODLugkJg4WaZnGg13CD8qB9pr+7q0=
|
||||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
||||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git v4.7.0+incompatible h1:+W9rgGY4DOKKdX2x6HxSR7HNeTxqiKrOvKnuittYVdA=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
||||
github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg=
|
||||
github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/h2non/filetype v1.0.12 h1:yHCsIe0y2cvbDARtJhGBTD2ecvqMSTvlIcph9En/Zao=
|
||||
github.com/h2non/filetype v1.0.12/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210113160501-8b1d76fa0423 h1:/hEknzWkMPCjTo7StMHRrBRa8YBbXuBWfck8680k3RE=
|
||||
golang.org/x/oauth2 v0.0.0-20210113160501-8b1d76fa0423/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e h1:hq86ru83GdWTlfQFZGO4nZJTU4Bs2wfHl8oFHRaXsfc=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200409170454-77362c5149f0/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d h1:lzLdP95xJmMpwQ6LUHwrc5V7js93hTiY7gkznu0BgmY=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.23.0 h1:YlvGEOq2NA2my8cZ/9V8BcEO9okD48FlJcdqN0xJL3s=
|
||||
google.golang.org/api v0.23.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo=
|
||||
google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0 h1:l2Nfbl2GPXdWorv+dT2XfinX2jOOw4zv1VhLstx+6rE=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200409111301-baae70f3302d/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 h1:Bz1qTn2YRWV+9OKJtxHJiQKCiXIdf+kwuKXdt9cBxyU=
|
||||
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200921151605-7abf4a1a14d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210113195801-ae06605f4595 h1:x7nk+/4+SvuTDI4wnzQUlhvi+DTpyfncXBo3QWTFs7U=
|
||||
google.golang.org/genproto v0.0.0-20210113195801-ae06605f4595/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.34.1 h1:ugq+9++ZQPFzM2pKUMCIK8gj9M0pFyuUWO9Q8kwEDQw=
|
||||
google.golang.org/grpc v1.34.1/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 h1:OfFoIUYv/me30yv7XlMy4F9RJw8DEm8WQ6QG1Ph4bH0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
+1073
-1450
File diff suppressed because it is too large
Load Diff
+242
-538
@@ -15,160 +15,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/datastore"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// This is what the structure should be when it's sent into a workflow
|
||||
type ParsedShuffleMail struct {
|
||||
Body struct {
|
||||
URI []string `json:"uri"`
|
||||
Email []string `json:"email"`
|
||||
Domain []string `json:"domain"`
|
||||
ContentHeader struct {
|
||||
} `json:"content_header"`
|
||||
Content string `json:"content"`
|
||||
ContentType string `json:"content_type"`
|
||||
Hash string `json:"hash"`
|
||||
RawBody string `json:"raw_body"`
|
||||
} `json:"body"`
|
||||
Header struct {
|
||||
Subject string `json:"subject"`
|
||||
From string `json:"from"`
|
||||
To []string `json:"to"`
|
||||
Date string `json:"date"`
|
||||
Received []struct {
|
||||
Src string `json:"src"`
|
||||
From []string `json:"from"`
|
||||
By []string `json:"by"`
|
||||
With string `json:"with"`
|
||||
Date string `json:"date"`
|
||||
} `json:"received"`
|
||||
ReceivedDomain []string `json:"received_domain"`
|
||||
ReceivedIP []string `json:"received_ip"`
|
||||
Header struct {
|
||||
} `json:"header"`
|
||||
} `json:"header"`
|
||||
MessageID string `json:"message_id"`
|
||||
EmailFileid string `json:"email_fileid"`
|
||||
AttachmentUids []string `json:"attachment_uids"`
|
||||
}
|
||||
|
||||
type FullEmail struct {
|
||||
OdataContext string `json:"@odata.context"`
|
||||
OdataEtag string `json:"@odata.etag"`
|
||||
ID string `json:"id"`
|
||||
Createddatetime time.Time `json:"createdDateTime"`
|
||||
Lastmodifieddatetime time.Time `json:"lastModifiedDateTime"`
|
||||
Changekey string `json:"changeKey"`
|
||||
Categories []interface{} `json:"categories"`
|
||||
Receiveddatetime time.Time `json:"receivedDateTime"`
|
||||
Sentdatetime time.Time `json:"sentDateTime"`
|
||||
Hasattachments bool `json:"hasAttachments"`
|
||||
Internetmessageid string `json:"internetMessageId"`
|
||||
Subject string `json:"subject"`
|
||||
Bodypreview string `json:"bodyPreview"`
|
||||
Importance string `json:"importance"`
|
||||
Parentfolderid string `json:"parentFolderId"`
|
||||
Conversationid string `json:"conversationId"`
|
||||
Conversationindex string `json:"conversationIndex"`
|
||||
Isdeliveryreceiptrequested interface{} `json:"isDeliveryReceiptRequested"`
|
||||
Isreadreceiptrequested bool `json:"isReadReceiptRequested"`
|
||||
Isread bool `json:"isRead"`
|
||||
Isdraft bool `json:"isDraft"`
|
||||
Weblink string `json:"webLink"`
|
||||
Inferenceclassification string `json:"inferenceClassification"`
|
||||
Body struct {
|
||||
Contenttype string `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
} `json:"body"`
|
||||
Sender struct {
|
||||
Emailaddress struct {
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
} `json:"emailAddress"`
|
||||
} `json:"sender"`
|
||||
From struct {
|
||||
Emailaddress struct {
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
} `json:"emailAddress"`
|
||||
} `json:"from"`
|
||||
Torecipients []struct {
|
||||
Emailaddress struct {
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
} `json:"emailAddress"`
|
||||
} `json:"toRecipients"`
|
||||
Ccrecipients []interface{} `json:"ccRecipients"`
|
||||
Bccrecipients []interface{} `json:"bccRecipients"`
|
||||
Replyto []interface{} `json:"replyTo"`
|
||||
Flag struct {
|
||||
Flagstatus string `json:"flagStatus"`
|
||||
} `json:"flag"`
|
||||
Attachments []struct {
|
||||
OdataType string `json:"@odata.type"`
|
||||
OdataMediacontenttype string `json:"@odata.mediaContentType"`
|
||||
ID string `json:"id"`
|
||||
Lastmodifieddatetime time.Time `json:"lastModifiedDateTime"`
|
||||
Name string `json:"name"`
|
||||
Contenttype string `json:"contentType"`
|
||||
Size int `json:"size"`
|
||||
Isinline bool `json:"isInline"`
|
||||
Contentid interface{} `json:"contentId"`
|
||||
Contentlocation interface{} `json:"contentLocation"`
|
||||
Contentbytes string `json:"contentBytes"`
|
||||
}
|
||||
}
|
||||
|
||||
type MailData struct {
|
||||
Value []struct {
|
||||
Subscriptionid string `json:"subscriptionId"`
|
||||
Subscriptionexpirationdatetime string `json:"subscriptionExpirationDateTime"`
|
||||
Changetype string `json:"changeType"`
|
||||
Resource string `json:"resource"`
|
||||
Resourcedata struct {
|
||||
OdataType string `json:"@odata.type"`
|
||||
OdataID string `json:"@odata.id"`
|
||||
OdataEtag string `json:"@odata.etag"`
|
||||
ID string `json:"id"`
|
||||
} `json:"resourceData"`
|
||||
Clientstate string `json:"clientState"`
|
||||
Tenantid string `json:"tenantId"`
|
||||
} `json:"value"`
|
||||
}
|
||||
|
||||
type OutlookProfile struct {
|
||||
OdataContext string `json:"@odata.context"`
|
||||
BusinessPhones []string `json:"businessPhones"`
|
||||
DisplayName string `json:"displayName"`
|
||||
GivenName string `json:"givenName"`
|
||||
JobTitle interface{} `json:"jobTitle"`
|
||||
Mail string `json:"mail"`
|
||||
MobilePhone interface{} `json:"mobilePhone"`
|
||||
OfficeLocation interface{} `json:"officeLocation"`
|
||||
PreferredLanguage interface{} `json:"preferredLanguage"`
|
||||
Surname string `json:"surname"`
|
||||
UserPrincipalName string `json:"userPrincipalName"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type OutlookFolder struct {
|
||||
ID string `json:"id"`
|
||||
DisplayName string `json:"displayName"`
|
||||
ParentFolderID string `json:"parentFolderId"`
|
||||
ChildFolderCount int `json:"childFolderCount"`
|
||||
UnreadItemCount int `json:"unreadItemCount"`
|
||||
TotalItemCount int `json:"totalItemCount"`
|
||||
}
|
||||
|
||||
type OutlookFolders struct {
|
||||
OdataContext string `json:"@odata.context"`
|
||||
OdataNextLink string `json:"@odata.nextLink"`
|
||||
Value []OutlookFolder `json:"value"`
|
||||
}
|
||||
|
||||
func getOutlookAttachment(client *http.Client, emailId, attachmentId string) ([]FullEmail, error) {
|
||||
func getOutlookAttachment(client *http.Client, emailId, attachmentId string) ([]shuffle.FullEmail, error) {
|
||||
//requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/ec03b4f2-fccf-4c35-b0eb-be85a0f5dd43/mailFolders")
|
||||
|
||||
requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/%s/attachments/%s", emailId, attachmentId)
|
||||
@@ -177,20 +27,20 @@ func getOutlookAttachment(client *http.Client, emailId, attachmentId string) ([]
|
||||
ret, err := client.Get(requestUrl)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] OutlookErr: %s", err)
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(ret.Body)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed body decoding from outlook email")
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
//type FullEmail struct {
|
||||
log.Printf("[INFO] Attachment Body: %s", string(body))
|
||||
log.Printf("[INFO] Status email: %d", ret.StatusCode)
|
||||
if ret.StatusCode != 200 {
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
//log.Printf("Body: %s", string(body))
|
||||
@@ -206,13 +56,13 @@ func getOutlookAttachment(client *http.Client, emailId, attachmentId string) ([]
|
||||
emails = append(emails, parsedmail)
|
||||
*/
|
||||
|
||||
return []FullEmail{}, nil
|
||||
return []shuffle.FullEmail{}, nil
|
||||
}
|
||||
|
||||
func getOutlookEmail(client *http.Client, maildata MailData) ([]FullEmail, error) {
|
||||
func getOutlookEmail(client *http.Client, maildata shuffle.MailData) ([]shuffle.FullEmail, error) {
|
||||
//requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/ec03b4f2-fccf-4c35-b0eb-be85a0f5dd43/mailFolders")
|
||||
|
||||
emails := []FullEmail{}
|
||||
emails := []shuffle.FullEmail{}
|
||||
for _, email := range maildata.Value {
|
||||
//messageId := email.Resourcedata.ID
|
||||
//requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/me/%s", messageId)
|
||||
@@ -222,29 +72,29 @@ func getOutlookEmail(client *http.Client, maildata MailData) ([]FullEmail, error
|
||||
ret, err := client.Get(requestUrl)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] OutlookErr: %s", err)
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(ret.Body)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed body decoding from outlook email")
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
//type FullEmail struct {
|
||||
//type shuffle.FullEmail struct {
|
||||
//log.Printf("[INFO] EMAIL Body: %s", string(body))
|
||||
//log.Printf("[INFO] Status email: %d", ret.StatusCode)
|
||||
if ret.StatusCode != 200 {
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
//log.Printf("Body: %s", string(body))
|
||||
|
||||
parsedmail := FullEmail{}
|
||||
parsedmail := shuffle.FullEmail{}
|
||||
err = json.Unmarshal(body, &parsedmail)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Email unmarshal error: %s", err)
|
||||
return []FullEmail{}, err
|
||||
return []shuffle.FullEmail{}, err
|
||||
}
|
||||
|
||||
emails = append(emails, parsedmail)
|
||||
@@ -253,77 +103,48 @@ func getOutlookEmail(client *http.Client, maildata MailData) ([]FullEmail, error
|
||||
return emails, nil
|
||||
}
|
||||
|
||||
func getOutlookFolders(client *http.Client) (OutlookFolders, error) {
|
||||
//requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/ec03b4f2-fccf-4c35-b0eb-be85a0f5dd43/mailFolders")
|
||||
requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/me/mailFolders")
|
||||
|
||||
ret, err := client.Get(requestUrl)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] FolderErr: %s", err)
|
||||
return OutlookFolders{}, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(ret.Body)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed body decoding from mailfolders")
|
||||
return OutlookFolders{}, err
|
||||
}
|
||||
|
||||
//log.Printf("[INFO] Folder Body: %s", string(body))
|
||||
log.Printf("[INFO] Status folders: %d", ret.StatusCode)
|
||||
if ret.StatusCode != 200 {
|
||||
return OutlookFolders{}, err
|
||||
}
|
||||
|
||||
//log.Printf("Body: %s", string(body))
|
||||
|
||||
mailfolders := OutlookFolders{}
|
||||
err = json.Unmarshal(body, &mailfolders)
|
||||
if err != nil {
|
||||
log.Printf("Unmarshal: %s", err)
|
||||
return OutlookFolders{}, err
|
||||
}
|
||||
|
||||
//fmt.Printf("%#v", mailfolders)
|
||||
// FIXME - recursion for subfolders
|
||||
// Recursive struct
|
||||
// folderEndpoint := fmt.Sprintf("%s/%s/childfolders?$top=40", requestUrl, parentId)
|
||||
//for _, folder := range mailfolders.Value {
|
||||
// log.Println(folder.DisplayName)
|
||||
//}
|
||||
|
||||
return mailfolders, nil
|
||||
}
|
||||
|
||||
func getOutlookProfile(client *http.Client) (OutlookProfile, error) {
|
||||
func getOutlookProfile(client *http.Client) (shuffle.OutlookProfile, error) {
|
||||
requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/me?$select=mail")
|
||||
|
||||
ret, err := client.Get(requestUrl)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Folder error: %s", err)
|
||||
return OutlookProfile{}, err
|
||||
return shuffle.OutlookProfile{}, err
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Status profile: %d", ret.StatusCode)
|
||||
body, err := ioutil.ReadAll(ret.Body)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Body: %s", err)
|
||||
return OutlookProfile{}, err
|
||||
return shuffle.OutlookProfile{}, err
|
||||
}
|
||||
|
||||
log.Printf("[INFO] BODY: %s", string(body))
|
||||
|
||||
profile := OutlookProfile{}
|
||||
profile := shuffle.OutlookProfile{}
|
||||
err = json.Unmarshal(body, &profile)
|
||||
if err != nil {
|
||||
log.Printf("Unmarshal: %s", err)
|
||||
return OutlookProfile{}, err
|
||||
return shuffle.OutlookProfile{}, err
|
||||
}
|
||||
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := shuffle.HandleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Api authentication failed in getting specific trigger: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
code := request.URL.Query().Get("code")
|
||||
if len(code) == 0 {
|
||||
log.Println("No code")
|
||||
@@ -334,7 +155,7 @@ func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
url := fmt.Sprintf("http://%s%s", request.Host, request.URL.EscapedPath())
|
||||
log.Println(url)
|
||||
ctx := context.Background()
|
||||
_, accessToken, err := getOutlookClient(ctx, code, OauthToken{}, url)
|
||||
_, accessToken, err := getOutlookClient(ctx, code, shuffle.OauthToken{}, url)
|
||||
if err != nil {
|
||||
log.Printf("Oauth client failure - outlook register: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
@@ -367,7 +188,7 @@ func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
// FIXME - trigger auth
|
||||
senderUser := ""
|
||||
trigger := TriggerAuth{}
|
||||
trigger := shuffle.TriggerAuth{}
|
||||
for _, item := range stateitems {
|
||||
itemsplit := strings.Split(item, "%3D")
|
||||
if len(itemsplit) == 1 {
|
||||
@@ -404,7 +225,7 @@ func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
*/
|
||||
|
||||
trigger.Code = code
|
||||
trigger.OauthToken = OauthToken{
|
||||
trigger.OauthToken = shuffle.OauthToken{
|
||||
AccessToken: accessToken.AccessToken,
|
||||
TokenType: accessToken.TokenType,
|
||||
RefreshToken: accessToken.RefreshToken,
|
||||
@@ -425,7 +246,7 @@ func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
// Should also update the user
|
||||
Userdata, err := shuffle.GetUser(ctx, senderUser)
|
||||
Userdata, err := shuffle.GetUser(ctx, user.Id)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Username %s doesn't exist (oauth2): %s", trigger.Username, err)
|
||||
resp.WriteHeader(401)
|
||||
@@ -458,14 +279,14 @@ func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
})
|
||||
|
||||
// Set apikey for the user if they don't have one
|
||||
err = shuffle.SetUser(ctx, Userdata)
|
||||
err = shuffle.SetUser(ctx, Userdata, true)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting user data for %s: %s", Userdata.Username, err)
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
err = setTriggerAuth(ctx, trigger)
|
||||
err = shuffle.SetTriggerAuth(ctx, trigger)
|
||||
if err != nil {
|
||||
log.Printf("Failed to set trigger auth for %s - %s", trigger.Username, err)
|
||||
resp.WriteHeader(401)
|
||||
@@ -476,50 +297,8 @@ func handleNewOutlookRegister(resp http.ResponseWriter, request *http.Request) {
|
||||
resp.Write([]byte(`{"success": true}`))
|
||||
}
|
||||
|
||||
type OauthToken struct {
|
||||
AccessToken string `json:"AccessToken" datastore:"AccessToken,noindex"`
|
||||
TokenType string `json:"TokenType" datastore:"TokenType,noindex"`
|
||||
RefreshToken string `json:"RefreshToken" datastore:"RefreshToken,noindex"`
|
||||
Expiry time.Time `json:"Expiry" datastore:"Expiry,noindex"`
|
||||
}
|
||||
|
||||
type TriggerAuth struct {
|
||||
Id string `json:"id" datastore:"id"`
|
||||
SubscriptionId string `json:"subscriptionId" datastore:"subscriptionId"`
|
||||
|
||||
Username string `json:"username" datastore:"username,noindex"`
|
||||
WorkflowId string `json:"workflow_id" datastore:"workflow_id,noindex"`
|
||||
Owner string `json:"owner" datastore:"owner"`
|
||||
Type string `json:"type" datastore:"type"`
|
||||
Code string `json:"code,omitempty" datastore:"code,noindex"`
|
||||
Start string `json:"start" datastore:"start"`
|
||||
OauthToken OauthToken `json:"oauth_token,omitempty" datastore:"oauth_token"`
|
||||
}
|
||||
|
||||
func getTriggerAuth(ctx context.Context, id string) (*TriggerAuth, error) {
|
||||
key := datastore.NameKey("trigger_auth", strings.ToLower(id), nil)
|
||||
triggerauth := &TriggerAuth{}
|
||||
if err := dbclient.Get(ctx, key, triggerauth); err != nil {
|
||||
return &TriggerAuth{}, err
|
||||
}
|
||||
|
||||
return triggerauth, nil
|
||||
}
|
||||
|
||||
func setTriggerAuth(ctx context.Context, trigger TriggerAuth) error {
|
||||
key1 := datastore.NameKey("trigger_auth", strings.ToLower(trigger.Id), nil)
|
||||
|
||||
// New struct, to not add body, author etc
|
||||
if _, err := dbclient.Put(ctx, key1, &trigger); err != nil {
|
||||
log.Printf("Error adding trigger auth: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// THis all of a sudden became really horrible.. fml
|
||||
func getOutlookClient(ctx context.Context, code string, accessToken OauthToken, redirectUri string) (*http.Client, *oauth2.Token, error) {
|
||||
func getOutlookClient(ctx context.Context, code string, accessToken shuffle.OauthToken, redirectUri string) (*http.Client, *oauth2.Token, error) {
|
||||
|
||||
conf := &oauth2.Config{
|
||||
ClientID: "fd55c175-aa30-4fa6-b303-09a29fb3f750",
|
||||
@@ -557,81 +336,6 @@ func getOutlookClient(ctx context.Context, code string, accessToken OauthToken,
|
||||
return client, access_token, nil
|
||||
}
|
||||
|
||||
func handleGetOutlookFolders(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
// Exchange every time hmm
|
||||
// FIXME
|
||||
// Should really just get the code from the trigger that's being used OR the user
|
||||
triggerId := request.URL.Query().Get("trigger_id")
|
||||
if len(triggerId) == 0 {
|
||||
log.Println("No trigger_id supplied")
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
trigger, err := getTriggerAuth(ctx, triggerId)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Trigger %s doesn't exist - outlook folders.", triggerId)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "Trigger doesn't exist."}`))
|
||||
return
|
||||
}
|
||||
|
||||
//client, accessToken, err := getOutlookClient(ctx, code, OauthToken{}, url)
|
||||
//if err != nil {
|
||||
// log.Printf("Oauth client failure - outlook register: %s", err)
|
||||
// resp.WriteHeader(401)
|
||||
// return
|
||||
//}
|
||||
|
||||
// FIXME - should be shuffler in literally every case except testing lol
|
||||
//log.Printf("TRIGGER: %#v", trigger)
|
||||
redirectDomain := "localhost:5001"
|
||||
url := fmt.Sprintf("http://%s/api/v1/triggers/outlook/register", redirectDomain)
|
||||
outlookClient, _, err := getOutlookClient(ctx, "", trigger.OauthToken, url)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Oauth client failure - outlook folders: %s", err)
|
||||
resp.Write([]byte(`{"success": false, "reason": "Failed creating outlook client"}`))
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
// This should be possible, and will also give the actual username
|
||||
/*
|
||||
profile, err := getOutlookProfile(outlookClient)
|
||||
if err != nil {
|
||||
log.Printf("Outlook profile failure: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
log.Printf("PROFILE: %#v", profile)
|
||||
*/
|
||||
|
||||
folders, err := getOutlookFolders(outlookClient)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed setting outlook folders: %s", err)
|
||||
resp.Write([]byte(`{"success": false, "reason": "Failed getting outlook folders"}`))
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := json.Marshal(folders.Value)
|
||||
if err != nil {
|
||||
log.Println("[INFO] Failed to marshal folderdata")
|
||||
resp.Write([]byte(`{"success": false, "reason": "Failed decoding JSON"}`))
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write(b)
|
||||
}
|
||||
|
||||
func handleGetSpecificTrigger(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
@@ -664,7 +368,7 @@ func handleGetSpecificTrigger(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
trigger, err := getTriggerAuth(ctx, workflowId)
|
||||
trigger, err := shuffle.GetTriggerAuth(ctx, workflowId)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Trigger %s doesn't exist - specific trigger.", workflowId)
|
||||
resp.WriteHeader(401)
|
||||
@@ -678,7 +382,7 @@ func handleGetSpecificTrigger(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
trigger.OauthToken = OauthToken{}
|
||||
trigger.OauthToken = shuffle.OauthToken{}
|
||||
trigger.Code = ""
|
||||
|
||||
b, err := json.Marshal(trigger)
|
||||
@@ -692,201 +396,6 @@ func handleGetSpecificTrigger(resp http.ResponseWriter, request *http.Request) {
|
||||
resp.Write(b)
|
||||
}
|
||||
|
||||
// This sets up the sub with outlook itself
|
||||
// Parses data from the workflow to see whether access is right to subscribe it
|
||||
// Creates the cloud function for outlook return
|
||||
// Wait for it to be available, then schedule a workflow to it
|
||||
func createOutlookSub(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
location := strings.Split(request.URL.String(), "/")
|
||||
|
||||
var workflowId string
|
||||
if location[1] == "api" {
|
||||
if len(location) <= 4 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
workflowId = location[4]
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
workflow, err := shuffle.GetWorkflow(ctx, workflowId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting the workflow locally (outlook sub): %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
user, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
if err != nil {
|
||||
log.Printf("Api authentication failed in outlook deploy: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME - have a check for org etc too..
|
||||
if user.Id != workflow.Owner && user.Role != "admin" {
|
||||
log.Printf("Wrong user (%s) for workflow %s when deploying outlook", user.Username, workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("[INFO] Handle outlook subscription for trigger")
|
||||
|
||||
// Should already be authorized at this point, as the workflow is shared
|
||||
body, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
log.Printf("Failed body read for workflow %s", workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Based on the input data from frontend
|
||||
type CurTrigger struct {
|
||||
Name string `json:"name"`
|
||||
Folders []string `json:"folders"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
//log.Println(string(body))
|
||||
var curTrigger CurTrigger
|
||||
err = json.Unmarshal(body, &curTrigger)
|
||||
if err != nil {
|
||||
log.Printf("Failed body read unmarshal for trigger %s", workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
if len(curTrigger.Folders) == 0 {
|
||||
log.Printf("Error for %s. Choosing folders is required, currently 0", workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Now that it's deployed - wait a few seconds before generating:
|
||||
// 1. Oauth2 token thingies for outlook.office.com
|
||||
// 2. Set the url to have the right mailboxes (probably ID?) ("https://outlook.office.com/api/v2.0/me/mailfolders('inbox')/messages")
|
||||
// 3. Set the callback URL to be the new trigger
|
||||
// 4. Run subscription test
|
||||
// 5. Set the subscriptionId to the trigger object
|
||||
|
||||
// First - lets regenerate an oauth token for outlook.office.com from the original items
|
||||
trigger, err := getTriggerAuth(ctx, curTrigger.ID)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Trigger %s doesn't exist - outlook sub.", curTrigger.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||
return
|
||||
}
|
||||
|
||||
// url doesn't really matter here
|
||||
//url := fmt.Sprintf("https://shuffler.io")
|
||||
redirectDomain := "localhost:5001"
|
||||
url := fmt.Sprintf("http://%s/api/v1/triggers/outlook/register", redirectDomain)
|
||||
outlookClient, _, err := getOutlookClient(ctx, "", trigger.OauthToken, url)
|
||||
if err != nil {
|
||||
log.Printf("Oauth client failure - triggerauth: %s", err)
|
||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
// Location +
|
||||
|
||||
// This is here simply to let the function start
|
||||
// Usually takes 10 attempts minimum :O
|
||||
// 10 * 5 = 50 seconds. That's waaay too much :(
|
||||
|
||||
if runningEnvironment != "cloud" {
|
||||
org, err := shuffle.GetOrg(ctx, user.ActiveOrg.Id)
|
||||
if err != nil {
|
||||
log.Printf("Failed finding org %s: %s", org.Id, err)
|
||||
return
|
||||
}
|
||||
log.Printf("[INFO] Starting cloud configuration TO START trigger %s in org %s for workflow %s", trigger.Id, org.Id, trigger.WorkflowId)
|
||||
|
||||
action := shuffle.CloudSyncJob{
|
||||
Type: "outlook",
|
||||
Action: "start",
|
||||
OrgId: org.Id,
|
||||
PrimaryItemId: trigger.Id,
|
||||
SecondaryItem: trigger.Start,
|
||||
ThirdItem: workflowId,
|
||||
}
|
||||
|
||||
err = executeCloudAction(action, org.SyncConfig.Apikey)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Failed cloud action START outlook execution: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
||||
return
|
||||
} else {
|
||||
log.Printf("[INFO] Successfully set up cloud action trigger")
|
||||
}
|
||||
} else {
|
||||
log.Printf("Should configure a running environment for CLOUD")
|
||||
}
|
||||
|
||||
notificationURL := fmt.Sprintf("%s/api/v1/hooks/webhook_%s", syncSubUrl, trigger.Id)
|
||||
curSubscriptions, err := getOutlookSubscriptions(outlookClient)
|
||||
if err == nil {
|
||||
for _, sub := range curSubscriptions.Value {
|
||||
if sub.NotificationURL == notificationURL {
|
||||
log.Printf("[INFO] Removing existing subscription %s", sub.Id)
|
||||
removeOutlookSubscription(outlookClient, sub.Id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("[INFO] Failed to get subscriptions - need to overwrite")
|
||||
}
|
||||
|
||||
maxFails := 5
|
||||
failCnt := 0
|
||||
log.Println(curTrigger.Folders)
|
||||
for {
|
||||
subId, err := makeOutlookSubscription(outlookClient, curTrigger.Folders, notificationURL)
|
||||
if err != nil {
|
||||
failCnt += 1
|
||||
log.Printf("Failed making oauth subscription, retrying in 5 seconds: %s", err)
|
||||
time.Sleep(5 * time.Second)
|
||||
if failCnt == maxFails {
|
||||
log.Printf("Failed to set up subscription %d times.", maxFails)
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Set the ID somewhere here
|
||||
trigger.SubscriptionId = subId
|
||||
err = setTriggerAuth(ctx, *trigger)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting triggerauth: %s", err)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Successfully handled outlook subscription for trigger %s in workflow %s", curTrigger.ID, workflow.ID)
|
||||
|
||||
//log.Printf("%#v", user)
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true}`))
|
||||
}
|
||||
|
||||
// Lists the users current subscriptions
|
||||
func getOutlookSubscriptions(outlookClient *http.Client) (SubscriptionsWrapper, error) {
|
||||
fullUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/subscriptions")
|
||||
@@ -1024,7 +533,7 @@ func handleOutlookCallback(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
//func getTriggerAuth(ctx context.Context, id string) (*TriggerAuth, error) {
|
||||
hook, err := getTriggerAuth(ctx, hookId)
|
||||
hook, err := shuffle.GetTriggerAuth(ctx, hookId)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Failed getting trigger %s (callback): %s", hookId, err)
|
||||
resp.WriteHeader(401)
|
||||
@@ -1054,7 +563,7 @@ func handleOutlookCallback(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
// 1. Take the body and parse data -> Get the email itself
|
||||
|
||||
maildata := MailData{}
|
||||
maildata := shuffle.MailData{}
|
||||
err = json.Unmarshal(body, &maildata)
|
||||
if err != nil {
|
||||
log.Printf("Maildata unmarshal error: %s", err)
|
||||
@@ -1076,14 +585,14 @@ func handleOutlookCallback(resp http.ResponseWriter, request *http.Request) {
|
||||
log.Printf("[INFO] EMAILS: %d. If this is more than 1, please contact frikky@shuffler.io", len(emails))
|
||||
//log.Printf("INSIDE GET OUTLOOK EMAIL!: %#v, %s", emails, err)
|
||||
|
||||
//type FullEmail struct {
|
||||
email := FullEmail{}
|
||||
//type shuffle.FullEmail struct {
|
||||
email := shuffle.FullEmail{}
|
||||
if len(emails) == 1 {
|
||||
email = emails[0]
|
||||
}
|
||||
|
||||
// Parse indicators (domains, emails, ips, domains etc)!
|
||||
newEmail := ParsedShuffleMail{}
|
||||
newEmail := shuffle.ParsedShuffleMail{}
|
||||
newEmail.Body.ContentType = email.Body.Contenttype
|
||||
newEmail.Body.Content = email.Body.Content
|
||||
newEmail.Body.RawBody = email.Body.Content
|
||||
@@ -1203,7 +712,7 @@ func handleOutlookSubRemoval(ctx context.Context, user shuffle.User, workflowId,
|
||||
// 2. Stop the subscription
|
||||
// 3. Remove the function
|
||||
// 4. Remove the database entry for auth
|
||||
trigger, err := getTriggerAuth(ctx, triggerId)
|
||||
trigger, err := shuffle.GetTriggerAuth(ctx, triggerId)
|
||||
if err != nil {
|
||||
log.Printf("Trigger auth %s doesn't exist - outlook sub removal.", triggerId)
|
||||
return err
|
||||
@@ -1293,7 +802,7 @@ func handleDeleteOutlookSub(resp http.ResponseWriter, request *http.Request) {
|
||||
ctx := context.Background()
|
||||
workflow, err := shuffle.GetWorkflow(ctx, workflowId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting the workflow locally (delete outlook): %s", err)
|
||||
log.Printf("[WARNING] Failed getting the workflow locally (delete outlook): %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
@@ -1327,3 +836,198 @@ func handleDeleteOutlookSub(resp http.ResponseWriter, request *http.Request) {
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true}`))
|
||||
}
|
||||
|
||||
// This sets up the sub with outlook itself
|
||||
// Parses data from the workflow to see whether access is right to subscribe it
|
||||
// Creates the cloud function for outlook return
|
||||
// Wait for it to be available, then schedule a workflow to it
|
||||
func createOutlookSub(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
location := strings.Split(request.URL.String(), "/")
|
||||
|
||||
var workflowId string
|
||||
if location[1] == "api" {
|
||||
if len(location) <= 4 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
workflowId = location[4]
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
workflow, err := shuffle.GetWorkflow(ctx, workflowId)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Failed getting the workflow locally (outlook sub): %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
user, err := shuffle.HandleApiAuthentication(resp, request)
|
||||
if err != nil {
|
||||
log.Printf("Api authentication failed in outlook deploy: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME - have a check for org etc too..
|
||||
if user.Id != workflow.Owner && user.Role != "admin" {
|
||||
log.Printf("Wrong user (%s) for workflow %s when deploying outlook", user.Username, workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("[INFO] Handle outlook subscription for trigger")
|
||||
|
||||
// Should already be authorized at this point, as the workflow is shared
|
||||
body, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
log.Printf("Failed body read for workflow %s", workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Based on the input data from frontend
|
||||
type CurTrigger struct {
|
||||
Name string `json:"name"`
|
||||
Folders []string `json:"folders"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
//log.Println(string(body))
|
||||
var curTrigger CurTrigger
|
||||
err = json.Unmarshal(body, &curTrigger)
|
||||
if err != nil {
|
||||
log.Printf("Failed body read unmarshal for trigger %s", workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
if len(curTrigger.Folders) == 0 {
|
||||
log.Printf("Error for %s. Choosing folders is required, currently 0", workflow.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Now that it's deployed - wait a few seconds before generating:
|
||||
// 1. Oauth2 token thingies for outlook.office.com
|
||||
// 2. Set the url to have the right mailboxes (probably ID?) ("https://outlook.office.com/api/v2.0/me/mailfolders('inbox')/messages")
|
||||
// 3. Set the callback URL to be the new trigger
|
||||
// 4. Run subscription test
|
||||
// 5. Set the subscriptionId to the trigger object
|
||||
|
||||
// First - lets regenerate an oauth token for outlook.office.com from the original items
|
||||
trigger, err := shuffle.GetTriggerAuth(ctx, curTrigger.ID)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Trigger %s doesn't exist - outlook sub.", curTrigger.ID)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||
return
|
||||
}
|
||||
|
||||
// url doesn't really matter here
|
||||
//url := fmt.Sprintf("https://shuffler.io")
|
||||
redirectDomain := "localhost:5001"
|
||||
url := fmt.Sprintf("http://%s/api/v1/triggers/outlook/register", redirectDomain)
|
||||
outlookClient, _, err := getOutlookClient(ctx, "", trigger.OauthToken, url)
|
||||
if err != nil {
|
||||
log.Printf("Oauth client failure - triggerauth: %s", err)
|
||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
// Location +
|
||||
|
||||
// This is here simply to let the function start
|
||||
// Usually takes 10 attempts minimum :O
|
||||
// 10 * 5 = 50 seconds. That's waaay too much :(
|
||||
|
||||
if runningEnvironment != "cloud" {
|
||||
org, err := shuffle.GetOrg(ctx, user.ActiveOrg.Id)
|
||||
if err != nil {
|
||||
log.Printf("Failed finding org %s: %s", org.Id, err)
|
||||
return
|
||||
}
|
||||
log.Printf("[INFO] Starting cloud configuration TO START trigger %s in org %s for workflow %s", trigger.Id, org.Id, trigger.WorkflowId)
|
||||
|
||||
action := shuffle.CloudSyncJob{
|
||||
Type: "outlook",
|
||||
Action: "start",
|
||||
OrgId: org.Id,
|
||||
PrimaryItemId: trigger.Id,
|
||||
SecondaryItem: trigger.Start,
|
||||
ThirdItem: workflowId,
|
||||
}
|
||||
|
||||
err = executeCloudAction(action, org.SyncConfig.Apikey)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Failed cloud action START outlook execution: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
|
||||
return
|
||||
} else {
|
||||
log.Printf("[INFO] Successfully set up cloud action trigger")
|
||||
}
|
||||
} else {
|
||||
log.Printf("Should configure a running environment for CLOUD")
|
||||
}
|
||||
|
||||
notificationURL := fmt.Sprintf("%s/api/v1/hooks/webhook_%s", syncSubUrl, trigger.Id)
|
||||
curSubscriptions, err := getOutlookSubscriptions(outlookClient)
|
||||
if err == nil {
|
||||
for _, sub := range curSubscriptions.Value {
|
||||
if sub.NotificationURL == notificationURL {
|
||||
log.Printf("[INFO] Removing existing subscription %s", sub.Id)
|
||||
removeOutlookSubscription(outlookClient, sub.Id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("[INFO] Failed to get subscriptions - need to overwrite")
|
||||
}
|
||||
|
||||
maxFails := 5
|
||||
failCnt := 0
|
||||
log.Println(curTrigger.Folders)
|
||||
for {
|
||||
subId, err := makeOutlookSubscription(outlookClient, curTrigger.Folders, notificationURL)
|
||||
if err != nil {
|
||||
failCnt += 1
|
||||
log.Printf("Failed making oauth subscription, retrying in 5 seconds: %s", err)
|
||||
time.Sleep(5 * time.Second)
|
||||
if failCnt == maxFails {
|
||||
log.Printf("Failed to set up subscription %d times.", maxFails)
|
||||
resp.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Set the ID somewhere here
|
||||
trigger.SubscriptionId = subId
|
||||
err = shuffle.SetTriggerAuth(ctx, *trigger)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting triggerauth: %s", err)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Successfully handled outlook subscription for trigger %s in workflow %s", curTrigger.ID, workflow.ID)
|
||||
|
||||
//log.Printf("%#v", user)
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true}`))
|
||||
}
|
||||
|
||||
+410
-1922
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
curl -XPOST http://192.168.3.8:5001/api/v1/orgs/6a6a99f5-6630-4f91-88ff-571c9f030ea0/set_cache -H "Authorization: Bearer e663cf93-7f10-4560-bef0-303f14aad982" -d '{
|
||||
"workflow_id": "61825389-a125-43a5-9119-97c401e9934b",
|
||||
"execution_id": "2c8ca1b7-6658-4742-86a1-105c9467702d",
|
||||
"org_id": "6a6a99f5-6630-4f91-88ff-571c9f030ea0",
|
||||
"key": "test",
|
||||
"value": "THIS IS SOME DATA HELLO"
|
||||
}'
|
||||
|
||||
curl -XPOST http://192.168.3.8:5001/api/v1/orgs/6a6a99f5-6630-4f91-88ff-571c9f030ea0/get_cache -H "Authorization: Bearer e663cf93-7f10-4560-bef0-303f14aad982" -d '{
|
||||
"workflow_id": "61825389-a125-43a5-9119-97c401e9934b",
|
||||
"execution_id": "2c8ca1b7-6658-4742-86a1-105c9467702d",
|
||||
"org_id": "6a6a99f5-6630-4f91-88ff-571c9f030ea0",
|
||||
"key": "test"
|
||||
}'
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
#!/bin/sh
|
||||
curl -XPOST http://localhost:5001/api/v1/get_docker_image -d '{"name":"frikky/shuffle:Testing_1.0.0"}' -H "Authorization: Bearer db0373c6-1083-4dec-a05d-3ba73f02ccd4"
|
||||
#curl -XPOST http://localhost:5001/api/v1/get_docker_image -d '{"name":"frikky/shuffle:testing_1.0.0"}' -H "Authorization: Bearer db0373c6-1083-4dec-a05d-3ba73f02ccd4" --output tarball.tgz
|
||||
#curl -XPOST http://localhost:5001/api/v1/get_docker_image -d '{"name":"frikky/shuffle:testing_1.0.0"}' -H "Authorization: Bearer db0373c6-1083-4dec-a05d-3ba73f02ccd4" -O -J
|
||||
#curl -XPOST http://localhost:5001/api/v1/get_docker_image -d '{"name":"frikky/shuffle:testing_1.0.0"}' -H "Authorization: Bearer db0373c6-1083-4dec-a05d-3ba73f02ccd4" --output tarball.tgz
|
||||
curl -XPOST http://localhost:5001/api/v1/get_docker_image -d '{"name":"frikky/shuffle:shuffle-tools_1.0.0"}' -H "Authorization: Bearer db0373c6-1083-4dec-a05d-3ba73f02ccd4" --output tarball.tgz
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
curl -XPOST -v localhost:5001/api/v1/migrate_database -H 'Authorization: Bearer 0184d7be-33c1-4391-bf9c-dfb8508a4ea2'
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
import re
|
||||
import json
|
||||
|
||||
def parse_nested_param(string, level):
|
||||
"""
|
||||
Generate strings contained in nested (), indexing i = level
|
||||
"""
|
||||
if len(re.findall("\(", string)) == len(re.findall("\)", string)):
|
||||
LeftRightIndex = [x for x in zip(
|
||||
[Left.start()+1 for Left in re.finditer('\(', string)],
|
||||
reversed([Right.start() for Right in re.finditer('\)', string)]))]
|
||||
|
||||
elif len(re.findall("\(", string)) > len(re.findall("\)", string)):
|
||||
return parse_nested_param(string + ')', level)
|
||||
elif len(re.findall("\(", string)) < len(re.findall("\)", string)):
|
||||
return parse_nested_param('(' + string, level)
|
||||
|
||||
else:
|
||||
return 'Failed to parse params'
|
||||
|
||||
try:
|
||||
return [string[LeftRightIndex[level][0]:LeftRightIndex[level][1]]]
|
||||
except IndexError:
|
||||
return [string[LeftRightIndex[level+1][0]:LeftRightIndex[level+1][1]]]
|
||||
|
||||
# Parses the deepest part
|
||||
def maxDepth(S):
|
||||
current_max = 0
|
||||
max = 0
|
||||
n = len(S)
|
||||
|
||||
# Traverse the input string
|
||||
for i in range(n):
|
||||
if S[i] == '(':
|
||||
current_max += 1
|
||||
|
||||
if current_max > max:
|
||||
max = current_max
|
||||
elif S[i] == ')':
|
||||
if current_max > 0:
|
||||
current_max -= 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
# finally check for unbalanced string
|
||||
if current_max != 0:
|
||||
return -1
|
||||
|
||||
return max-1
|
||||
|
||||
def parse_type(data, thistype):
|
||||
if data == None:
|
||||
return "Empty"
|
||||
|
||||
if "int" in thistype:
|
||||
try:
|
||||
return int(data)
|
||||
except ValueError:
|
||||
print("ValueError while casting %s" % data)
|
||||
return data
|
||||
if "lower" in thistype:
|
||||
return data.lower()
|
||||
if "upper" in thistype:
|
||||
return data.upper()
|
||||
if "trim" in thistype:
|
||||
return data.strip()
|
||||
if "strip" in thistype:
|
||||
return data.strip()
|
||||
if "split" in thistype:
|
||||
# Should be able to split anything
|
||||
return data.split()
|
||||
if "len" in thistype or "length" in thistype:
|
||||
return len(data)
|
||||
if "parse" in thistype:
|
||||
splitvalues = []
|
||||
default_error = """Error. Expected syntax: parse(["hello","test1"],0:1)"""
|
||||
if "," in data:
|
||||
splitvalues = data.split(",")
|
||||
|
||||
for item in range(len(splitvalues)):
|
||||
splitvalues[item] = splitvalues[item].strip()
|
||||
else:
|
||||
return default_error
|
||||
|
||||
lastsplit = []
|
||||
if ":" in splitvalues[-1]:
|
||||
lastsplit = splitvalues[-1].split(":")
|
||||
else:
|
||||
try:
|
||||
lastsplit = [int(splitvalues[-1])]
|
||||
except ValueError:
|
||||
return default_error
|
||||
|
||||
try:
|
||||
parsedlist = ",".join(splitvalues[0:-1])
|
||||
print(parsedlist)
|
||||
print(lastsplit)
|
||||
|
||||
if len(lastsplit) > 1:
|
||||
tmp = json.loads(parsedlist)[int(lastsplit[0]):int(lastsplit[1])]
|
||||
else:
|
||||
tmp = json.loads(parsedlist)[lastsplit[0]]
|
||||
|
||||
print(tmp)
|
||||
return tmp
|
||||
except IndexError as e:
|
||||
return default_error
|
||||
|
||||
# Parses the INNER value and recurses until everything is done
|
||||
def parse_wrapper(data):
|
||||
try:
|
||||
if "(" not in data or ")" not in data:
|
||||
return data
|
||||
except TypeError:
|
||||
return data
|
||||
|
||||
print("Running %s" % data)
|
||||
|
||||
# Look for the INNER wrapper first, then move out
|
||||
wrappers = ["int", "number", "lower", "upper", "trim", "strip", "split", "parse", "len", "length"]
|
||||
found = False
|
||||
for wrapper in wrappers:
|
||||
if wrapper not in data.lower():
|
||||
continue
|
||||
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
return data
|
||||
|
||||
# Do stuff here.
|
||||
innervalue = parse_nested_param(data, maxDepth(data)-0)
|
||||
outervalue = parse_nested_param(data, maxDepth(data)-1)
|
||||
print("INNER: ", outervalue)
|
||||
print("OUTER: ", outervalue)
|
||||
|
||||
if outervalue != innervalue:
|
||||
#print("Outer: ", outervalue, " inner: ", innervalue)
|
||||
for key in range(len(innervalue)):
|
||||
# Replace OUTERVALUE[key] with INNERVALUE[key] in data.
|
||||
print("Replace %s with %s in %s" % (outervalue[key], innervalue[key], data))
|
||||
data = data.replace(outervalue[key], innervalue[key])
|
||||
else:
|
||||
for thistype in wrappers:
|
||||
if thistype not in data.lower():
|
||||
continue
|
||||
|
||||
parsed_value = parse_type(innervalue[0], thistype)
|
||||
return parsed_value
|
||||
|
||||
print("DATA: %s\n" % data)
|
||||
return parse_wrapper(data)
|
||||
|
||||
def parse_wrapper_start(data):
|
||||
newdata = []
|
||||
newstring = ""
|
||||
record = True
|
||||
paranCnt = 0
|
||||
for char in data:
|
||||
if char == "(":
|
||||
paranCnt += 1
|
||||
|
||||
if not record:
|
||||
record = True
|
||||
|
||||
if record:
|
||||
newstring += char
|
||||
|
||||
if paranCnt == 0 and char == " ":
|
||||
newdata.append(newstring)
|
||||
newstring = ""
|
||||
record = True
|
||||
|
||||
if char == ")":
|
||||
paranCnt -= 1
|
||||
|
||||
if paranCnt == 0:
|
||||
record = False
|
||||
|
||||
if len(newstring) > 0:
|
||||
newdata.append(newstring)
|
||||
|
||||
parsedlist = []
|
||||
non_string = False
|
||||
for item in newdata:
|
||||
ret = parse_wrapper(item)
|
||||
if not isinstance(ret, str):
|
||||
non_string = True
|
||||
|
||||
parsedlist.append(ret)
|
||||
|
||||
if len(parsedlist) > 0 and not non_string:
|
||||
return " ".join(parsedlist)
|
||||
elif len(parsedlist) == 1 and non_string:
|
||||
return parsedlist[0]
|
||||
else:
|
||||
print("Casting back to string because multi: ", parsedlist)
|
||||
newlist = []
|
||||
for item in parsedlist:
|
||||
try:
|
||||
newlist.append(str(item))
|
||||
except ValueError:
|
||||
newlist.append("parsing_error")
|
||||
return " ".join(newlist)
|
||||
|
||||
data = "split(hello there)"
|
||||
data = """parse(["testing", "what", "is this"], 0:2)"""
|
||||
#data = "int(int(2))"
|
||||
print("RET: ", parse_wrapper_start(data))
|
||||
@@ -0,0 +1,14 @@
|
||||
# ExecutionOrg MUST be executing.
|
||||
curl -XPOST http://localhost:5001/api/v1/orgs/b199646b-16d2-456d-9fd6-b9972e929466/validate_app_values -d '{
|
||||
"append": true,
|
||||
"workflow_check": true,
|
||||
"authorization": "1aae630c-ccaf-4cb5-87f9-8a9e0a9afd11",
|
||||
"execution_ref": "c59ff288-4f02-4d02-b839-133d55c7fdf0",
|
||||
"org_id": "b199646b-16d2-456d-9fd6-b9972e929466",
|
||||
"values": [{
|
||||
"app": "testing",
|
||||
"action": "repeat_back_to_me",
|
||||
"parameternames": ["call"],
|
||||
"parametervalues": ["hey", "ho", "lets", "go"]
|
||||
}]
|
||||
}'
|
||||
Reference in New Issue
Block a user