def mocked_director_service_fcts( minimal_app: FastAPI, fake_service_details: ServiceDockerData, fake_service_extras: ServiceExtras, fake_running_service_details: RunningServiceDetails, ): with respx.mock( base_url=minimal_app.state.settings.director_v0.base_url( include_tag=False), assert_all_called=False, assert_all_mocked=True, ) as respx_mock: respx_mock.get( "/v0/services/simcore%2Fservices%2Fdynamic%2Fmyservice/1.3.4", content={"data": [fake_service_details.dict(by_alias=True)]}, alias="get_service_version", ) respx_mock.get( "/v0/service_extras/simcore%2Fservices%2Fdynamic%2Fmyservice/1.3.4", content={"data": fake_service_extras.dict(by_alias=True)}, alias="get_service_extras", ) pattern = re.compile( r"v0/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}$" ) respx_mock.get( pattern, content={"data": fake_running_service_details.dict(by_alias=True)}, alias="get_running_service_details", ) yield respx_mock
def _get_fake_service_details(service: ServiceKeyVersion) -> ServiceDockerData: if "file-picker" in service.key: file_picker_outputs = { "outFile": { "label": "the output", "displayOrder": 0, "description": "a file", "type": "data:*/*", } } file_picker_type = ServiceType.FRONTEND return ServiceDockerData( **service.dict(), name="file-picker", description="file-picks", authors=[ Author(name="ITIS", email="*****@*****.**", affiliation="IT'IS") ], contact="*****@*****.**", inputs={}, outputs=file_picker_outputs, type=file_picker_type, ) raise ValueError("")
def test_service_port_units(osparc_simcore_root_dir): ureg = UnitRegistry() data = yaml.safe_load( (osparc_simcore_root_dir / "packages/models-library/tests/image-meta.yaml").read_text()) print(ServiceDockerData.schema_json(indent=2)) service_meta = ServiceDockerData.parse_obj(data) for input_nameid, input_meta in service_meta.inputs.items(): assert input_nameid # validation valid_unit: Unit = ureg.parse_units(input_meta.unit) assert isinstance(valid_unit, Unit) assert valid_unit.dimensionless
def test_service_port_units(project_tests_dir: Path): ureg = UnitRegistry() data = yaml.safe_load( (project_tests_dir / "data" / "image-meta.yaml").read_text()) print(ServiceDockerData.schema_json(indent=2)) service_meta = ServiceDockerData.parse_obj(data) assert service_meta.inputs for input_nameid, input_meta in service_meta.inputs.items(): assert input_nameid # validation valid_unit: Unit = ureg.parse_units(input_meta.unit) assert isinstance(valid_unit, Unit) assert valid_unit.dimensionless
async def get_service_details( self, service: ServiceKeyVersion ) -> ServiceDockerData: resp = await self.request( "GET", f"services/{urllib.parse.quote_plus(service.key)}/{service.version}" ) if resp.status_code == status.HTTP_200_OK: return ServiceDockerData.parse_obj(unenvelope_or_raise_error(resp)[0]) raise HTTPException(status_code=resp.status_code, detail=resp.content)
def create_from_image(cls, image_meta: ServiceDockerData) -> "Solver": data = image_meta.dict( include={"name", "key", "version", "description", "contact"}, ) return cls( id=data.pop("key"), version=data.pop("version"), title=data.pop("name"), maintainer=data.pop("contact"), url=None, **data, )
def get_version(target_version, metadata_file_path): """Prints to output requested version""" # parse and validate metadata = ServiceDockerData(**yaml.safe_load(metadata_file_path.read_text())) attrname = target_version.replace("-", "_") current_version: str = getattr(metadata, attrname) # MUST have no new line so that we can produce a VERSION file with no extra new-line # VERSION: $(METADATA) # @osparc-service-integrator get-version --metadata-file $< > $@ click.echo(current_version, nl=False)
def registry_services() -> List[ServiceDockerData]: NUMBER_OF_SERVICES = 5 return [ ServiceDockerData( key="simcore/services/comp/my_comp_service", version=f"{v}.{randint(0,20)}.{randint(0,20)}", type=ServiceType.computational, name=f"my service {v}", description="a sleeping service version {v}", authors=[{"name": "me", "email": "*****@*****.**"}], contact="*****@*****.**", inputs=[], outputs=[], ) for v in range(NUMBER_OF_SERVICES) ]
def bump_version(target_version, upgrade, metadata_file_path): """ Bumps target version in metadata """ # load raw_data: OrderedDict = ordered_safe_load(metadata_file_path.read_text()) # parse and validate metadata = ServiceDockerData(**raw_data) # get + bump + set attrname = target_version.replace("-", "_") current_version: str = getattr(metadata, attrname) raw_data[target_version] = new_version = bump_version_string( current_version, upgrade) # dump to file (preserving order!) text = ordered_safe_dump(raw_data) metadata_file_path.write_text(text) click.echo( f"{target_version.title()} bumped: {current_version} → {new_version}")
def _file_picker_service() -> ServiceDockerData: return ServiceDockerData( key="simcore/services/frontend/file-picker", version="1.0.0", type="dynamic", name="File Picker", description="File Picker", authors=[{"name": "Odei Maiz", "email": "*****@*****.**"}], contact="*****@*****.**", inputs={}, outputs={ "outFile": { "displayOrder": 0, "label": "File", "description": "Chosen File", "type": "data:*/*", } }, )
async def _list_registry_services(app: FastAPI, ) -> ServiceDockerDataMap: client = get_director_api(app) data = await client.get("/services") services: ServiceDockerDataMap = {(s.key, s.version): s for s in iter_service_docker_data()} for x in data: try: service_data = ServiceDockerData.parse_obj(x) services[(service_data.key, service_data.version)] = service_data except ValidationError as exc: logger.warning( "Skip service %s:%s with invalid fields\n%s", x.get("key"), x.get("version"), exc, ) return services
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
async def _list_registry_services( app: FastAPI, ) -> Dict[Tuple[ServiceKey, ServiceVersion], ServiceDockerData]: client = get_director_api(app) data = await client.get("/services") services: Dict[Tuple[ServiceKey, ServiceVersion], ServiceDockerData] = {(s.key, s.version): s for s in get_frontend_services()} for x in data: try: service_data = ServiceDockerData.parse_obj(x) services[(service_data.key, service_data.version)] = service_data # services = parse_obj_as(List[ServiceDockerData], data) except ValidationError as exc: logger.warning( "skip service %s:%s that has invalid fields\n%s", x["key"], x["version"], exc, ) return services
async def test_auto_upgrade_policy( sqlalchemy_async_engine: AsyncEngine, user_groups_ids: List[int], products_names: List[str], services_db_tables_injector: Callable, service_catalog_faker: Callable, mocker, ): everyone_gid, user_gid, team_gid = user_groups_ids target_product = products_names[0] # Avoids calls to director API mocker.patch( "simcore_service_catalog.services.access_rights._is_old_service", return_value=False, ) # Avoids creating a users + user_to_group table data = GroupAtDB.Config.schema_extra["example"] data["gid"] = everyone_gid mocker.patch( "simcore_service_catalog.services.access_rights.GroupsRepository.get_everyone_group", return_value=GroupAtDB.parse_obj(data), ) mocker.patch( "simcore_service_catalog.services.access_rights.GroupsRepository.get_user_gid_from_email", return_value=user_gid, ) # SETUP --- MOST_UPDATED_EXAMPLE = -1 new_service_metadata = ServiceDockerData.parse_obj( ServiceDockerData.Config.schema_extra["examples"] [MOST_UPDATED_EXAMPLE]) new_service_metadata.version = "1.0.1" # we two versions of the service in the database await services_db_tables_injector([ service_catalog_faker( new_service_metadata.key, "0.5.0", team_access=None, everyone_access=None, product=target_product, ), # new release is a patch on released 1.0.X # which were released in two different product service_catalog_faker( new_service_metadata.key, "1.0.0", team_access="x", everyone_access=None, product=target_product, ), service_catalog_faker( new_service_metadata.key, "1.0.0", team_access="x", everyone_access=None, product=products_names[-1], ), ]) # ------------ app = FastAPI() app.state.engine = sqlalchemy_async_engine app.state.settings = mocker.Mock() app.state.settings.CATALOG_ACCESS_RIGHTS_DEFAULT_PRODUCT_NAME = target_product services_repo = ServicesRepository(app.state.engine) # DEFAULT policies owner_gid, service_access_rights = await evaluate_default_policy( app, new_service_metadata) assert owner_gid == user_gid assert len(service_access_rights) == 1 assert {a.gid for a in service_access_rights} == {owner_gid} assert service_access_rights[0].dict() == { "key": new_service_metadata.key, "version": new_service_metadata.version, "gid": user_gid, "product_name": target_product, "execute_access": True, "write_access": True, } assert service_access_rights[0].product_name == target_product # AUTO-UPGRADE PATCH policy inherited_access_rights = await evaluate_auto_upgrade_policy( new_service_metadata, services_repo) assert len(inherited_access_rights) == 4 assert {a.gid for a in inherited_access_rights} == {team_gid, owner_gid} assert {a.product_name for a in inherited_access_rights} == { target_product, products_names[-1], } # ALL service_access_rights += inherited_access_rights service_access_rights = reduce_access_rights(service_access_rights) assert len(service_access_rights) == 4 assert {a.gid for a in service_access_rights} == {team_gid, owner_gid} assert {a.product_name for a in service_access_rights} == { target_product, products_names[-1], }
def fake_service_details(mocks_dir: Path) -> ServiceDockerData: fake_service_path = mocks_dir / "fake_service.json" assert fake_service_path.exists() fake_service_data = json.loads(fake_service_path.read_text()) return ServiceDockerData(**fake_service_data)
def load_images(cls) -> Iterator[ServiceDockerData]: mocks_dir: Path = files("simcore_service_api_server").joinpath("mocks") for filepath in mocks_dir.glob("*.y*ml"): image = yaml.safe_load(filepath.read_text()) yield ServiceDockerData.parse_obj(image)
def _as_dict(model_instance: ServiceDockerData) -> Dict[str, Any]: # FIXME: In order to convert to ServiceOut, now we have to convert back to front-end service because of alias # FIXME: set the same policy for f/e and director datasets! return model_instance.dict(by_alias=True, exclude_unset=True)