229 lines
7.8 KiB
Python
229 lines
7.8 KiB
Python
import requests;
|
|
import json;
|
|
import logging;
|
|
|
|
class PyExecPlugins(type):
|
|
def __init__(cls, name, bases, attrs):
|
|
if not hasattr(cls, "plugins"):
|
|
logging.getLogger("pyexec").debug("Initializing plugins")
|
|
cls.plugins = {}
|
|
cls.alias = {}
|
|
else:
|
|
logging.getLogger("pyexec").debug("Appending a plugin %s - %s ", cls.name, cls)
|
|
cls.plugins[cls.name] = cls
|
|
#Alias plugin also with taskdefinition so it will be lookup-able with poth Operation name and taskdefinition
|
|
if cls.taskdef is not None:
|
|
cls.alias[cls.taskdef["name"]] = cls
|
|
|
|
def getPlugins(cls):
|
|
return cls.plugins
|
|
|
|
def getPluginNames(cls):
|
|
return [*cls.plugins.keys()]
|
|
|
|
def get(cls, name):
|
|
return cls.plugins.get(name)
|
|
|
|
def getAlias(cls, name):
|
|
return cls.alias.get(name)
|
|
|
|
def registerTaskDefinitions(cls, server):
|
|
url = server + "/metadata/taskdefs"
|
|
#pyexec generic taskdefinition
|
|
taskdefs = [
|
|
#{
|
|
# "name" : "pyexec",
|
|
# "description" : "Execute PyExec operations",
|
|
# "inputKeys" : ["operation"],
|
|
# "outputKeys" : ["ret"],
|
|
# "ownerEmail" : "m.lettere@gmail.com"
|
|
#}
|
|
]
|
|
for plg in cls.getPluginNames():
|
|
if cls.plugins[plg].taskdef is not None:
|
|
taskdef = cls.plugins[plg].taskdef
|
|
taskdefs.append(taskdef)
|
|
|
|
#Post all new (or not) task definitions to orchestrator
|
|
logging.getLogger("pyexec").debug("Recording task definitions %s", taskdefs)
|
|
headers = {'Content-Type': 'application/json'}
|
|
try:
|
|
response = requests.request("POST", url, headers=headers, data=json.dumps(taskdefs))
|
|
except Exception as e:
|
|
logging.getLogger("pyexec").warning("Unable to register task defs %s", e)
|
|
|
|
class PyExecPlugin(object, metaclass=PyExecPlugins):
|
|
def __init__(self, data=None, config=None):
|
|
self.data = data
|
|
self.config = config
|
|
|
|
def hasDefinition(self):
|
|
return (self.taskdef is not None)
|
|
|
|
#class Nop(PyExecPlugin):
|
|
# name = "Nop"
|
|
# taskdef = None
|
|
#
|
|
# def __init__(self, data=None):
|
|
# super().__init__(data)
|
|
#
|
|
# def execute(self):
|
|
# return None
|
|
|
|
#class Identity(PyExecPlugin):
|
|
# name = "Identity"
|
|
# taskdef = None
|
|
#
|
|
# def __init__(self, data=None):
|
|
# super().__init__(data)
|
|
#
|
|
# def execute(self):
|
|
# self.data.pop("_result", None)
|
|
# return self.data
|
|
|
|
#class Sequence(PyExecPlugin):
|
|
# name = "Sequence"
|
|
# taskdef = None
|
|
#
|
|
# def __init__(self, data=None):
|
|
# super().__init__(data)
|
|
#
|
|
# def handleSequence(self, sequence, currentresults):
|
|
# for t in sequence:
|
|
# operation = t.get("operation", "Nop")
|
|
# if operation == "Sequence":
|
|
# self.handleSequence(t.tasks, self.results)
|
|
# else:
|
|
# p = PyExecPlugin.get(operation)
|
|
# if p != None:
|
|
# t["_result"] = currentresults
|
|
# pi = p(t)
|
|
# ret = pi.execute()
|
|
# self.result.append(ret)
|
|
#
|
|
# else: raise Exception("Operation {} not found.".format(operation))
|
|
#
|
|
# def execute(self):
|
|
# self.result = []
|
|
# self.handleSequence(self.data.get("tasks",[]),self.result)
|
|
# return {"result": self.result}
|
|
|
|
#class Http(PyExecPlugin):
|
|
# name = "Http"
|
|
#
|
|
# def __init__(self, data):
|
|
# super().__init__(data)
|
|
# self.method = data.get("method") or "get"
|
|
# self.url = data.get("url")
|
|
# self.headers = data.get("headers") or {}
|
|
# self.contenttype = self.headers.get("Content-Type")
|
|
# self.accept = self.headers.get("Accept")
|
|
# self.body = data.get("body")
|
|
# self.params = data.get("params")
|
|
# self.expect = data.get("expect")
|
|
# self.fail = data.get("fail")
|
|
#
|
|
# def doRequest(self):
|
|
# #print(self.method, self.url, self.contenttype, self.accept)
|
|
# if self.contenttype != None and self.contenttype.find("json") != -1:
|
|
# self.response = requests.request(self.method, self.url, headers=self.headers, json = self.body)
|
|
# else:
|
|
# self.response = requests.request(self.method, self.url, headers=self.headers, data = self.body, params = self.params)
|
|
# return self.response
|
|
#
|
|
# def computeStatus(self):
|
|
# if self.fail == False:
|
|
# return "COMPLETED"
|
|
# elif self.expect == None:
|
|
# return "COMPLETED" if self.response.ok else "FAILED"
|
|
# else:
|
|
# if type(self.expect) == list:
|
|
# return "COMPLETED" if (self.response.status_code in self.expect) else "FAILED"
|
|
# else:
|
|
# return "COMPLETED" if (self.response.status_code == self.expect) else "FAILED"
|
|
#
|
|
# def buildOutput(self, status):
|
|
# hdrs = {}
|
|
# for k in self.response.headers.keys(): hdrs[k] = self.response.headers[k]
|
|
#
|
|
# print("Response: {} {}".format(self.response.status_code, self.response.reason))
|
|
#
|
|
# if hdrs.get("Content-Type") != None and hdrs["Content-Type"].find("json") != -1 or self.accept != None and #self.accept.find("json") != -1:
|
|
# outbody = self.response.json() if len(self.response.content) != 0 else None
|
|
# else:
|
|
# outbody = self.response.text
|
|
# #print(outbody)
|
|
# return {
|
|
# 'status': status,
|
|
# 'output': {
|
|
# "body" : outbody,
|
|
# "headers" : hdrs,
|
|
# "status" : self.response.status_code,
|
|
# "reason" : self.response.reason
|
|
# },
|
|
# 'logs': ['one', 'two']
|
|
# }
|
|
#
|
|
# def execute(self):
|
|
# self.doRequest()
|
|
# status = self.computeStatus()
|
|
# return self.buildOutput(status)
|
|
|
|
#class Eval(PyExecPlugin):
|
|
# name = "Eval"
|
|
#
|
|
# def __init__(self, data=None):
|
|
# super().__init__(data)
|
|
#
|
|
# def execute(self):
|
|
# code = self.data.get("code")
|
|
# if code != None:
|
|
# ret = eval(code, { "data" : self.data})
|
|
# return { "result" : ret }
|
|
|
|
#class Write(PyExecPlugin):
|
|
# name = "Write"
|
|
#
|
|
# def __init__(self, data=None):
|
|
# super().__init__(data)
|
|
#
|
|
# def execute(self):
|
|
# print("File opening at", self.data["path"])
|
|
# fo = open(self.data["path"], "w")
|
|
# print("File opened", fo)
|
|
# typ = self.data.get("type", "text")
|
|
# if typ == "json":
|
|
# fo.write(json.dumps(self.data.get("content","{}")))
|
|
# else:
|
|
# fo.write(self.data.get("content", ""))
|
|
# fo.close()
|
|
# return {}
|
|
|
|
#class Shell(PyExecPlugin):
|
|
# name = "Shell"
|
|
#
|
|
# def __init__(self, data=None):
|
|
# super().__init__(data)
|
|
#
|
|
# def execute(self):
|
|
# output = {
|
|
# 'results' : [],
|
|
# 'status' : "COMPLETED"
|
|
# }
|
|
# for cmdentry in self.data.get("commands"):
|
|
# expect = cmdentry.get("expect", 0)
|
|
# cmd = cmdentry.get("line")
|
|
# #Use shell=True for very complex cmdlines that do have quotes and ther amenities
|
|
# withshell = cmdentry.get("withshell", self.data.get("withshell", False))
|
|
# if cmd == None:
|
|
# continue
|
|
# else:
|
|
# cmd = cmd.split() if not withshell else cmd
|
|
# print("Going to execute", withshell, cmd)
|
|
# completed = subprocess.run(cmd, shell=withshell, capture_output=True, text=True)
|
|
# output["results"].append({ 'returncode' : completed.returncode, 'stdout' : completed.stdout, 'stderr': completed.stderr})
|
|
# if completed.returncode != expect:
|
|
# output["status"] = "FAILED"
|
|
# break
|
|
# return output
|