Exemplo n.º 1
0
 def test_deploy_with_undeploy(self):
     test_id = f"{self.test_process_prefix}-deploy-undeploy-flag"
     result = mocked_sub_requests(self.app, self.client.deploy, test_id, self.test_payload)
     assert result.success
     result = mocked_sub_requests(self.app, self.client.deploy, test_id, self.test_payload, undeploy=True)
     assert result.success
     assert "undefined" not in result.message
Exemplo n.º 2
0
    def test_execute_manual_monitor_status_and_download_results(self):
        """
        Test a typical case of :term:`Job` execution, result retrieval and download, but with manual monitoring.

        Manual monitoring can be valid in cases where a *very* long :term:`Job` must be executed, and the user does
        not intend to wait after it. This avoids leaving some shell/notebook/etc. open of a long time and provide a
        massive ``timeout`` value. Instead, the user can simply re-call :meth:`WeaverClient.monitor` at a later time
        to resume monitoring. Other situation can be if the connection was dropped or script runner crashed, and the
        want to pick up monitoring again.

        .. note::
            The :meth:`WeaverClient.execute` is accomplished synchronously during this test because of the mock.
            The :meth:`WeaverClient.monitor` step can therefore only return ``success``/``failed`` directly
            without any intermediate and asynchronous pooling of ``running`` status.
            The first status result from  :meth:`WeaverClient.execute` is ``accept`` because this is the
            default status that is generated by the HTTP response from the :term:`Job` creation.
            Any following GET status will directly return the final :term:`Job` result.
        """
        result = self.run_execute_inputs_schema_variant("Execute_Echo_cwl_schema.yml", mock_exec=False)
        job_id = result.body["jobID"]
        result = mocked_sub_requests(self.app, self.client.monitor, job_id, timeout=1, interval=1)
        assert result.success, result.text
        assert "undefined" not in result.message
        assert result.body.get("status") == STATUS_SUCCEEDED
        links = result.body.get("links")
        assert isinstance(links, list)
        assert len(list(filter(lambda _link: _link["rel"].endswith("results"), links))) == 1

        # first test to get job results details, but not downloading yet
        result = mocked_sub_requests(self.app, self.client.results, job_id)
        assert result.success, result.text
        assert "undefined" not in result.message
        outputs_body = result.body
        assert isinstance(outputs_body, dict) and len(outputs_body) == 1
        output = outputs_body.get("output")  # single of this process
        assert isinstance(output, dict) and "href" in output, "Output named 'output' should be a 'File' reference."
        output_href = output.get("href")
        assert isinstance(output_href, str) and output_href.startswith(self.settings["weaver.wps_output_url"])

        # test download feature
        with contextlib.ExitStack() as stack:
            server_mock = stack.enter_context(mocked_wps_output(self.settings))
            target_dir = stack.enter_context(tempfile.TemporaryDirectory())
            result = mocked_sub_requests(self.app, self.client.results,
                                         job_id, download=True, out_dir=target_dir,  # 'client.results' parameters
                                         only_local=True)  # mock parameter (avoid download HTTP redirect to TestApp)
            assert result.success, result.text
            assert "undefined" not in result.message
            assert result.body != outputs_body, "Download operation should modify the original outputs body."
            output = result.body.get("output", {})
            assert output.get("href") == output_href
            output_path = output.get("path")  # inserted by download
            assert isinstance(output_path, str) and output_path.startswith(target_dir)
            output_name = output_href.split(job_id)[-1][1:]  # everything after jobID, and without the first '/'
            output_file = os.path.join(target_dir, output_name)
            assert output_path == output_file
            assert os.path.isfile(output_file) and not os.path.islink(output_file)
            assert len(server_mock.calls) == 1  # list of (PreparedRequest, Response)
            assert server_mock.calls[0][0].url == output_href
Exemplo n.º 3
0
    def test_vault_encrypted_decrypted_contents(self):
        """
        Validate that Vault file gets encrypted on upload, that description still works, and is decrypted on download.
        """
        # upload file
        data = {"fake": "data"}
        text = json.dumps(data)
        with tempfile.NamedTemporaryFile(suffix=".json",
                                         mode="w+") as tmp_file:
            tmp_file.write(text)
            tmp_file.seek(0)
            tmp_name = os.path.split(tmp_file.name)[-1]
            lines = mocked_sub_requests(
                self.app,
                run_command,
                [
                    # weaver
                    "upload",
                    "-u",
                    self.url,
                    "-f",
                    tmp_file.name,
                ],
                trim=False,
                entrypoint=weaver_cli,
                only_local=True,
            )
        result = json.loads("\n".join(lines))
        assert "file_id" in result

        # check encrypted contents in vault
        vault_dir = self.settings.get("weaver.vault_dir")
        vault_id = result["file_id"]
        vault_path = os.path.join(vault_dir, vault_id, tmp_name)
        with open(vault_path, mode="r", encoding="utf-8") as vault_fd:
            vault_data = vault_fd.read()
        assert vault_data != data
        assert "{" not in vault_data
        assert vault_data.endswith("=")

        # check details
        vault_token = result["access_token"]
        vault_url = f"/vault/{vault_id}"
        resp = mocked_sub_requests(self.app,
                                   "HEAD",
                                   vault_url,
                                   headers={"X-Auth-Vault": vault_token})
        assert resp.status_code == 200
        assert resp.headers["Content-Type"].startswith(ContentType.APP_JSON)

        # check download decrypted
        resp = mocked_sub_requests(self.app,
                                   "GET",
                                   vault_url,
                                   headers={"X-Auth-Vault": vault_token})
        assert resp.status_code == 200
        assert resp.text == text
Exemplo n.º 4
0
    def test_undeploy(self):
        # deploy a new process to leave the test one available
        other_payload = copy.deepcopy(self.test_payload)
        other_process = self.test_process + "-other"
        self.deploy_process(other_payload, process_id=other_process)

        result = mocked_sub_requests(self.app, self.client.undeploy, other_process)
        assert result.success
        assert result.body.get("undeploymentDone", None) is True
        assert "undefined" not in result.message

        path = f"/processes/{other_process}"
        resp = mocked_sub_requests(self.app, "get", path, expect_errors=True)
        assert resp.status_code == 404
Exemplo n.º 5
0
    def deploy_process(cls, payload):
        # type: (JSON) -> JSON
        """
        Deploys a process with :paramref:`payload`.

        :returns: resulting tuple of ``(process-description, package)`` JSON responses.
        """
        resp = mocked_sub_requests(cls.app,
                                   "post_json",
                                   "/processes",
                                   data=payload,
                                   headers=cls.json_headers)
        # TODO: status should be 201 when properly modified to match API conformance
        assert resp.status_code == 200, "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 pkg_url in [path, "{}/package".format(path)]:
            resp = cls.app.get(pkg_url, headers=cls.json_headers)
            assert resp.status_code == 200
            info.append(deepcopy(resp.json))
        return info
Exemplo n.º 6
0
 def run_execute_inputs_schema_variant(self, inputs_param, preload=False, expect_success=True, mock_exec=True):
     if isinstance(inputs_param, str):
         if preload:
             inputs_param = self.load_resource_file(inputs_param)
         else:
             inputs_param = self.get_resource_file(inputs_param)
     with contextlib.ExitStack() as stack_exec:
         # use pass-through function because don't care about execution result here, only the parsing of I/O
         if mock_exec:
             mock_exec_func = lambda *_, **__: None  # noqa
         else:
             mock_exec_func = None
         for mock_exec_proc in mocked_execute_process(func_execute_process=mock_exec_func):
             stack_exec.enter_context(mock_exec_proc)
         result = mocked_sub_requests(self.app, self.client.execute, self.test_process, inputs=inputs_param)
     if expect_success:
         assert result.success, result.text
         assert "jobID" in result.body
         assert "processID" in result.body
         assert "status" in result.body
         assert "location" in result.body
         assert result.body["processID"] == self.test_process
         assert result.body["status"] == STATUS_ACCEPTED
         assert result.body["location"] == result.headers["Location"]
         assert "undefined" not in result.message
     else:
         assert not result.success, result.text
     return result
Exemplo n.º 7
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
Exemplo n.º 8
0
    def test_deploy_payload_file_cwl_embedded(self):
        test_id = f"{self.test_process_prefix}-deploy-file-no-cwl"
        payload = self.load_resource_file("DeployProcess_Echo.yml")
        package = self.get_resource_file("echo.cwl")
        payload["executionUnit"][0] = {"href": package}

        with tempfile.NamedTemporaryFile(mode="w", suffix=".cwl") as body_file:
            json.dump(payload, body_file)
            body_file.flush()
            body_file.seek(0)

            lines = mocked_sub_requests(
                self.app, run_command,
                [
                    # weaver
                    "deploy",
                    "-p", test_id,
                    "-b", body_file.name,
                    self.url
                ],
                trim=False,
                entrypoint=weaver_cli,
                only_local=True,
            )
            assert any(f"\"id\": \"{test_id}\"" in line for line in lines)
            assert any("\"deploymentDone\": true" in line for line in lines)
Exemplo n.º 9
0
 def test_dismiss(self):
     for status in [STATUS_ACCEPTED, STATUS_FAILED, STATUS_RUNNING, STATUS_SUCCEEDED]:
         job = self.job_store.save_job(task_id="12345678-1111-2222-3333-111122223333", process=self.test_process)
         job.status = status
         job = self.job_store.update_job(job)
         result = mocked_sub_requests(self.app, self.client.dismiss, str(job.id))
         assert result.success
         assert "undefined" not in result.message
Exemplo n.º 10
0
    def test_execute_manual_monitor(self):
        with contextlib.ExitStack() as stack_exec:
            for mock_exec_proc in mocked_execute_process():
                stack_exec.enter_context(mock_exec_proc)

            lines = mocked_sub_requests(
                self.app, run_command,
                [
                    # "weaver",
                    "execute",
                    self.url,
                    "-p", self.test_process,
                    "-I", "message='TEST MESSAGE!'"
                ],
                trim=False,
                entrypoint=weaver_cli,
                only_local=True,
            )
            # ignore indents of fields from formatted JSON content
            assert any(f"\"processID\": \"{self.test_process}\"" in line for line in lines)
            assert any("\"jobID\": \"" in line for line in lines)
            assert any("\"location\": \"" in line for line in lines)
            job_loc = [line for line in lines if "location" in line][0]
            job_ref = [line for line in job_loc.split("\"") if line][-1]
            job_id = job_ref.split("/")[-1]

            lines = mocked_sub_requests(
                self.app, run_command,
                [
                    # "weaver",
                    "monitor",
                    "-j", job_ref,
                    "-T", 10,
                    "-W", 1,
                ],
                trim=False,
                entrypoint=weaver_cli,
                only_local=True,
            )

            assert any(f"\"jobID\": \"{job_id}\"" in line for line in lines)
            assert any(f"\"status\": \"{STATUS_SUCCEEDED}\"" in line for line in lines)
            assert any(f"\"href\": \"{job_ref}/results\"" in line for line in lines)
            assert any("\"rel\": \"http://www.opengis.net/def/rel/ogc/1.0/results\"" in line for line in lines)
Exemplo n.º 11
0
    def test_quote_atomic_process(self, mocked_estimate):
        with contextlib.ExitStack() as stack_quote:
            for mock_quote in mocked_execute_celery(
                    celery_task=
                    "weaver.quotation.estimation.process_quote_estimator"):
                stack_quote.enter_context(mock_quote)

            data = {
                "inputs": {
                    "message": "test quote"
                },
                "outputs": {
                    "output": {
                        "transmissionMode": ExecuteTransmissionMode.VALUE
                    }
                }
            }
            path = sd.process_quotes_service.path.format(process_id="Echo")
            resp = mocked_sub_requests(self.app,
                                       "POST",
                                       path,
                                       json=data,
                                       headers=self.json_headers,
                                       only_local=True)
            assert resp.status_code == 202  # 'Accepted' async task, but already finished by skipping celery
            assert mocked_estimate.called
            body = resp.json
            assert body["status"] == QuoteStatus.SUBMITTED

            path = sd.process_quote_service.path.format(process_id="Echo",
                                                        quote_id=body["id"])
            resp = mocked_sub_requests(self.app,
                                       "GET",
                                       path,
                                       headers=self.json_headers,
                                       only_local=True)
            assert resp.status_code == 200
            body = resp.json
            assert body["status"] == QuoteStatus.COMPLETED
            assert isinstance(body["price"], float) and body["price"] > 0
            assert isinstance(body["currency"],
                              str) and body["currency"] == "CAD"
            assert isinstance(body["estimatedSeconds"],
                              int) and body["estimatedSeconds"] > 0
Exemplo n.º 12
0
    def test_jsonarray2netcdf_execute_async_output_by_reference_dontcare_response_document(
            self):
        """
        Jobs submitted with ``response=document`` are not impacted by ``transmissionMode``.

        The results schema should always be returned when document is requested.

        .. seealso::
            https://docs.ogc.org/is/18-062r2/18-062r2.html#req_core_process-execute-sync-document
        """
        with contextlib.ExitStack() as stack_exec:
            body, nc_data = self.setup_inputs(stack_exec)
            body.update({
                "response":
                ExecuteResponse.
                DOCUMENT,  # by value/reference don't care because of this
                "outputs": [{
                    "id":
                    "output",
                    "transmissionMode":
                    ExecuteTransmissionMode.REFERENCE
                }],
            })
            for mock_exec in mocked_execute_celery():
                stack_exec.enter_context(mock_exec)
            path = "/processes/jsonarray2netcdf/jobs"
            resp = mocked_sub_requests(self.app,
                                       "post_json",
                                       path,
                                       data=body,
                                       headers=self.json_headers,
                                       only_local=True)

        assert resp.content_type in ContentType.APP_JSON
        assert resp.status_code == 201, f"Error: {resp.json}"
        job_url = resp.json["location"]
        self.monitor_job(
            job_url, return_status=True)  # don't fetch results automatically

        resp = self.app.get(f"{job_url}/results", headers=self.json_headers)
        assert resp.status_code == 200, f"Error: {resp.text}"
        assert resp.content_type == ContentType.APP_JSON
        result_links = [
            hdr for hdr in resp.headers if hdr[0].lower() == "link"
        ]
        assert len(result_links) == 0
        results = resp.json

        # even though results are requested by Link reference,
        # Weaver still offers them with document on outputs endpoint
        output_url = job_url + "/outputs"
        resp = self.app.get(output_url, headers=self.json_headers)
        assert resp.status_code == 200, f"Error job outputs:\n{resp.text}"
        outputs = resp.json

        self.validate_results(results, outputs, nc_data, result_links)
Exemplo n.º 13
0
 def test_quote_bad_inputs(self):
     path = sd.process_quotes_service.path.format(process_id="Echo")
     data = {"inputs": [1, 2, 3]}
     resp = mocked_sub_requests(self.app,
                                "POST",
                                path,
                                json=data,
                                headers=self.json_headers,
                                only_local=True)
     assert resp.status_code == 400
Exemplo n.º 14
0
    def test_jsonarray2netcdf_execute_async_output_by_value_response_raw(self):
        """
        Jobs submitted with ``response=raw`` and single output as ``transmissionMode=value`` must return its raw data.

        .. seealso::
            https://docs.ogc.org/is/18-062r2/18-062r2.html#req_core_process-execute-sync-raw-value-one
        """
        with contextlib.ExitStack() as stack_exec:
            body, nc_data = self.setup_inputs(stack_exec)
            body.update({
                "response":
                ExecuteResponse.RAW,  # by value/reference important here
                # NOTE: quantity of outputs important as well
                #       since single output, content-type is directly that output (otherwise should be multipart)
                "outputs": [{
                    "id": "output",
                    "transmissionMode": ExecuteTransmissionMode.VALUE
                }],  # data dump
            })
            for mock_exec in mocked_execute_celery():
                stack_exec.enter_context(mock_exec)
            path = "/processes/jsonarray2netcdf/jobs"
            resp = mocked_sub_requests(self.app,
                                       "post_json",
                                       path,
                                       data=body,
                                       headers=self.json_headers,
                                       only_local=True)

        assert resp.content_type in ContentType.APP_JSON
        assert resp.status_code == 201, f"Error: {resp.json}"
        job_url = resp.json["location"]
        self.monitor_job(
            job_url, return_status=True)  # don't fetch results automatically

        resp = self.app.get(f"{job_url}/results", headers=self.json_headers)
        assert resp.status_code < 400, f"Error: {resp.text}"
        assert resp.status_code == 200, "Body should contain literal raw data dump"
        assert resp.content_type in ContentType.APP_NETCDF, "raw result by value should be directly the content-type"
        assert resp.text == nc_data, "raw result by value should be directly the data content"
        assert resp.headers
        result_links = [
            hdr for hdr in resp.headers if hdr[0].lower() == "link"
        ]
        assert len(result_links) == 0

        # even though results are requested by raw data,
        # Weaver still offers them with document on outputs endpoint
        output_url = job_url + "/outputs"
        resp = self.app.get(output_url, headers=self.json_headers)
        assert resp.status_code == 200, f"Error job outputs:\n{resp.text}"
        outputs = resp.json

        self.validate_results(None, outputs, nc_data, result_links)
Exemplo n.º 15
0
    def test_jsonarray2netcdf_execute_async_output_by_reference_response_raw(
            self):
        """
        Jobs submitted with ``response=raw`` and single output as ``transmissionMode=reference`` must a link.

        Contents should be empty, and the reference should be provided with HTTP ``Link`` header.

        .. seealso::
            https://docs.ogc.org/is/18-062r2/18-062r2.html#req_core_process-execute-sync-raw-ref
        """
        with contextlib.ExitStack() as stack_exec:
            body, nc_data = self.setup_inputs(stack_exec)
            body.update({
                "response":
                ExecuteResponse.RAW,  # by value/reference important here
                "outputs": [{
                    "id":
                    "output",
                    "transmissionMode":
                    ExecuteTransmissionMode.REFERENCE
                }],  # Link header
            })
            for mock_exec in mocked_execute_celery():
                stack_exec.enter_context(mock_exec)
            path = "/processes/jsonarray2netcdf/jobs"
            resp = mocked_sub_requests(self.app,
                                       "post_json",
                                       path,
                                       data=body,
                                       headers=self.json_headers,
                                       only_local=True)

        assert resp.content_type in ContentType.APP_JSON
        assert resp.status_code == 201, f"Error: {resp.json}"
        job_url = resp.json["location"]
        self.monitor_job(
            job_url, return_status=True)  # don't fetch results automatically

        resp = self.app.get(f"{job_url}/results", headers=self.json_headers)
        assert resp.status_code < 400, f"Error: {resp.text}"
        assert resp.status_code == 204, "Body should be empty since all outputs requested by reference (Link header)"
        assert resp.content_type is None
        assert resp.headers
        result_links = [hdr for hdr in resp.headers if hdr[0] == "Link"]

        # even though results are requested by Link reference,
        # Weaver still offers them with document on outputs endpoint
        resp = self.app.get(f"{job_url}/outputs", headers=self.json_headers)
        assert resp.status_code == 200, f"Error job outputs:\n{resp.json}"
        outputs = resp.json

        self.validate_results(None, outputs, nc_data, result_links)
Exemplo n.º 16
0
    def test_quote_workflow_process(self, mocked_estimate):
        with contextlib.ExitStack() as stack_quote:
            for mock_quote in mocked_execute_celery(
                    celery_task=
                    "weaver.quotation.estimation.process_quote_estimator"):
                stack_quote.enter_context(mock_quote)

            path = os.path.join(APP_PKG_ROOT, "WorkflowChainStrings",
                                "execute.json")
            with open(path, mode="r", encoding="utf-8") as exec_file:
                data = yaml.safe_load(exec_file)
            path = sd.process_quotes_service.path.format(
                process_id="WorkflowChainStrings")
            resp = mocked_sub_requests(self.app,
                                       "POST",
                                       path,
                                       json=data,
                                       headers=self.json_headers,
                                       only_local=True)
            assert resp.status_code == 202  # 'Accepted' async task, but already finished by skipping celery
            assert mocked_estimate.called
            body = resp.json
            assert body["status"] == QuoteStatus.SUBMITTED

            path = sd.process_quote_service.path.format(process_id="Echo",
                                                        quote_id=body["id"])
            resp = mocked_sub_requests(self.app,
                                       "GET",
                                       path,
                                       headers=self.json_headers,
                                       only_local=True)
            assert resp.status_code == 200
            body = resp.json
            assert body["status"] == QuoteStatus.COMPLETED
            assert isinstance(body["price"], float) and body["price"] > 0
            assert isinstance(body["currency"],
                              str) and body["currency"] == "CAD"
            assert isinstance(body["estimatedSeconds"],
                              int) and body["estimatedSeconds"] > 0
Exemplo n.º 17
0
    def test_deploy_payload_body_cwl_embedded(self):
        test_id = f"{self.test_process_prefix}-deploy-body-no-cwl"
        payload = self.load_resource_file("DeployProcess_Echo.yml")
        package = self.load_resource_file("echo.cwl")
        payload["executionUnit"][0] = {"unit": package}

        result = mocked_sub_requests(self.app, self.client.deploy, test_id, payload)
        assert result.success
        assert "processSummary" in result.body
        assert result.body["processSummary"]["id"] == test_id
        assert "deploymentDone" in result.body
        assert result.body["deploymentDone"] is True
        assert "undefined" not in result.message
Exemplo n.º 18
0
    def test_deploy_payload_inject_cwl_file(self):
        test_id = f"{self.test_process_prefix}-deploy-body-with-cwl-file"
        payload = self.load_resource_file("DeployProcess_Echo.yml")
        package = self.get_resource_file("echo.cwl")
        payload.pop("executionUnit", None)

        result = mocked_sub_requests(self.app, self.client.deploy, test_id, payload, package)
        assert result.success
        assert "processSummary" in result.body
        assert result.body["processSummary"]["id"] == test_id
        assert "deploymentDone" in result.body
        assert result.body["deploymentDone"] is True
        assert "undefined" not in result.message
Exemplo n.º 19
0
 def process_listing_op(self, operation):
     result = mocked_sub_requests(self.app, operation)
     assert result.success
     assert "processes" in result.body
     assert set(result.body["processes"]) == {
         # builtin
         "file2string_array",
         "file_index_selector",
         "jsonarray2netcdf",
         "metalink2netcdf",
         # test process
         self.test_process,
     }
     assert "undefined" not in result.message
Exemplo n.º 20
0
    def test_execute_wps_rest_resp_json(self):
        """
        Test validates that basic Docker application runs successfully, fetching the reference as needed.

        The job execution is launched using the WPS-REST endpoint for this test.
        Both the request body and response content are JSON.

        .. seealso::
            - :meth:`test_execute_wps_kvp_get_resp_xml`
            - :meth:`test_execute_wps_kvp_get_resp_json`
            - :meth:`test_execute_wps_xml_post_resp_xml`
            - :meth:`test_execute_wps_xml_post_resp_json`
        """

        test_content = "Test file in Docker - WPS-REST job endpoint"
        with contextlib.ExitStack() as stack_exec:
            # setup
            dir_name = tempfile.gettempdir()
            tmp_path = tempfile.NamedTemporaryFile(dir=dir_name, mode="w", suffix=".txt")
            tmp_file = stack_exec.enter_context(tmp_path)  # noqa
            tmp_file.write(test_content)
            tmp_file.seek(0)
            exec_body = {
                "mode": EXECUTE_MODE_ASYNC,
                "response": EXECUTE_RESPONSE_DOCUMENT,
                "inputs": [
                    {"id": "file", "href": tmp_file.name},
                ],
                "outputs": [
                    {"id": self.out_key, "transmissionMode": EXECUTE_TRANSMISSION_MODE_REFERENCE},
                ]
            }
            for mock_exec in mocked_execute_process():
                stack_exec.enter_context(mock_exec)

            # execute
            proc_url = "/processes/{}/jobs".format(self.process_id)
            resp = mocked_sub_requests(self.app, "post_json", proc_url,
                                       data=exec_body, headers=self.json_headers, only_local=True)
            assert resp.status_code in [200, 201], "Failed with: [{}]\nReason:\n{}".format(resp.status_code, resp.json)
            status_url = resp.json["location"]
            job_id = resp.json["jobID"]

            # job monitoring
            result = self.monitor_job(status_url)

        self.validate_outputs(job_id, result, test_content)
Exemplo n.º 21
0
 def test_log_options_any_level(self):
     """
     Logging parameters should be allowed at main parser level or under any operation subparser.
     """
     for options in [
         ["--verbose", "describe", self.url, "-p", self.test_process],
         ["describe", self.url, "--verbose", "-p", self.test_process],
         ["describe", self.url, "-p", self.test_process, "--verbose"],
     ]:
         lines = mocked_sub_requests(
             self.app, run_command,
             options,
             trim=False,
             entrypoint=weaver_cli,
             only_local=True,
         )
         assert any(f"\"id\": \"{self.test_process}\"" in line for line in lines)
Exemplo n.º 22
0
    def test_deploy_payload_file_cwl_embedded(self):
        test_id = f"{self.test_process_prefix}-deploy-file-no-cwl"
        payload = self.load_resource_file("DeployProcess_Echo.yml")
        package = self.get_resource_file("echo.cwl")
        payload["executionUnit"][0] = {"href": package}

        with tempfile.NamedTemporaryFile(mode="w", suffix=".cwl") as body_file:
            json.dump(payload, body_file)
            body_file.flush()
            body_file.seek(0)
            result = mocked_sub_requests(self.app, self.client.deploy, test_id, body_file.name)
        assert result.success
        assert "processSummary" in result.body
        assert result.body["processSummary"]["id"] == test_id
        assert "deploymentDone" in result.body
        assert result.body["deploymentDone"] is True
        assert "undefined" not in result.message
Exemplo n.º 23
0
 def test_describe(self):
     # prints formatted JSON ProcessDescription over many lines
     lines = mocked_sub_requests(
         self.app, run_command,
         [
             # "weaver",
             "describe",
             self.url,
             "-p", self.test_process,
         ],
         trim=False,
         entrypoint=weaver_cli,
         only_local=True,
     )
     # ignore indents of fields from formatted JSON content
     assert any(f"\"id\": \"{self.test_process}\"" in line for line in lines)
     assert any("\"inputs\": {" in line for line in lines)
     assert any("\"outputs\": {" in line for line in lines)
Exemplo n.º 24
0
 def test_deploy_no_process_id_option(self):
     payload = self.get_resource_file("DeployProcess_Echo.yml")
     package = self.get_resource_file("echo.cwl")
     lines = mocked_sub_requests(
         self.app, run_command,
         [
             # weaver
             "deploy",
             "--body", payload,  # no --process/--id, but available through --body
             "--cwl", package,
             self.url
         ],
         trim=False,
         entrypoint=weaver_cli,
         only_local=True,
     )
     assert any("\"id\": \"Echo\"" in line for line in lines)
     assert any("\"deploymentDone\": true" in line for line in lines)
Exemplo n.º 25
0
 def test_describe(self):
     result = mocked_sub_requests(self.app, self.client.describe, self.test_process)
     assert result.success
     # see deployment file for details that are expected here
     assert result.body["id"] == self.test_process
     assert result.body["version"] == "1.0"
     assert result.body["keywords"] == ["test", "application"]  # app is added by Weaver since not CWL Workflow
     assert "message" in result.body["inputs"]
     assert result.body["inputs"]["message"]["title"] == "message"
     assert result.body["inputs"]["message"]["description"] == "Message to echo."
     assert result.body["inputs"]["message"]["minOccurs"] == 1
     assert result.body["inputs"]["message"]["maxOccurs"] == 1
     assert result.body["inputs"]["message"]["literalDataDomains"][0]["dataType"]["name"] == "string"
     assert "output" in result.body["outputs"]
     assert result.body["outputs"]["output"]["title"] == "output"
     assert result.body["outputs"]["output"]["description"] == "Output file with echo message."
     assert result.body["outputs"]["output"]["formats"] == [{"default": True, "mediaType": CONTENT_TYPE_TEXT_PLAIN}]
     assert "undefined" not in result.message, "CLI should not have confused process description as response detail."
     assert "description" not in result.body, "CLI should not have overridden the process description field."
Exemplo n.º 26
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"
Exemplo n.º 27
0
 def test_execute_invalid_format(self):
     bad_input_value = "'this is my malformed message'"  # missing '<id>=' portion
     lines = mocked_sub_requests(
         self.app, run_command,
         [
             # "weaver",
             "execute",
             self.url,
             "-p", self.test_process,
             "-I", bad_input_value,
             "-M",
             "-T", 10,
             "-W", 1
         ],
         trim=False,
         entrypoint=weaver_cli,
         expect_error=True,
         only_local=True,
     )
     assert any(bad_input_value in line for line in lines)
Exemplo n.º 28
0
    def test_deploy_payload_body_cwl_embedded(self):
        test_id = f"{self.test_process_prefix}-deploy-body-no-cwl"
        payload = self.load_resource_file("DeployProcess_Echo.yml")
        package = self.load_resource_file("echo.cwl")
        payload["executionUnit"][0] = {"unit": package}

        lines = mocked_sub_requests(
            self.app, run_command,
            [
                # weaver
                "deploy",
                "-p", test_id,
                "-b", json.dumps(payload),  # literal JSON string accepted for CLI
                self.url
            ],
            trim=False,
            entrypoint=weaver_cli,
            only_local=True,
        )
        assert any(f"\"id\": \"{test_id}\"" in line for line in lines)
        assert any("\"deploymentDone\": true" in line for line in lines)
Exemplo n.º 29
0
    def test_jsonarray2netcdf_execute_async(self):
        with contextlib.ExitStack() as stack_exec:
            body, nc_data = self.setup_inputs(stack_exec)
            body.update({
                "mode":
                ExecuteMode.ASYNC,
                "response":
                ExecuteResponse.DOCUMENT,
                "outputs": [{
                    "id": "output",
                    "transmissionMode": ExecuteTransmissionMode.VALUE
                }],
            })
            for mock_exec in mocked_execute_celery():
                stack_exec.enter_context(mock_exec)
            path = "/processes/jsonarray2netcdf/jobs"
            resp = mocked_sub_requests(self.app,
                                       "post_json",
                                       path,
                                       data=body,
                                       headers=self.json_headers,
                                       only_local=True)

        assert resp.status_code == 201, f"Error: {resp.json}"
        assert resp.content_type in ContentType.APP_JSON
        # following details not available yet in async, but are in sync
        assert "created" not in resp.json
        assert "finished" not in resp.json
        assert "duration" not in resp.json
        assert "progress" not in resp.json

        job_url = resp.json["location"]
        results = self.monitor_job(job_url)

        output_url = job_url + "/outputs"
        resp = self.app.get(output_url, headers=self.json_headers)
        assert resp.status_code == 200, f"Error job outputs:\n{resp.json}"
        outputs = resp.json

        self.validate_results(results, outputs, nc_data, None)
Exemplo n.º 30
0
    def test_deploy_payload_inject_cwl_file(self):
        test_id = f"{self.test_process_prefix}-deploy-body-with-cwl-file"
        payload = self.load_resource_file("DeployProcess_Echo.yml")
        package = self.get_resource_file("echo.cwl")
        payload.pop("executionUnit", None)

        lines = mocked_sub_requests(
            self.app, run_command,
            [
                # weaver
                "deploy",
                "-p", test_id,
                "--body", json.dumps(payload),  # literal JSON string accepted for CLI
                "--cwl", package,
                self.url
            ],
            trim=False,
            entrypoint=weaver_cli,
            only_local=True,
        )
        assert any(f"\"id\": \"{test_id}\"" in line for line in lines)
        assert any("\"deploymentDone\": true" in line for line in lines)