Ejemplo n.º 1
0
def wait_delete_operation_finish(timeout: int, wait: bool, md_id: str, md_client: ModelDeploymentClient):
    """
    Wait delete operation

    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until deletion will be finished
    :param md_id: Model Deployment name
    :param md_client: Model Deployment Client

    :return: None
    """
    if not wait:
        return

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

    while True:
        elapsed = time.time() - start
        if elapsed > timeout:
            raise Exception('Time out: operation has not been confirmed')

        try:
            md_client.get(md_id)
        except WrongHttpStatusCode as e:
            if e.status_code == 404:
                print(f'Model deployment {md_id} was deleted')
                return
            LOGGER.info('Callback have not confirmed completion of the operation')

        print(f'Model deployment {md_id} is still being deleted...')
        time.sleep(DEFAULT_WAIT_TIMEOUT)
Ejemplo n.º 2
0
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))
Ejemplo n.º 3
0
    def deployment_post(payload_file, image=None):
        api_object = parse_resources_file_with_one_item(payload_file).resource

        if image:
            api_object.spec.image = image

        return ModelDeploymentClient().create(api_object)
Ejemplo n.º 4
0
def edit(client: ModelDeploymentClient, md_id: str, file: str, wait: bool, timeout: int, image: str):
    """
    \b
    Update a deployment.
    You should specify a path to file with a deployment. The file must contain only one deployment.
    For now, CLI supports YAML and JSON file formats.
    If you want to update multiple deployments, you should use "odahuflowctl bulk apply" instead.
    If you provide the deployment id parameter, it will override before sending to API server.
    \b
    Usage example:
        * odahuflowctl dep update -f dep.yaml --id examples-git
    \f
    :param client: Model deployment HTTP client
    :param md_id: Model deployment ID
    :param file: Path to the file with only one deployment
    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until edit will be finished
    :param image: Override Docker image from file
    """
    md = parse_resources_file_with_one_item(file).resource
    if not isinstance(md, ModelDeployment):
        raise ValueError(f'Model deployment expected, but {type(md)} provided')

    if md_id:
        md.id = md_id

    if image:
        md.spec.image = image

    click.echo(client.edit(md))

    wait_deployment_finish(timeout, wait, md.id, client)
Ejemplo n.º 5
0
def wait_deployment_finish(timeout: int, wait: bool, md_id: str,
                           md_client: ModelDeploymentClient):
    """
    Wait for deployment to finish according to command line arguments

    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until deletion will be finished
    :param md_id: Model Deployment name
    :param md_client: Model Deployment Client

    :return: None
    """
    if not wait:
        return

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

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

        try:
            md: ModelDeployment = md_client.get(md_id)
            if md.status.state == READY_STATE:
                if md.spec.min_replicas <= md.status.available_replicas:
                    print(
                        f'Model {md_id} was deployed. '
                        f'Deployment process took {round(time.time() - start)} seconds'
                    )
                    return
                else:
                    print(
                        f'Model {md_id} was deployed. '
                        f'Number of available pods is {md.status.available_replicas}/{md.spec.min_replicas}'
                    )
            elif md.status.state == FAILED_STATE:
                raise Exception(f'Model deployment {md_id} was failed')
            elif md.status.state == "":
                print(f"Can't determine the state of {md.id}. Sleeping...")
            else:
                print(
                    f'Current deployment state is {md.status.state}. Sleeping...'
                )
        except WrongHttpStatusCode:
            LOGGER.info(
                'Callback have not confirmed completion of the operation')

        LOGGER.debug('Sleep before next request')
        time.sleep(DEFAULT_WAIT_TIMEOUT)
Ejemplo n.º 6
0
def get(client: ModelDeploymentClient, md_id: str, output_format: str):
    """
    \b
    Get deployments.
    The command without id argument retrieve all deployments.
    \b
    Get all deployments in json format:
        odahuflowctl dep get --output-format json
    \b
    Get deployment with "git-repo" id:
        odahuflowctl dep get --id model-wine
    \b
    Using jsonpath:
        odahuflowctl dep get -o 'jsonpath=[*].spec.reference'
    \f
    :param client: Model deployment HTTP client
    :param md_id: Model deployment ID
    :param output_format: Output format
    :return:
    """
    mds = [client.get(md_id)] if md_id else client.get_all()

    format_output(mds, output_format)
Ejemplo n.º 7
0
def delete(client: ModelDeploymentClient, md_id: str, file: str,
           ignore_not_found: bool, wait: bool, timeout: int):
    """
    \b
    Delete a deployment.
    For this command, you must provide a deployment ID or path to file with one deployment.
    The file must contain only one deployment.
    If you want to delete multiple deployments, 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 dep delete --id examples-git
        * odahuflowctl dep delete -f dep.yaml
    \f
    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until deletion will be finished
    :param client: Model deployment HTTP client
    :param md_id: Model deployment ID
    :param file: Path to the file with only one deployment
    :param ignore_not_found: ignore if Model Deployment is not found
    """
    check_id_or_file_params_present(md_id, file)

    if file:
        md = parse_resources_file_with_one_item(file).resource
        if not isinstance(md, ModelDeployment):
            raise ValueError(
                f'Model deployment expected, but {type(md)} provided')

        md_id = md.id

    try:
        message = client.delete(md_id)

        wait_delete_operation_finish(timeout, wait, md_id, client)
        click.echo(message)
    except WrongHttpStatusCode as e:
        if e.status_code != 404 or not ignore_not_found:
            raise e

        click.echo(
            IGNORE_NOT_FOUND_ERROR_MESSAGE.format(
                kind=ModelDeployment.__name__, id=md_id))
Ejemplo n.º 8
0
def create(client: ModelDeploymentClient, md_id: str, file: str, wait: bool,
           timeout: int, image: str, ignore_if_exists: bool):
    """
    \b
    Create a deployment.
    You should specify a path to file with a deployment. The file must contain only one deployment.
    For now, CLI supports YAML and JSON file formats.
    If you want to create multiple deployments, you should use "odahuflowctl bulk apply" instead.
    If you provide the deployment id parameter, it will override before sending to API server.
    \b
    Usage example:
        * odahuflowctl dep create -f dep.yaml --id examples-git
    \f
    :param timeout: timeout in seconds. for wait (if no-wait is off)
    :param wait: no wait until deployment will be finished
    :param client: Model deployment HTTP client
    :param md_id: Model deployment ID
    :param file: Path to the file with only one deployment
    :param image: Override Docker image from file
    :param ignore_if_exists: Return success status code if entity is already exists
    """
    md = parse_resources_file_with_one_item(file).resource
    if not isinstance(md, ModelDeployment):
        raise ValueError(f'Model deployment expected, but {type(md)} provided')

    if md_id:
        md.id = md_id

    if image:
        md.spec.image = image

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

    click.echo(res)

    wait_deployment_finish(timeout, wait, md.id, client)
Ejemplo n.º 9
0
def deployment(ctx: click.core.Context, url: str, token: str):
    """
    Allow you to perform actions on deployments.\n
    Alias for the command is dep.
    """
    ctx.obj = ModelDeploymentClient(url, token)
Ejemplo n.º 10
0
 def deployment_delete(dep_id: str):
     return ModelDeploymentClient().delete(dep_id)
Ejemplo n.º 11
0
 def deployment_get_id(dep_id: str):
     return ModelDeploymentClient().get(dep_id)
Ejemplo n.º 12
0
 def deployment_get():
     return ModelDeploymentClient().get_all()
Ejemplo n.º 13
0
    'ModelPackaging',
)

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

DEPLOYMENT = EntityTestData(
    ModelDeploymentClient(),
    ModelDeployment(id=ENTITY_ID,
                    spec=ModelDeploymentSpec(image="odahu:image",
                                             min_replicas=0),
                    status=ModelDeploymentStatus(
                        state=READY_STATE,
                        available_replicas=1,
                    )),
    deployment.deployment,
    'ModelDeployment',
)

ROUTER = EntityTestData(
    ModelRouteClient(),
    ModelRoute(id=ENTITY_ID,
               spec=ModelRouteSpec(mirror="test", ),