Example #1
0
def wait_packaging_finish(timeout: int, wait: bool, mp_id: str,
                          mp_client: ModelPackagingClient):
    """
    Wait for packaging to finish according to command line arguments

    :param wait:
    :param timeout:
    :param mp_id: Model Packaging name
    :param mp_client: Model Packaging Client
    """
    if not wait:
        return

    start = time.time()
    if timeout <= 0:
        raise Exception(
            'Invalid --timeout argument: should be positive integer')

    # We create a separate client for logs because it has the different timeout settings
    log_mp_client = ModelPackagingClient.construct_from_other(mp_client)
    log_mp_client.timeout = mp_client.timeout, LOG_READ_TIMEOUT_SECONDS

    click.echo("Logs streaming...")

    while True:
        elapsed = time.time() - start
        if elapsed > timeout:
            raise Exception(TIMEOUT_ERROR_MESSAGE)

        try:
            mp = mp_client.get(mp_id)
            if mp.status.state == SUCCEEDED_STATE:
                click.echo(
                    f'Model {mp_id} was packed. Packaging took {round(time.time() - start)} seconds'
                )
                return
            elif mp.status.state == FAILED_STATE:
                raise Exception(f'Model packaging {mp_id} was failed.')
            elif mp.status.state == "":
                click.echo(
                    f"Can't determine the state of {mp.id}. Sleeping...")
            else:
                for msg in log_mp_client.log(mp.id, follow=True):
                    print_logs(msg)

        except (WrongHttpStatusCode, HTTPException, RequestException,
                APIConnectionException) as e:
            LOGGER.info(
                'Callback have not confirmed completion of the operation. Exception: %s',
                str(e))

        LOGGER.debug('Sleep before next request')
        time.sleep(DEFAULT_WAIT_TIMEOUT)
Example #2
0
def run(client: ModelPackagingClient, pack_id: str, manifest_file: List[str], manifest_dir: List[str],
        artifact_path: str, artifact_name: str, is_target_disabled: bool):
    """
    \b
    Start a packaging process locally.
    \b
    Usage example:
        * odahuflowctl local pack run --id wine
    \f
    """
    entities: List[OdahuflowCloudResourceUpdatePair] = []
    for file_path in manifest_file:
        entities.extend(parse_resources_file(file_path).changes)

    for dir_path in manifest_dir:
        entities.extend(parse_resources_dir(dir_path))

    mp: Optional[ModelPackaging] = None

    packagers: Dict[str, PackagingIntegration] = {}
    for entity in map(lambda x: x.resource, entities):
        if isinstance(entity, PackagingIntegration):
            packagers[entity.id] = entity
        elif isinstance(entity, ModelPackaging) and entity.id == pack_id:
            mp = entity

    if not mp:
        click.echo(
            f'The {pack_id} packaging not found in the manifest files.'
            f' Trying to retrieve it from API server'
        )
        mp = client.get(pack_id)

    integration_name = mp.spec.integration_name
    packager = packagers.get(integration_name)
    if not packager:
        click.echo(
            f'The {integration_name} packager not found in the manifest files.'
            f' Trying to retrieve it from API server'
        )
        packager = PackagingIntegrationClient.construct_from_other(client).get(integration_name)

    if artifact_name:
        mp.spec.artifact_name = artifact_name
        LOGGER.debug('Override the artifact name')

    if is_target_disabled:
        mp.spec.targets = []

    k8s_packager = K8sPackager(
        model_packaging=mp,
        packaging_integration=packager,
        targets=[],
    )

    result = start_package(k8s_packager, artifact_path)

    click.echo('Packager results:')
    for key, value in result.items():
        click.echo(f'* {key} - {value}')
def build_client(resource: OdahuflowCloudResourceUpdatePair,
                 api_client: RemoteAPIClient) -> typing.Optional[object]:
    """
    Build client for particular resource (e.g. it builds ModelTrainingClient for ModelTraining resource)

    :param resource: target resource
    :param api_client: base API client to extract connection options from
    :return: remote client or None
    """
    if isinstance(resource.resource, ModelTraining):
        return ModelTrainingClient.construct_from_other(api_client)
    elif isinstance(resource.resource, ModelDeployment):
        return ModelDeploymentClient.construct_from_other(api_client)
    elif isinstance(resource.resource, Connection):
        return ConnectionClient.construct_from_other(api_client)
    elif isinstance(resource.resource, ToolchainIntegration):
        return ToolchainIntegrationClient.construct_from_other(api_client)
    elif isinstance(resource.resource, ModelRoute):
        return ModelRouteClient.construct_from_other(api_client)
    elif isinstance(resource.resource, ModelPackaging):
        return ModelPackagingClient.construct_from_other(api_client)
    elif isinstance(resource.resource, PackagingIntegration):
        return PackagingIntegrationClient.construct_from_other(api_client)
    else:
        raise InvalidResourceType('{!r} is invalid resource '.format(
            resource.resource))
Example #4
0
def logs(client: ModelPackagingClient, pack_id: str, file: str, follow: bool):
    """
    \b
    Stream packaging logs.
    For this command, you must provide a packaging ID or path to file with one packaging.
    The file must contain only one packaging.
    The command will fail if you provide both arguments.
    \b
    Usage example:
        * odahuflowctl pack delete --id examples-git
        * odahuflowctl pack delete -f pack.yaml
    \f
    :param follow: Follow logs stream
    :param client: Model packaging HTTP client
    :param pack_id: Model packaging ID
    :param file: Path to the file with only one packaging
    """
    check_id_or_file_params_present(pack_id, file)

    if file:
        pack = parse_resources_file_with_one_item(file).resource
        if not isinstance(pack, ModelPackaging):
            raise ValueError(
                f'Model packaging expected, but {type(pack)} provided')

        pack_id = pack.id

    for msg in client.log(pack_id, follow):
        print_logs(msg)
Example #5
0
def edit(client: ModelPackagingClient, pack_id: str, file: str, wait: bool,
         timeout: int, artifact_name: str):
    """
    \b
    Update a packaging.
    You should specify a path to file with a packaging. The file must contain only one packaging.
    For now, CLI supports YAML and JSON file formats.
    If you want to update multiple packagings, you should use "odahuflowctl bulk apply" instead.
    If you provide the packaging id parameter, it will override before sending to API server.
    \b
    Usage example:
        * odahuflowctl pack update -f pack.yaml --id examples-git
    \f
    :param client: Model packaging HTTP client
    :param pack_id: Model packaging ID
    :param file: Path to the file with only one packaging
    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until scale will be finished
    :param artifact_name: Override artifact name from file
    """
    pack = parse_resources_file_with_one_item(file).resource
    if not isinstance(pack, ModelPackaging):
        raise ValueError(
            f'Model packaging expected, but {type(pack)} provided')

    if pack_id:
        pack.id = pack_id

    if artifact_name:
        pack.spec.artifact_name = artifact_name

    mp = client.edit(pack)
    click.echo(f"Rerun packing: {mp}")

    wait_packaging_finish(timeout, wait, pack.id, client)
Example #6
0
    def packaging_post(payload_file, artifact_name=None):
        api_object = parse_resources_file_with_one_item(payload_file).resource

        if artifact_name:
            api_object.spec.artifact_name = artifact_name

        return ModelPackagingClient().create(api_object)
Example #7
0
def get(client: ModelPackagingClient, pack_id: str, output_format: str):
    """
    \b
    Get packagings.
    The command without id argument retrieve all packagings.
    \b
    Get all packagings in json format:
        odahuflowctl pack get --output-format json
    \b
    Get packaging with "git-repo" id:
        odahuflowctl pack get --id git-repo
    \b
    Using jsonpath:
        odahuflowctl pack get -o 'jsonpath=[*].spec.reference'
    \f
    :param client: Model packaging HTTP client
    :param pack_id: Model packaging ID
    :param output_format: Output format
    :return:
    """
    packs = [client.get(pack_id)] if pack_id else client.get_all()

    format_output(packs, output_format)
Example #8
0
def create(client: ModelPackagingClient, pack_id: str, file: str, wait: bool,
           timeout: int, artifact_name: str, ignore_if_exists: bool):
    """
    \b
    Create a packaging.
    You should specify a path to file with a packaging. The file must contain only one packaging.
    For now, CLI supports YAML and JSON file formats.
    If you want to create multiple packagings, you should use "odahuflowctl bulk apply" instead.
    If you provide the packaging id parameter, it will override before sending to API server.
    \b
    Usage example:
        * odahuflowctl pack create -f pack.yaml --id examples-git
    \f
    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until scale will be finished
    :param client: Model packaging HTTP client
    :param pack_id: Model packaging ID
    :param file: Path to the file with only one packaging
    :param artifact_name: Override artifact name from file
    :param ignore_if_exists: Return success status code if entity is already exists
    """
    pack = parse_resources_file_with_one_item(file).resource
    if not isinstance(pack, ModelPackaging):
        raise ValueError(
            f'Model packaging expected, but {type(pack)} provided')

    if pack_id:
        pack.id = pack_id

    if artifact_name:
        pack.spec.artifact_name = artifact_name

    try:
        mp = client.create(pack)
    except EntityAlreadyExists as e:
        if ignore_if_exists:
            LOGGER.debug(
                f'--ignore-if-exists was passed: {e} will be suppressed')
            click.echo('Packaging already exists')
            return
        raise

    click.echo(f"Start packing: {mp}")

    wait_packaging_finish(timeout, wait, pack.id, client)
Example #9
0
def delete(client: ModelPackagingClient, pack_id: str, file: str,
           ignore_not_found: bool):
    """
    \b
    Delete a packaging.
    For this command, you must provide a packaging ID or path to file with one packaging.
    The file must contain only one packaging.
    If you want to delete multiple packagings, you should use "odahuflowctl bulk delete" instead.
    For now, CLI supports YAML and JSON file formats.
    The command will fail if you provide both arguments.
    \b
    Usage example:
        * odahuflowctl pack delete --id examples-git
        * odahuflowctl pack delete -f pack.yaml
    \f
    :param client: Model packaging HTTP client
    :param pack_id: Model packaging ID
    :param file: Path to the file with only one packaging
    :param ignore_not_found: ignore if Model Packaging is not found
    """
    check_id_or_file_params_present(pack_id, file)

    if file:
        pack = parse_resources_file_with_one_item(file).resource
        if not isinstance(pack, ModelPackaging):
            raise ValueError(
                f'Model packaging expected, but {type(pack)} provided')

        pack_id = pack.id

    try:
        message = client.delete(pack_id)
        click.echo(message)
    except WrongHttpStatusCode as e:
        if e.status_code != 404 or not ignore_not_found:
            raise e

        click.echo(f'Model packaging {pack_id} was not found. Ignore')
Example #10
0
def packaging_group(ctx: click.core.Context, url: str, token: str):
    """
    Local packaging process.\n
    Alias for the command is pack.
    """
    ctx.obj = ModelPackagingClient(url, token)
Example #11
0
def packaging(ctx: click.core.Context, url: str, token: str):
    """
    Allow you to perform actions on packagings.\n
    Alias for the command is pack.
    """
    ctx.obj = ModelPackagingClient(url, token)
Example #12
0
 def packaging_get():
     return ModelPackagingClient().get_all()
Example #13
0
 def packaging_get_log(pack_id):
     log_generator = ModelPackagingClient().log(pack_id, follow=False)
     # logs_list will be list of log lines
     logs_list = list(log_generator)
     text = "\n".join(logs_list)
     return text
Example #14
0
 def packaging_delete(pack_id: str):
     return ModelPackagingClient().delete(pack_id)
Example #15
0
 def packaging_get_id(pack_id: str):
     return ModelPackagingClient().get(pack_id)
Example #16
0
TOOLCHAIN = EntityTestData(
    ToolchainIntegrationClient(),
    ToolchainIntegration(
        id=ENTITY_ID,
        spec=ToolchainIntegrationSpec(
            default_image="mock-image",
            entrypoint="default-entrypoint",
        ),
    ),
    toolchain_integration.toolchain_integration,
    'ToolchainIntegration',
)

PACKAGING = EntityTestData(
    ModelPackagingClient(),
    ModelPackaging(id=ENTITY_ID,
                   spec=ModelPackagingSpec(artifact_name='test-artifact-name',
                                           integration_name='test'),
                   status=ModelPackagingStatus(state=SUCCEEDED_STATE, )),
    packaging.packaging,
    'ModelPackaging',
)

PACKAGING_INTEGRATION = EntityTestData(
    PackagingIntegrationClient(),
    PackagingIntegration(
        id=ENTITY_ID,
        spec=PackagingIntegrationSpec(default_image="odahu:image",
                                      entrypoint="some_entrypoint"),
    ),