def test_running_service_details_make_status(scheduler_data: SchedulerData, service_message: str, service_state: ServiceState): running_service_details = RunningDynamicServiceDetails.from_scheduler_data( node_uuid=scheduler_data.node_uuid, scheduler_data=scheduler_data, service_state=service_state, service_message=service_message, ) print(running_service_details) assert running_service_details running_service_details_dict = running_service_details.dict( exclude_unset=True, by_alias=True) expected_running_service_details = { "boot_type": ServiceBootType.V2, "project_id": scheduler_data.project_id, "service_state": service_state, "service_message": service_message, "service_uuid": scheduler_data.node_uuid, "service_key": scheduler_data.key, "service_version": scheduler_data.version, "service_host": scheduler_data.service_name, "user_id": scheduler_data.user_id, "service_port": scheduler_data.service_port, } assert running_service_details_dict == expected_running_service_details
async def test_get_stack_status( ensure_scheduler_runs_once: Callable, scheduler: DynamicSidecarsScheduler, scheduler_data: SchedulerData, docker_swarm: None, mocked_dynamic_scheduler_events: None, ) -> None: await ensure_scheduler_runs_once() await scheduler.add_service(scheduler_data) stack_status = await scheduler.get_stack_status(scheduler_data.node_uuid) assert stack_status == RunningDynamicServiceDetails.from_scheduler_data( node_uuid=scheduler_data.node_uuid, scheduler_data=scheduler_data, service_state=ServiceState.PENDING, service_message="", )
async def test_get_stack_status_containers_are_starting( scheduler: DynamicSidecarsScheduler, scheduler_data: SchedulerData, mock_service_running: AsyncMock, docker_swarm: None, mocked_dynamic_scheduler_events: None, ) -> None: async with _assert_get_dynamic_services_mocked( scheduler, scheduler_data, mock_service_running, expected_response=httpx.Response(200, json={}), ) as stack_status: assert stack_status == RunningDynamicServiceDetails.from_scheduler_data( node_uuid=scheduler_data.node_uuid, scheduler_data=scheduler_data, service_state=ServiceState.STARTING, service_message="", )
async def test_get_stack_status_failing_sidecar( scheduler: DynamicSidecarsScheduler, scheduler_data: SchedulerData, docker_swarm: None, mocked_dynamic_scheduler_events: None, ) -> None: failing_message = "some_failing_message" scheduler_data.dynamic_sidecar.status.update_failing_status( failing_message) await scheduler.add_service(scheduler_data) stack_status = await scheduler.get_stack_status(scheduler_data.node_uuid) assert stack_status == RunningDynamicServiceDetails.from_scheduler_data( node_uuid=scheduler_data.node_uuid, scheduler_data=scheduler_data, service_state=ServiceState.FAILED, service_message=failing_message, )
async def mock_retrieve_features( minimal_app: FastAPI, client: TestClient, service: Dict[str, Any], is_legacy: bool, scheduler_data_from_http_request: SchedulerData, ) -> AsyncIterator[Optional[MockRouter]]: with respx.mock( assert_all_called=False, assert_all_mocked=True, ) as respx_mock: if is_legacy: service_details = RunningDynamicServiceDetails.parse_obj( RunningDynamicServiceDetails.Config.schema_extra["examples"] [0]) respx_mock.post( f"{service_details.legacy_service_url}/retrieve", name="retrieve").respond(json=RetrieveDataOutEnveloped.Config. schema_extra["examples"][0]) yield respx_mock # no cleanup required else: dynamic_sidecar_scheduler = minimal_app.state.dynamic_sidecar_scheduler node_uuid = UUID(service["node_uuid"]) serice_name = "serice_name" # pylint: disable=protected-access dynamic_sidecar_scheduler._inverse_search_mapping[ node_uuid] = serice_name dynamic_sidecar_scheduler._to_observe[serice_name] = Namespace( scheduler_data=scheduler_data_from_http_request) respx_mock.post( f"{scheduler_data_from_http_request.dynamic_sidecar.endpoint}/v1/containers/ports/inputs:pull", name="service_pull_input_ports", ).respond(json=42) yield respx_mock dynamic_sidecar_scheduler._inverse_search_mapping.pop(node_uuid) dynamic_sidecar_scheduler._to_observe.pop(serice_name)
async def test_get_stack_status_report_missing_statuses( scheduler: DynamicSidecarsScheduler, scheduler_data: SchedulerData, mock_service_running: AsyncMock, docker_swarm: None, mocked_dynamic_scheduler_events: None, ) -> None: async with _assert_get_dynamic_services_mocked( scheduler, scheduler_data, mock_service_running, expected_response=httpx.HTTPError("Mock raised error"), ) as stack_status: assert stack_status == RunningDynamicServiceDetails.from_scheduler_data( node_uuid=scheduler_data.node_uuid, scheduler_data=scheduler_data, service_state=ServiceState.STARTING, service_message= "There was an error while trying to fetch the stautes form the contianers", )
def mocked_director_service_fcts( minimal_app: FastAPI, mock_service_key_version: ServiceKeyVersion, fake_service_details: ServiceDockerData, fake_service_extras: ServiceExtras, fake_service_labels: Dict[str, Any], fake_running_service_details: RunningDynamicServiceDetails, ): with respx.mock( base_url=minimal_app.state.settings.DIRECTOR_V0.endpoint, assert_all_called=False, assert_all_mocked=True, ) as respx_mock: quoted_key = urllib.parse.quote_plus(mock_service_key_version.key) version = mock_service_key_version.version respx_mock.get( f"/services/{quoted_key}/{version}", name="get_service_version").respond( json={"data": [fake_service_details.dict(by_alias=True)]}) respx_mock.get( f"/service_extras/{quoted_key}/{version}", name="get_service_extras").respond( json={"data": fake_service_extras.dict(by_alias=True)}) respx_mock.get(f"/services/{quoted_key}/{version}/labels", name="get_service_labels").respond( json={"data": fake_service_labels}) respx_mock.get( re.compile( r"running_interactive_services/[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$" ), name="get_running_service_details", ).respond(json={ "data": json.loads(fake_running_service_details.json(by_alias=True)) }) yield respx_mock
def test_regression_legacy_service_compatibility() -> None: api_response = { "published_port": None, "entry_point": "", "service_uuid": "e5aa2f7a-eac4-4522-bd4f-270b5d8d9fff", "service_key": "simcore/services/dynamic/mocked", "service_version": "1.6.10", "service_host": "mocked_e5aa2f7a-eac4-4522-bd4f-270b5d8d9fff", "service_port": 8888, "service_basepath": "/x/e5aa2f7a-eac4-4522-bd4f-270b5d8d9fff", "service_state": "running", "service_message": "", "user_id": "1", "project_id": "b1ec5c8e-f5bb-11eb-b1d5-02420a000006", } service_details = RunningDynamicServiceDetails.parse_obj(api_response) assert service_details service_url = f"http://{service_details.host}:{service_details.internal_port}{service_details.basepath}" assert service_url == service_details.legacy_service_url
async def test_get_stack_status_ok( loop: asyncio.AbstractEventLoop, scheduler: DynamicSidecarsScheduler, scheduler_data: SchedulerData, mock_service_running: AsyncMock, docker_swarm: None, mocked_dynamic_scheduler_events: None, ) -> None: async with _assert_get_dynamic_services_mocked( scheduler, scheduler_data, mock_service_running, expected_response=httpx.Response( 200, json={"fake_entry": { "Status": "running" }}), ) as stack_status: assert stack_status == RunningDynamicServiceDetails.from_scheduler_data( node_uuid=scheduler_data.node_uuid, scheduler_data=scheduler_data, service_state=ServiceState.RUNNING, service_message="", )
def get_stack_status(node_uuid: NodeID) -> RunningDynamicServiceDetails: if exp_status_code == status.HTTP_307_TEMPORARY_REDIRECT: raise DynamicSidecarNotFoundError(node_uuid) return RunningDynamicServiceDetails.parse_obj( RunningDynamicServiceDetails.Config.schema_extra["examples"][0])
def fake_running_service_details() -> RunningDynamicServiceDetails: sample_data = choice( RunningDynamicServiceDetails.Config.schema_extra["examples"]) return RunningDynamicServiceDetails(**sample_data)