Esempio n. 1
0
    def catch_api_proxy_experiments_post():

        json_obj = request.json

        json_obj["pipeline_run_spec"]["run_config"] = {
            "host_user_dir": app.config["HOST_USER_DIR"],
            "project_dir": get_project_directory(
                json_obj["project_uuid"], host_path=True
            ),
            "pipeline_path": pipeline_uuid_to_path(
                json_obj["pipeline_uuid"],
                json_obj["project_uuid"],
            ),
        }

        # Analytics call
        send_pipeline_run(
            app,
            f"{json_obj['project_uuid']}-{json_obj['pipeline_uuid']}",
            get_project_directory(json_obj["project_uuid"]),
            "noninteractive",
        )

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/experiments/",
            json=json_obj,
        )

        return resp.content, resp.status_code, resp.headers.items()
Esempio n. 2
0
    def catch_api_proxy_sessions_post():

        json_obj = request.json

        json_obj["project_dir"] = get_project_directory(
            json_obj["project_uuid"], host_path=True)

        json_obj["pipeline_path"] = pipeline_uuid_to_path(
            json_obj["pipeline_uuid"],
            json_obj["project_uuid"],
        )

        json_obj["host_userdir"] = app.config["HOST_USER_DIR"]

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/sessions/",
            json=json_obj,
        )

        tel_props = {
            "project_uuid": json_obj["project_uuid"],
            "pipeline_uuid": json_obj["pipeline_uuid"],
        }
        analytics.send_event(app, "session start", tel_props)
        return resp.content, resp.status_code, resp.headers.items()
Esempio n. 3
0
    def pipeline_cwd(project_uuid, pipeline_uuid):

        pipeline_dir = get_pipeline_directory(pipeline_uuid, project_uuid)
        project_dir = get_project_directory(project_uuid)
        cwd = pipeline_dir.replace(project_dir, "")

        return jsonify({"cwd": cwd})
Esempio n. 4
0
    def catch_api_proxy_sessions():

        json_obj = request.json

        json_obj["project_dir"] = get_project_directory(
            json_obj["project_uuid"], host_path=True
        )

        json_obj["pipeline_path"] = pipeline_uuid_to_path(
            json_obj["pipeline_uuid"],
            json_obj["project_uuid"],
        )

        json_obj["host_userdir"] = app.config["HOST_USER_DIR"]

        pipeline_json = get_pipeline_json(
            json_obj["pipeline_uuid"], json_obj["project_uuid"]
        )
        json_obj["settings"] = pipeline_json.get("settings", {})

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/sessions/",
            json=json_obj,
        )

        return resp.content, resp.status_code, resp.headers.items()
Esempio n. 5
0
    def catch_api_proxy_jobs_post():

        json_obj = request.json

        pipeline_path = pipeline_uuid_to_path(json_obj["pipeline_uuid"],
                                              json_obj["project_uuid"])
        json_obj["pipeline_run_spec"]["run_config"] = {
            "host_user_dir":
            app.config["HOST_USER_DIR"],
            "project_dir":
            get_project_directory(json_obj["project_uuid"], host_path=True),
            "pipeline_path":
            pipeline_path,
        }

        json_obj["pipeline_definition"] = get_pipeline_json(
            json_obj["pipeline_uuid"], json_obj["project_uuid"])

        # Validate whether the pipeline contains environments
        # that do not exist in the project.
        project_environments = get_environments(json_obj["project_uuid"])
        project_environment_uuids = set(
            [environment.uuid for environment in project_environments])
        pipeline_environment_uuids = get_environments_from_pipeline_json(
            json_obj["pipeline_definition"])

        missing_environment_uuids = (pipeline_environment_uuids -
                                     project_environment_uuids)
        if len(missing_environment_uuids) > 0:
            missing_environment_uuids_str = ", ".join(
                missing_environment_uuids)
            return (
                jsonify({
                    "message":
                    "The pipeline definition references environments "
                    f"that do not exist in the project. "
                    "The following environments do not exist:"
                    f" [{missing_environment_uuids_str}].\n\n Please make sure all"
                    " pipeline steps are assigned an environment that exists"
                    " in the project."
                }),
                500,
            )

        # Jobs should always have eviction enabled.
        json_obj["pipeline_definition"]["settings"]["auto_eviction"] = True

        job_uuid = str(uuid.uuid4())
        json_obj["uuid"] = job_uuid
        create_job_directory(job_uuid, json_obj["pipeline_uuid"],
                             json_obj["project_uuid"])

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/jobs/",
            json=json_obj,
        )

        analytics.send_job_create(app, json_obj)
        return resp.content, resp.status_code, resp.headers.items()
Esempio n. 6
0
    def catch_api_proxy_runs():

        if request.method == "POST":

            json_obj = request.json

            # add image mapping
            # TODO: replace with dynamic mapping instead of hardcoded
            json_obj["run_config"] = {
                "project_dir": get_project_directory(
                    json_obj["project_uuid"], host_path=True
                ),
                "pipeline_path": pipeline_uuid_to_path(
                    json_obj["pipeline_definition"]["uuid"], json_obj["project_uuid"]
                ),
            }

            # Analytics call
            send_pipeline_run(
                app,
                f"{json_obj['project_uuid']}-{json_obj['pipeline_definition']['uuid']}",
                get_project_directory(json_obj["project_uuid"]),
                "interactive",
            )

            resp = requests.post(
                "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/runs/",
                json=json_obj,
            )

            return resp.content, resp.status_code, resp.headers.items()

        elif request.method == "GET":

            resp = requests.get(
                "http://"
                + app.config["ORCHEST_API_ADDRESS"]
                + "/api/runs/?"
                + request.query_string.decode(),
            )

            return resp.content, resp.status_code, resp.headers.items()
Esempio n. 7
0
    def catch_api_proxy_jobs_post():

        json_obj = request.json

        pipeline_path = pipeline_uuid_to_path(
            json_obj["pipeline_uuid"], json_obj["project_uuid"]
        )
        json_obj["pipeline_run_spec"]["run_config"] = {
            "host_user_dir": app.config["HOST_USER_DIR"],
            "project_dir": get_project_directory(
                json_obj["project_uuid"], host_path=True
            ),
            "pipeline_path": pipeline_path,
        }

        json_obj["pipeline_definition"] = get_pipeline_json(
            json_obj["pipeline_uuid"], json_obj["project_uuid"]
        )

        # Jobs should always have eviction enabled.
        json_obj["pipeline_definition"]["settings"]["auto_eviction"] = True

        job_uuid = str(uuid.uuid4())
        json_obj["uuid"] = job_uuid
        create_job_directory(
            job_uuid, json_obj["pipeline_uuid"], json_obj["project_uuid"]
        )

        # Analytics call
        send_pipeline_run(
            app,
            f"{json_obj['project_uuid']}-{json_obj['pipeline_uuid']}",
            get_project_directory(json_obj["project_uuid"]),
            "noninteractive",
        )

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/jobs/",
            json=json_obj,
        )

        return resp.content, resp.status_code, resp.headers.items()
Esempio n. 8
0
    def get_file_picker_tree(project_uuid):

        allowed_file_extensions = ["ipynb", "R", "py", "sh"]

        project_dir = get_project_directory(project_uuid)

        if not os.path.isdir(project_dir):
            return jsonify(
                {"message": "Project dir %s not found." % project_dir}), 404

        tree = {"type": "directory", "root": True, "name": "/", "children": []}

        dir_nodes = {}

        dir_nodes[project_dir] = tree

        for root, dirs, files in os.walk(project_dir):

            # exclude directories that start with "." from file_picker
            dirs[:] = [
                dirname for dirname in dirs if not dirname.startswith(".")
            ]

            for dirname in dirs:

                dir_path = os.path.join(root, dirname)
                dir_node = {
                    "type": "directory",
                    "name": dirname,
                    "children": [],
                }

                dir_nodes[dir_path] = dir_node
                dir_nodes[root]["children"].append(dir_node)

            for filename in files:

                if filename.split(".")[-1] in allowed_file_extensions:
                    file_node = {
                        "type": "file",
                        "name": filename,
                    }

                    # this key should always exist
                    try:
                        dir_nodes[root]["children"].append(file_node)
                    except KeyError as e:
                        app.logger.error(
                            "Key %s does not exist in dir_nodes %s. Error: %s"
                            % (root, dir_nodes, e))
                    except Exception as e:
                        app.logger.error("Error: %e" % e)

        return jsonify(tree)
Esempio n. 9
0
    def catch_api_proxy_sessions_post():

        json_obj = request.json

        project_uuid = json_obj["project_uuid"]
        pipeline_uuid = json_obj["pipeline_uuid"]

        # Lock the project and pipeline row to avoid race conditions
        # with RenameProject and MovePipeline, which are locking for
        # update themselves.
        Project.query.with_for_update().filter(
            Project.uuid == project_uuid, ).one()
        Pipeline.query.with_for_update().filter(
            Pipeline.project_uuid == project_uuid,
            Pipeline.uuid == pipeline_uuid,
        ).one()

        pipeline_path = pipeline_uuid_to_path(
            json_obj["pipeline_uuid"],
            json_obj["project_uuid"],
        )

        project_dir = get_project_directory(json_obj["project_uuid"])

        services = get_pipeline_json(json_obj["pipeline_uuid"],
                                     json_obj["project_uuid"]).get(
                                         "services", {})

        session_config = {
            "project_uuid": project_uuid,
            "pipeline_uuid": pipeline_uuid,
            "pipeline_path": pipeline_path,
            "project_dir": project_dir,
            "userdir_pvc": app.config["USERDIR_PVC"],
            "services": services,
        }

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/sessions/",
            json=session_config,
        )

        analytics.send_event(
            app,
            analytics.Event.SESSION_START,
            {
                "project_uuid": project_uuid,
                "pipeline_uuid": pipeline_uuid,
                "services": services,
            },
        )
        return resp.content, resp.status_code, resp.headers.items()
Esempio n. 10
0
def create_job_spec(config) -> dict:
    """Returns a job spec based on the provided configuration.

    Args: Initial configuration with which the job spec should be built.
        project_uuid, pipeline_uuid, pipeline_run_spec, pipeline_name,
        name are required. Optional entries such as env_variables can be
        used to further customize the initial state of the newly created
        job.

    Returns:
        A job spec that can be POSTED to the orchest-api to create a job
        that is a duplicate of the job identified by the provided
        job_uuid.
    """
    job_spec = copy.deepcopy(config)
    pipeline_path = pipeline_uuid_to_path(
        job_spec["pipeline_uuid"], job_spec["project_uuid"]
    )
    job_spec["pipeline_run_spec"]["run_config"] = {
        "userdir_pvc": current_app.config["USERDIR_PVC"],
        "project_dir": get_project_directory(job_spec["project_uuid"]),
        "pipeline_path": pipeline_path,
    }

    job_spec["pipeline_definition"] = get_pipeline_json(
        job_spec["pipeline_uuid"], job_spec["project_uuid"]
    )

    # Validate whether the pipeline contains environments
    # that do not exist in the project.
    project_environments = get_environments(job_spec["project_uuid"])
    project_environment_uuids = set(
        [environment.uuid for environment in project_environments]
    )
    pipeline_environment_uuids = get_environments_from_pipeline_json(
        job_spec["pipeline_definition"]
    )

    missing_environment_uuids = pipeline_environment_uuids - project_environment_uuids
    if len(missing_environment_uuids) > 0:
        raise error.EnvironmentsDoNotExist(missing_environment_uuids)

    # Jobs should always have eviction enabled.
    job_spec["pipeline_definition"]["settings"]["auto_eviction"] = True

    job_uuid = str(uuid.uuid4())
    job_spec["uuid"] = job_uuid
    create_job_directory(job_uuid, job_spec["pipeline_uuid"], job_spec["project_uuid"])
    return job_spec
Esempio n. 11
0
    def catch_api_proxy_runs():

        if request.method == "POST":

            json_obj = request.json

            # add image mapping
            # TODO: replace with dynamic mapping instead of hardcoded
            # All the paths are container path
            json_obj["run_config"] = {
                "userdir_pvc":
                app.config["USERDIR_PVC"],
                "project_dir":
                get_project_directory(json_obj["project_uuid"]),
                "pipeline_path":
                pipeline_uuid_to_path(json_obj["pipeline_definition"]["uuid"],
                                      json_obj["project_uuid"]),
                "pipeline_uuid":
                json_obj["pipeline_definition"]["uuid"],
                "project_uuid":
                json_obj["project_uuid"],
            }

            resp = requests.post(
                "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/runs/",
                json=json_obj,
            )

            analytics.send_event(
                app,
                analytics.Event.PIPELINE_RUN_START,
                {
                    "run_uuid": resp.json().get("uuid"),
                    "run_type": "interactive",
                    "pipeline_definition": json_obj["pipeline_definition"],
                    "step_uuids_to_execute": json_obj["uuids"],
                },
            )

            return resp.content, resp.status_code, resp.headers.items()

        elif request.method == "GET":

            resp = requests.get(
                "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/runs/" +
                request_args_to_string(request.args), )

            return resp.content, resp.status_code, resp.headers.items()
Esempio n. 12
0
    def create_project_file(project_uuid):
        """Create project file in specified directory within project."""

        project_dir = get_project_directory(project_uuid)

        # Client sends absolute path relative to project root, hence the
        # starting / character is removed.
        file_path = os.path.join(project_dir, request.json["file_path"][1:])

        if os.path.isfile(file_path):
            return jsonify({"message": "File already exists."}), 409

        try:
            open(file_path, "a").close()
            return jsonify({"message": "File created."})
        except IOError as e:
            app.logger.error("Could not create file at %s. Error: %s" %
                             (file_path, e))
Esempio n. 13
0
    def catch_api_proxy_runs():

        json_obj = request.json

        # add image mapping
        # TODO: replace with dynamic mapping instead of hardcoded
        json_obj["run_config"] = {
            "project_dir":
            get_project_directory(json_obj["project_uuid"], host_path=True),
            "pipeline_path":
            pipeline_uuid_to_path(json_obj["pipeline_description"]["uuid"],
                                  json_obj["project_uuid"]),
        }

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] + "/api/runs/",
            json=json_obj,
            stream=True,
        )

        return resp.raw.read(), resp.status_code, resp.headers.items()
Esempio n. 14
0
    def catch_api_proxy_experiments_post():

        json_obj = request.json

        json_obj["pipeline_run_spec"]["run_config"] = {
            "host_user_dir":
            app.config["HOST_USER_DIR"],
            "project_dir":
            get_project_directory(json_obj["project_uuid"], host_path=True),
            "pipeline_path":
            pipeline_uuid_to_path(
                json_obj["pipeline_uuid"],
                json_obj["project_uuid"],
            ),
        }

        resp = requests.post(
            "http://" + app.config["ORCHEST_API_ADDRESS"] +
            "/api/experiments/",
            json=json_obj,
            stream=True,
        )

        return resp.raw.read(), resp.status_code, resp.headers.items()