Пример #1
0
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
Пример #2
0
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("")
Пример #3
0
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
Пример #4
0
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
Пример #5
0
 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)
Пример #6
0
    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,
        )
Пример #7
0
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)
    ]
Пример #9
0
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:*/*",
            }
        },
    )
Пример #11
0
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
Пример #12
0
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
Пример #13
0
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],
            }
Пример #15
0
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)
Пример #16
0
 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)
Пример #17
0
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)