Beispiel #1
0
        def stop_service_handler(url: URL, **kwargs):
            service_uuid = url.parts[-1]
            required_query_parameter = "save_state"
            if required_query_parameter not in kwargs["params"]:
                return CallbackResult(
                    payload={
                        "error": f"stop_service endpoint was called without query parameter {required_query_parameter} {url}"
                    },
                    status=500,
                )

            try:
                service = next(
                    s
                    for s in _fake_running_services
                    if s["service_uuid"] == service_uuid
                )
                service["service_state"] = "complete"

            except StopIteration:
                return CallbackResult(
                    payload={"error": "service not found"}, status=404
                )

            return CallbackResult(status=204)
    def get_stacks_cb(url, **kwargs) -> CallbackResult:
        if not _check_auth(**kwargs):
            return CallbackResult(status=401)

        return CallbackResult(
            status=200,
            payload=portainer_stacks,
        )
 def get_docker_swarm_cb(url, **kwargs) -> CallbackResult:
     if not _check_auth(**kwargs):
         return CallbackResult(status=401)
     # returns the docker API /swarm endpoint
     return CallbackResult(
         status=200,
         payload={"ID": "abajmipo7b4xz5ip2nrla6b11"},
     )
    def get_endpoints_cb(url, **kwargs) -> CallbackResult:
        if not _check_auth(**kwargs):
            return CallbackResult(status=401)

        return CallbackResult(
            status=200,
            payload=[
                {"Name": valid_config["main"]["portainer"][0]["stack_name"], "Id": 1}
            ],
        )
Beispiel #5
0
    def get_download_link_cb(url: URL, **kwargs) -> CallbackResult:
        file_id = url.path.rsplit("/files/")[1]

        return CallbackResult(status=200,
                              payload={"data": {
                                  "link": f"file://{file_id}"
                              }})
        def get_service_by_key_version_handler(url: URL, **kwargs):
            service_key, service_version = url.parts[-2:]
            # TODO: validate against schema?
            # TODO: improve API: does it make sense to return multiple services
            services = [
                s for s in _fake_project_services
                if s["key"] == service_key and s["version"] == service_version
            ]
            if services:
                return CallbackResult(payload={"data": services}, status=200)

            return CallbackResult(
                payload={
                    "error":
                    f"Service {service_key}:{service_version} not found in project"
                },
                status=404,
            )
    def create_stack_cb(url, **kwargs) -> CallbackResult:
        if not _check_auth(**kwargs):
            return CallbackResult(status=401)

        if "json" not in kwargs:
            return CallbackResult(status=400)
        body = kwargs["json"]

        return CallbackResult(
            status=200,
            payload={
                "SwarmID": body["SwarmID"],
                "Name": body["Name"],
                "EndpointID": url.query["endpointId"],
                "Type": url.query["type"],
                "Id": randint(1, 10),
            },
        )
        def start_service_handler(url: URL, **kwargs):
            assert int(url.query["user_id"]) == user_id
            assert url.query["project_id"] == project_id

            service_uuid = url.query["service_uuid"]

            if any(s["service_uuid"] == service_uuid for s in _get_running()):
                return CallbackResult(
                    payload={
                        "error":
                        f"A service with the same uuid {service_uuid} already running exists"
                    },
                    status=409,
                )

            service_key = url.query["service_key"]
            service_tag = url.query.get("service_tag")

            try:
                service = next(
                    s for s in _fake_project_services
                    if s["key"] == service_key and s["version"] == service_tag)
            except StopIteration:
                return CallbackResult(
                    payload={
                        "error":
                        f"Service {service_key}:{service_tag} not found in project"
                    },
                    status=404,
                )

            starting_service = fake_running_service_model(
                service_key=service["key"],
                service_version=service["version"],
                service_basepath=url.query.get(
                    "service_basepath", ""
                ),  # predefined basepath for the backend service otherwise uses root
                service_state="starting",  # let's assume it pulls very fast :-)
            )

            _fake_running_services.append(starting_service)
            return CallbackResult(payload={"data": starting_service},
                                  status=201)
def creation_cb(url, **kwargs):

    assert "json" in kwargs, f"missing body in call to {url}"
    body = kwargs["json"]
    for param in ["user_id", "project_id"]:
        assert param in body, f"{param} is missing from body: {body}"
    state = (RunningState.PUBLISHED if "start_pipeline" in body
             and body["start_pipeline"] else RunningState.NOT_STARTED)

    return CallbackResult(status=201,
                          payload={
                              "id": kwargs["json"]["project_id"],
                              "state": state
                          })
Beispiel #10
0
def creation_cb(url, **kwargs) -> CallbackResult:

    assert "json" in kwargs, f"missing body in call to {url}"
    body = kwargs["json"]
    for param in ["user_id", "project_id"]:
        assert param in body, f"{param} is missing from body: {body}"
    state = (RunningState.PUBLISHED if "start_pipeline" in body
             and body["start_pipeline"] else RunningState.NOT_STARTED)
    pipeline: Dict[str, List[str]] = FULL_PROJECT_PIPELINE_ADJACENCY
    node_states = FULL_PROJECT_NODE_STATES
    if body.get("subgraph"):
        # create some fake adjacency list
        pipeline = {}
        node_states = {}
        for node_id in body.get("subgraph"):
            pipeline[node_id] = [
                "62237c33-8d6c-4709-aa92-c3cf693dd6d2",
                "0bdf824f-57cb-4e38-949e-fd12c184f000",
            ]
            node_states[node_id] = {
                "state": {
                    "modified": True,
                    "dependencies": []
                }
            }
        node_states["62237c33-8d6c-4709-aa92-c3cf693dd6d2"] = {
            "modified": True,
            "dependencies": ["2f493631-30b4-4ad8-90f2-a74e4b46fe73"],
        }
        node_states["0bdf824f-57cb-4e38-949e-fd12c184f000"] = {
            "modified":
            True,
            "dependencies": [
                "2f493631-30b4-4ad8-90f2-a74e4b46fe73",
                "62237c33-8d6c-4709-aa92-c3cf693dd6d2",
            ],
        }

    return CallbackResult(
        status=201,
        payload={
            "id": kwargs["json"]["project_id"],
            "state": state,
            "pipeline_details": {
                "adjacency_list": pipeline,
                "node_states": node_states,
            },
        },
    )
Beispiel #11
0
def get_computation_cb(url, **kwargs) -> CallbackResult:
    state = RunningState.NOT_STARTED
    pipeline: Dict[str, List[str]] = FULL_PROJECT_PIPELINE_ADJACENCY
    node_states = FULL_PROJECT_NODE_STATES

    return CallbackResult(
        status=202,
        payload={
            "id": Path(url.path).name,
            "state": state,
            "pipeline_details": {
                "adjacency_list": pipeline,
                "node_states": node_states,
            },
        },
    )
async def _start_get_stop_services(
    client,
    push_services,
    user_id,
    project_id,
    api_version_prefix: str,
    save_state: Optional[bool],
    expected_save_state_call: bool,
    mocker,
):
    params = {}
    web_response = await client.post(
        f"/{api_version_prefix}/running_interactive_services", params=params)
    assert web_response.status == 400

    params = {
        "user_id": "None",
        "project_id": "None",
        "service_uuid": "sdlfkj4",
        "service_key": "None",
        "service_tag": "None",  # optional
        "service_basepath": "None",  # optional
    }
    web_response = await client.post(
        f"/{api_version_prefix}/running_interactive_services", params=params)
    data = await web_response.json()
    assert web_response.status == 400, data

    params["service_key"] = "simcore/services/comp/somfunkyname-nhsd"
    params["service_tag"] = "1.2.3"
    web_response = await client.post(
        f"/{api_version_prefix}/running_interactive_services", params=params)
    data = await web_response.json()
    assert web_response.status == 404, data

    created_services = await push_services(0, 2)
    assert len(created_services) == 2
    for created_service in created_services:
        service_description = created_service["service_description"]
        params["user_id"] = user_id
        params["project_id"] = project_id
        params["service_key"] = service_description["key"]
        params["service_tag"] = service_description["version"]
        service_port = created_service["internal_port"]
        service_entry_point = created_service["entry_point"]
        params["service_basepath"] = "/i/am/a/basepath"
        params["service_uuid"] = str(uuid.uuid4())
        # start the service
        web_response = await client.post(
            f"/{api_version_prefix}/running_interactive_services",
            params=params)
        assert web_response.status == 201
        assert web_response.content_type == "application/json"
        running_service_enveloped = await web_response.json()
        assert isinstance(running_service_enveloped["data"], dict)
        assert all(k in running_service_enveloped["data"] for k in [
            "service_uuid",
            "service_key",
            "service_version",
            "published_port",
            "entry_point",
            "service_host",
            "service_port",
            "service_basepath",
        ])
        assert (running_service_enveloped["data"]["service_uuid"] ==
                params["service_uuid"])
        assert running_service_enveloped["data"]["service_key"] == params[
            "service_key"]
        assert (running_service_enveloped["data"]["service_version"] ==
                params["service_tag"])
        assert running_service_enveloped["data"][
            "service_port"] == service_port
        service_published_port = running_service_enveloped["data"][
            "published_port"]
        assert not service_published_port
        assert service_entry_point == running_service_enveloped["data"][
            "entry_point"]
        service_host = running_service_enveloped["data"]["service_host"]
        assert service_host == f"test_{params['service_uuid']}"
        service_basepath = running_service_enveloped["data"][
            "service_basepath"]
        assert service_basepath == params["service_basepath"]

        # get the service
        web_response = await client.request(
            "GET",
            f"/{api_version_prefix}/running_interactive_services/{params['service_uuid']}",
        )
        assert web_response.status == 200
        text = await web_response.text()
        assert web_response.content_type == "application/json", text
        running_service_enveloped = await web_response.json()
        assert isinstance(running_service_enveloped["data"], dict)
        assert all(k in running_service_enveloped["data"] for k in [
            "service_uuid",
            "service_key",
            "service_version",
            "published_port",
            "entry_point",
        ])
        assert (running_service_enveloped["data"]["service_uuid"] ==
                params["service_uuid"])
        assert running_service_enveloped["data"]["service_key"] == params[
            "service_key"]
        assert (running_service_enveloped["data"]["service_version"] ==
                params["service_tag"])
        assert (running_service_enveloped["data"]["published_port"] ==
                service_published_port)
        assert running_service_enveloped["data"][
            "entry_point"] == service_entry_point
        assert running_service_enveloped["data"][
            "service_host"] == service_host
        assert running_service_enveloped["data"][
            "service_port"] == service_port
        assert running_service_enveloped["data"][
            "service_basepath"] == service_basepath

        # stop the service
        query_params = {}
        if save_state:
            query_params.update(
                {"save_state": "true" if save_state else "false"})

        mocked_save_state_cb = mocker.MagicMock(
            return_value=CallbackResult(status=200, payload={}))
        PASSTHROUGH_REQUESTS_PREFIXES = [
            "http://127.0.0.1",
            "http://localhost",
            "unix://",  # docker engine
            "ws://",  # websockets
        ]
        with aioresponses(passthrough=PASSTHROUGH_REQUESTS_PREFIXES) as mock:

            # POST /http://service_host:service_port service_basepath/state -------------------------------------------------
            mock.post(
                f"http://{service_host}:{service_port}{service_basepath}/state",
                status=200,
                callback=mocked_save_state_cb,
            )
            web_response = await client.delete(
                f"/{api_version_prefix}/running_interactive_services/{params['service_uuid']}",
                params=query_params,
            )
            if expected_save_state_call:
                mocked_save_state_cb.assert_called_once()

        text = await web_response.text()
        assert web_response.status == 204, text
        assert web_response.content_type == "application/json"
        data = await web_response.json()
        assert data is None
        def get_running_interactive_services_handler(url: URL, **kwargs):
            assert int(url.query.get("user_id", 0)) in (user_id, 0)
            assert url.query.get("project_id") in (project_id, None)

            return CallbackResult(payload={"data": _get_running()}, status=200)