Exemple #1
0
    def deploy_process(cls, payload, process_id=None, describe_schema=PROCESS_SCHEMA_OGC):
        # type: (JSON, Optional[str], str) -> JSON
        """
        Deploys a process with :paramref:`payload`.

        :returns: resulting tuple of ``(process-description, package)`` JSON responses.
        """
        if process_id:
            payload["processDescription"]["process"]["id"] = process_id  # type: ignore
        exec_list = payload.get("executionUnit", [])
        if len(exec_list):
            # test-only feature:
            #   substitute 'href' starting by 'tests/' by the corresponding file in test resources
            #   this allows clean separation of deploy payload from CWL to allow reuse and test CWL locally beforehand
            exec_href = exec_list[0].get("href", "")
            if exec_href.startswith("tests/"):
                exec_unit = load_file(os.path.join(WEAVER_ROOT_DIR, exec_href))
                exec_list[0]["unit"] = exec_unit
                exec_list[0].pop("href")
        resp = mocked_sub_requests(cls.app, "post_json", "/processes", data=payload, headers=cls.json_headers)
        assert resp.status_code == 201, "Expected successful deployment.\nError:\n{}".format(resp.text)
        path = resp.json["processSummary"]["processDescriptionURL"]
        body = {"value": VISIBILITY_PUBLIC}
        resp = cls.app.put_json("{}/visibility".format(path), params=body, headers=cls.json_headers)
        assert resp.status_code == 200, "Expected successful visibility.\nError:\n{}".format(resp.text)
        info = []
        for info_path in ["{}?schema={}".format(path, describe_schema), "{}/package".format(path)]:
            resp = cls.app.get(info_path, headers=cls.json_headers)
            assert resp.status_code == 200
            info.append(deepcopy(resp.json))
        return info
Exemple #2
0
    def test_execute_docker_embedded_python_script(self):
        test_proc = "test-docker-python-script"
        cwl = load_file(os.path.join(WEAVER_ROOT_DIR, "docs/examples/docker-python-script-report.cwl"))
        body = {
            "processDescription": {
                "process": {
                    "id": test_proc
                }
            },
            "executionUnit": [{"unit": cwl}],
            "deploymentProfileName": "http://www.opengis.net/profiles/eoc/dockerizedApplication"
        }
        self.deploy_process(body)

        with contextlib.ExitStack() as stack:
            for mock_exec in mocked_execute_process():
                stack.enter_context(mock_exec)

            path = f"/processes/{test_proc}/execution"
            cost = 2.45
            amount = 3
            body = {
                "mode": EXECUTE_MODE_ASYNC,
                "response": EXECUTE_RESPONSE_DOCUMENT,
                "inputs": [
                    {"id": "amount", "value": amount},
                    {"id": "cost", "value": cost}
                ],
                "outputs": [
                    {"id": "quote", "transmissionMode": EXECUTE_TRANSMISSION_MODE_REFERENCE},
                ]
            }
            resp = mocked_sub_requests(self.app, "POST", path, json=body, headers=self.json_headers, only_local=True)
            status_url = resp.headers["Location"]
            results = self.monitor_job(status_url)

            assert results["quote"]["href"].startswith("http")
            stack.enter_context(mocked_wps_output(self.settings))
            tmpdir = stack.enter_context(tempfile.TemporaryDirectory())
            report_file = fetch_file(results["quote"]["href"], tmpdir, self.settings)
            report_data = load_file(report_file, text=True)
            assert report_data == f"Order Total: {amount * cost:0.2f}$\n"
Exemple #3
0
 def _parse_inputs(inputs):
     # type: (Optional[Union[str, JSON]]) -> Union[OperationResult, JSON]
     try:
         if isinstance(inputs, str):
             # loaded inputs could be mapping or listing format (any schema: CWL, OGC, OLD)
             inputs = load_file(inputs) if inputs != "" else []
         if not inputs or not isinstance(inputs, (dict, list)):
             return OperationResult(
                 False, "No inputs or invalid schema provided.", inputs)
         if isinstance(inputs, list):
             # list of literals from CLI
             if any("=" in value for value in inputs):
                 inputs = repr2json_input_values(inputs)
             # list of single file from CLI (because of 'nargs')
             elif len(inputs) == 1 and "=" not in inputs[0]:
                 inputs = load_file(inputs[0])
             elif len(inputs) == 1 and inputs[0] == "":
                 inputs = []
         if isinstance(inputs, list):
             inputs = {"inputs": inputs}  # OLD format provided directly
         # consider possible ambiguity if literal CWL input is named 'inputs'
         # - if value of 'inputs' is an object, it can collide with 'OGC' schema,
         #   unless 'value/href' are present or their sub-dict don't have CWL 'class'
         # - if value of 'inputs' is an array, it can collide with 'OLD' schema,
         #   unless 'value/href' (and 'id' technically) are present
         values = inputs.get("inputs", null)
         if (values is null or values is not null and
             ((isinstance(values, dict) and get_any_value(values) is null
               and "class" not in values) or
              (isinstance(values, list) and all(
                  isinstance(v, dict) and get_any_value(v) is null
                  for v in values)))):
             values = cwl2json_input_values(inputs)
         if values is null:
             raise ValueError(
                 "Input values parsed as null. Could not properly detect employed schema."
             )
     except Exception as exc:
         return OperationResult(
             False, f"Failed inputs parsing with error: [{exc!s}].", inputs)
     return values
Exemple #4
0
 def _parse_deploy_body(body, process_id):
     # type: (Optional[Union[JSON, str]], Optional[str]) -> OperationResult
     data = {}  # type: JSON
     try:
         if body:
             if isinstance(body, str) and (body.startswith("http")
                                           or os.path.isfile(body)):
                 data = load_file(body)
             elif isinstance(
                     body,
                     str) and body.startswith("{") and body.endswith("}"):
                 data = yaml.safe_load(body)
             elif isinstance(body, dict):
                 data = body
             else:
                 msg = "Cannot load badly formed body. Deploy JSON object or file reference expected."
                 return OperationResult(False, msg, body, {})
         elif not body:
             data = {"processDescription": {"process": {"id": process_id}}}
         if body and process_id:
             LOGGER.debug(
                 "Override provided process ID [%s] into provided/loaded body.",
                 process_id)
             data.setdefault("processDescription", {})
             data["processDescription"].setdefault("process", {})
             data["processDescription"]["process"][
                 "id"] = process_id  # type: ignore
         # for convenience, always set visibility by default
         data.setdefault("processDescription", {})
         data["processDescription"].setdefault("process", {})
         data["processDescription"]["process"][
             "visibility"] = VISIBILITY_PUBLIC  # type: ignore
     except (ValueError, TypeError, ScannerError) as exc:
         return OperationResult(
             False, f"Failed resolution of body definition: [{exc!s}]",
             body)
     return OperationResult(True, "", data)
Exemple #5
0
def _load_path(file_path, text=False, xml=False):
    # type: (str, bool, bool) -> Union[JSON, xml_util.XML, str]
    if xml:
        return xml_util.parse(file_path)
    return load_file(file_path, text=text)