Example #1
0
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,
    )
Example #2
0
        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
Example #3
0
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,
    )