def renderworkflow(application_name, workflow): """route for /workflow/<application_name>/<workflow> :param application_name: application name :param workflow: workflow name Renders <workflow> for <application_name> and lets user answer questions.""" appview = fullpath_import(f"{application_name}", "views") data = json.loads(session["data"]) try: appcontroller = fullpath_import(f"{application_name}", "controller") prefuncs = appcontroller.workflow.prefuncs postfuncs = appcontroller.workflow.postfuncs except ModuleNotFoundError: prefuncs = {} postfuncs = {} if workflow in prefuncs.keys(): data.update(prefuncs[workflow](data) or {}) appview.appform.questions = deque() if workflow in appview.appform.workflows: wfquestions = appview.appform.workflows[workflow] else: if workflow not in appview.__dict__: raise NameError(f"Couldn't find workflow {workflow}") wfquestions = appview.__dict__[workflow] # "Instantiate" workflow questions wfquestions(data) # Ask workflow questions appview.appform.workflows = {} questionsform = form_generator(application_name, [], wfquestions) if questionsform.validate_on_submit(): data.update(json.loads(session["data"])) data.update(questionsform.data) session["data"] = json.dumps(data) # If selected workflow have a post_-function, run that now if workflow in postfuncs.keys(): data.update(postfuncs[workflow](data) or {}) if ("workflow" or "nextworkflow" in questionsform) or ("nextworkflow" in data): workflow = (questionsform.data.get("workflow") or questionsform.data.get("nextworkflow") or data["nextworkflow"]) if workflow: return redirect( url_for( "main.renderworkflow", application_name=application_name, workflow=workflow, )) # FIXME: Same as in apps function. # DRY templatedir = ( f"{jobbergateconfig['apps']['path']}/{application_name}/templates/" ) template = data.get("template", None) or data.get( "default_template", "job_template.j2") jinjaenv = Environment(loader=FileSystemLoader(templatedir)) jinjatemplate = jinjaenv.get_template(template) return Response( jinjatemplate.render(data=data), mimetype="text/x-shellscript", headers={"Content-Disposition": "attachment;filename=jobfile.sh"}, ) return render_template( "main/form.html", form=questionsform, application_name=application_name, )
def _wrapper(**kvargs): """The callback needs to be wrapped""" appview = fullpath_import(f"{application}", "views") data = {} data["jobbergateconfig"] = deepcopy(jobbergateconfig) saveanswers = kvargs["saveanswers"] if kvargs["answerfile"]: with open(kvargs["answerfile"]) as jsonfile: answerfile = json.load(jsonfile) else: answerfile = {} # Update data from answerfile with command line arguments answerfile.update(parse_prefill(kvargs["prefill"])) data.update(answerfile) # Check if the app has a controller file try: appcontroller = fullpath_import(f"{application}", "controller") prefuncs = appcontroller.workflow.prefuncs postfuncs = appcontroller.workflow.postfuncs except ModuleNotFoundError: prefuncs = {} postfuncs = {} outputfile = kvargs["output"] use_defaults = kvargs["fast"] try: with open( f"{jobbergateconfig['apps']['path']}/{application}/config.yaml", "r") as ymlfile: data.update(yaml.safe_load(ymlfile)) except FileNotFoundError: pass # If the is a pre_-function in the controller, run that before all # questions if "" in prefuncs.keys(): data.update(prefuncs[""](data) or {}) # Ask the questions questions = appview.mainflow(data) answers = ask_questions(questions, answerfile, use_defaults) if saveanswers: savedanswers = answers data.update(answers) if "mainflow" in postfuncs.keys(): data.update(postfuncs["mainflow"](data) or {}) if "nextworkflow" in data or ("flows" in answerfile and "mainflow" in answerfile["flows"]): if saveanswers: savedanswers["flow"] = {} currentworkflow = "mainflow" while True: if "flows" in answerfile: workflow = answerfile["flows"].get( currentworkflow) or data.pop("nextworkflow") if workflow in answerfile["flows"]: answerfile["nextworkflow"] = answerfile["flows"][ workflow] else: workflow = data.pop("nextworkflow") if saveanswers: savedanswers["flow"].update( {currentworkflow: workflow}) currentworkflow = workflow # If nextworkflow isn't defined, raise exception if workflow not in appview.__dict__: raise NameError(f"Couldn't find workflow {workflow}") # If selected workflow have a pre_-function, run that now if workflow in prefuncs.keys(): data.update(prefuncs[workflow](data) or {}) # "Instantiate" workflow questions wfquestions = appview.__dict__[workflow] questions = wfquestions(data) answers = ask_questions(questions, answerfile, use_defaults) if saveanswers: savedanswers.update(answers) data.update(answers) # If selected workflow have a post_-function, run that now if workflow in postfuncs.keys(): data.update(postfuncs[workflow](data) or {}) if "nextworkflow" not in data: break # Check if workflows is defined if appview.appform.workflows: if "workflow" in answerfile: workflow = answerfile["workflow"] else: workflows = [ inquirer.List( "workflow", message="What workflow should be used", choices=appview.appform.workflows.keys(), ) ] try: wfdata = inquirer.prompt(workflows) except TypeError: exit(0) if "mainflow" in postfuncs.keys(): data.update(postfuncs["mainflow"](data) or {}) workflow = wfdata["workflow"] if saveanswers: savedanswers.update({"workflow": workflow}) # If selected workflow have a pre_-function, run that now if workflow in prefuncs.keys(): data.update(prefuncs[workflow](data) or {}) # "Instantiate" workflow questions wfquestions = appview.appform.workflows[workflow] questions = wfquestions(data) # Ask workflow questions answers = ask_questions(questions, answerfile, use_defaults) if saveanswers: savedanswers.update(answers) data.update(answers) # If selected workflow have a post_-function, run that now if workflow in postfuncs.keys(): data.update(postfuncs[workflow](data) or {}) appview.appform.workflows = {} if kvargs["template"]: templatedir = str(Path(kvargs["template"]).parent) template = Path(kvargs["template"]).name else: templatedir = ( f"{jobbergateconfig['apps']['path']}/{application}/templates/" ) template = data.get("template", None) or data.get( "default_template", "job_template.j2") # If there is a global post_-function, run that now if "" in postfuncs.keys(): data.update(postfuncs[""](data) or {}) if saveanswers: with open(kvargs["saveanswers"], "w") as jsonfile: json.dump(savedanswers, jsonfile, indent=4) jinjaenv = Environment(loader=FileSystemLoader(templatedir)) jinjatemplate = jinjaenv.get_template(template) file = outputfile.write(jinjatemplate.render(data=data)) outputfile.flush() if "cmd_command" in data.keys() and not kvargs["no_cmd"]: subprocess.run(data["cmd_command"], shell=True) return file
def application(application_name): """route for /app/<application_name> :param application_name: Name of application Renders base questions for <application_name> and lets users answer them.""" templates = [(template, template) for template in json.loads(session["templates"])] importedlib = fullpath_import(application_name, "views") data = {} data["jobbergateconfig"] = deepcopy(jobbergateconfig) try: with open( f"{jobbergateconfig['apps']['path']}/{application_name}/config.yaml", "r") as ymlfile: data.update(yaml.safe_load(ymlfile)) except FileNotFoundError: pass try: appcontroller = fullpath_import(f"{application_name}", "controller") prefuncs = appcontroller.workflow.prefuncs postfuncs = appcontroller.workflow.postfuncs except ModuleNotFoundError: prefuncs = {} postfuncs = {} if request.method == "GET": # If the is a pre_-function in the controller, run that before all # questions if "" in prefuncs.keys(): data.update(prefuncs[""](data) or {}) questionsform = form_generator(application_name, templates, importedlib.mainflow) if questionsform.validate_on_submit(): data.update(json.loads(session["data"])) data.update(questionsform.data) session["data"] = json.dumps(data) if "mainflow" in postfuncs: data.update(postfuncs["mainflow"](data) or {}) if "workflow" or "nextworkflow" in questionsform: workflow = questionsform.data.get( "workflow") or questionsform.data.get("nextworkflow") if "views" in sys.modules: del sys.modules["views"] return redirect( url_for( "main.renderworkflow", application_name=application_name, workflow=workflow, )) templatedir = ( f"{jobbergateconfig['apps']['path']}/{application_name}/templates/" ) template = data.get("template", None) or data.get( "default_template", "job_template.j2") jinjaenv = Environment(loader=FileSystemLoader(templatedir)) jinjatemplate = jinjaenv.get_template(template) return Response( jinjatemplate.render(data=data), mimetype="text/x-shellscript", headers={"Content-Disposition": "attachment;filename=jobfile.sh"}, ) session["data"] = json.dumps(data) if "views" in sys.modules: del sys.modules["views"] return render_template( "main/form.html", form=questionsform, application_name=application_name, )