def pull(self, bento: str) -> "BentoUri":
        """
        Pull a :class:`~bentoml.BentoService` from remote Yatai.
        The BentoService will then be saved and registered to local Yatai.

        Args:
            bento (`str`):
                a BentoService identifier in the form of ``NAME:VERSION``

        Returns:
            :class:`reflection.GeneratedProtocolMessageType`:
                URI as gRPC stub for save location of BentoService.

        Example::

            from bentoml.yatai.client import get_yatai_client
            client = get_yatai_client('127.0.0.1:50051')
            saved_path = client.repository.pull('MyService:20210808_E38F3')
        """
        bento_pb: "Bento" = self.get(bento)
        with TempDirectory() as tmpdir:
            # Create a non-exist directory for safe_retrieve
            target_bundle_path = os.path.join(tmpdir, 'bundle')
            self.download_to_directory(bento_pb, target_bundle_path)

            from bentoml.yatai.client import get_yatai_client

            labels = (dict(bento_pb.bento_service_metadata.labels)
                      if bento_pb.bento_service_metadata.labels else None)

            local_yc = get_yatai_client()
            return local_yc.repository.upload_from_dir(target_bundle_path,
                                                       labels=labels)
Exemple #2
0
def test_s3(minio_address):
    yatai_server_command = [
        'bentoml',
        'yatai-service-start',
        '--no-ui',
        '--grpc-port',
        '50051',
        '--repo-base-url',
        f's3://{bucket_name}/',
        '--s3-endpoint-url',
        'localhost:9000',
    ]
    proc = subprocess.Popen(yatai_server_command,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    yatai_server_url = "localhost:50051"
    svc = ExampleBentoService()
    svc.pack('model', {'model': 'abc'})
    bento_tag = f'{svc.name}:{svc.version}'
    saved_path = svc.save(yatai_url=yatai_server_url)
    yc = get_yatai_client(yatai_server_url)

    assert saved_path.startswith('s3://')

    bento_pb = yc.repository.get(bento_tag)
    with TempDirectory() as temp_dir:
        yc.repository.download_to_directory(bento_pb, f'{temp_dir}/bundle')
        assert os.path.exists(f'{temp_dir}/bundle/bentoml.yml')
    proc.kill()
Exemple #3
0
def resolve_bundle_path(
    bento: str,
    pip_installed_bundle_path: Optional[str] = None,
    yatai_url: Optional[str] = None,
) -> str:
    from bentoml.exceptions import BentoMLException
    from bentoml.yatai.client import get_yatai_client

    if pip_installed_bundle_path:
        assert (
            bento is None
        ), "pip installed BentoService commands should not have Bento argument"
        return pip_installed_bundle_path

    if os.path.isdir(bento) or is_s3_url(bento) or is_gcs_url(bento):
        # saved_bundle already support loading local, s3 path and gcs path
        return bento

    elif ":" in bento:
        # assuming passing in BentoService in the form of Name:Version tag
        yatai_client = get_yatai_client(yatai_url)
        bento_pb = yatai_client.repository.get(bento)
        return resolve_bento_bundle_uri(bento_pb)
    else:
        raise BentoMLException(
            f'BentoService "{bento}" not found - either specify the file path of '
            f"the BentoService saved bundle, or the BentoService id in the form of "
            f'"name:version"')
Exemple #4
0
def resolve_bundle_path(bento, pip_installed_bundle_path, yatai_url=None):
    from bentoml.yatai.client import get_yatai_client
    from bentoml.exceptions import BentoMLException

    if pip_installed_bundle_path:
        assert (
            bento is None
        ), "pip installed BentoService commands should not have Bento argument"
        return pip_installed_bundle_path

    if os.path.isdir(bento) or is_s3_url(bento) or is_gcs_url(bento):
        # saved_bundle already support loading local, s3 path and gcs path
        return bento

    elif ":" in bento:
        # assuming passing in BentoService in the form of Name:Version tag
        yatai_client = get_yatai_client(yatai_url)
        bento_pb = yatai_client.repository.get(bento)
        if bento_pb.uri.s3_presigned_url:
            # Use s3 presigned URL for downloading the repository if it is presented
            return bento_pb.uri.s3_presigned_url
        if bento_pb.uri.gcs_presigned_url:
            return bento_pb.uri.gcs_presigned_url
        else:
            return bento_pb.uri.uri
    else:
        raise BentoMLException(
            f'BentoService "{bento}" not found - either specify the file path of '
            f"the BentoService saved bundle, or the BentoService id in the form of "
            f'"name:version"')
Exemple #5
0
    def push(self, bento, labels=None):
        """
        Push a local BentoService to a remote yatai server.

        Args:
            bento: a BentoService identifier in the format of NAME:VERSION
            labels: optional. List of labels for the BentoService.

        Returns:
            BentoService saved path

        Example:

        >>> svc = MyBentoService()
        >>> svc.save()
        >>>
        >>> remote_yatai_client = get_yatai_client('http://remote.yatai.service:50050')
        >>> bento = f'{svc.name}:{svc.version}'
        >>> remote_saved_path= remote_yatai_client.repository.push(bento)
        """
        track('py-api-push')

        from bentoml.yatai.client import get_yatai_client

        local_yc = get_yatai_client()

        local_bento_pb = local_yc.repository.get(bento)
        if local_bento_pb.uri.s3_presigned_url:
            bento_bundle_path = local_bento_pb.uri.s3_presigned_url
        elif local_bento_pb.uri.gcs_presigned_url:
            bento_bundle_path = local_bento_pb.uri.gcs_presigned_url
        else:
            bento_bundle_path = local_bento_pb.uri.uri
        return self.upload_from_dir(bento_bundle_path, labels=labels)
def test_yatai_server_with_postgres_and_s3(postgres_db_container_url):
    # Note: Use pre-existing bucket instead of newly created bucket, because the
    # bucket's global DNS needs time to get set up.
    # https://github.com/boto/boto3/issues/1982#issuecomment-511947643

    s3_bucket_name = 's3://bentoml-e2e-test-repo/'

    with local_yatai_server(db_url=postgres_db_container_url,
                            repo_base_url=s3_bucket_name) as yatai_service_url:
        yc = get_yatai_client(yatai_service_url)
        logger.info('Saving bento service')
        svc = SampleBentoService()
        svc.save(yatai_url=yatai_service_url)
        bento_tag = f'{svc.name}:{svc.version}'
        logger.info('BentoService saved')

        logger.info("Display bentoservice info")
        bento = yc.repository.get(bento_tag)
        logger.info(bento)
        assert (bento.uri.type == BentoUri.S3
                ), 'BentoService storage type mismatched, expect S3'

        logger.info('Validate BentoService prediction result')
        run_result = execute_bentoml_run_command(bento_tag=bento_tag,
                                                 data='[]',
                                                 yatai_url=yatai_service_url)
        assert 'cat' in run_result, 'Unexpected BentoService prediction result'

        logger.info(f'Deleting saved bundle {bento_tag}')
        yc.repository.delete(bento_tag=bento_tag)
Exemple #7
0
def test_yatai_server_with_sqlite_and_gcs():
    gcs_bucket_name = 'gs://bentoml-e2e-tests/'

    with local_yatai_server(
            repo_base_url=gcs_bucket_name) as yatai_service_url:
        yc = get_yatai_client(yatai_service_url)
        logger.info('Saving bento service')
        svc = SampleBentoService()
        svc.save(yatai_url=yatai_service_url)
        bento_tag = f'{svc.name}:{svc.version}'
        logger.info('BentoService saved')

        logger.info("Display bentoservice info")
        bento = yc.repository.get(bento_tag)
        logger.info(bento)
        assert (bento.uri.type == BentoUri.GCS
                ), 'BentoService storage type mismatched, expect GCS'

        logger.info('Validate BentoService prediction result')
        run_result = execute_bentoml_run_command(bento_tag=bento_tag,
                                                 data='[]',
                                                 yatai_url=yatai_service_url)
        logger.info(run_result)
        assert 'cat' in run_result, 'Unexpected BentoService prediction result'

        logger.info(f'Deleting saved bundle {bento_tag}')
        yc.repository.delete(bento_tag=bento_tag)
Exemple #8
0
 def push(bento, yatai_url):
     if ':' not in bento:
         _echo(f'BentoService {bento} invalid - specify name:version')
         return
     yc = get_yatai_client(yatai_url)
     yc.repository.push(bento=bento)
     _echo(f'Pushed {bento} to {yatai_url}')
Exemple #9
0
    def push(self, bento, labels=None):
        """
        Push a local BentoService to a remote yatai server.
        Args:
            bento: a BentoService identifier in the format of NAME:VERSION
            labels: optional. List of labels for the BentoService.

        Returns:
            BentoService saved path
        """
        track('py-api-push')
        if isinstance(self.yatai_service, YataiService):
            raise BentoMLException('need set yatai_service_url')

        from bentoml.yatai.client import get_yatai_client

        local_yc = get_yatai_client()

        local_bento_pb = local_yc.repository.get(bento)
        if local_bento_pb.uri.s3_presigned_url:
            bento_bundle_path = local_bento_pb.uri.s3_presigned_url
        elif local_bento_pb.uri.gcs_presigned_url:
            bento_bundle_path = local_bento_pb.uri.gcs_presigned_url
        else:
            bento_bundle_path = local_bento_pb.uri.uri
        return self.upload_from_dir(bento_bundle_path, labels=labels)
def test_delete_bentos_with_tags(bento_service):
    yc = get_yatai_client()
    yc.repository.delete(prune=True)
    version_one = uuid.uuid4().hex[0:8]
    version_two = uuid.uuid4().hex[0:8]
    version_three = uuid.uuid4().hex[0:8]
    bento_service.save(version=version_one)
    bento_service.save(version=version_two)
    bento_service.save(version=version_three)
    yc.repository.delete(bento_tag=f'{bento_service.name}:{version_one}')
    bentos = yc.repository.list()
    assert len(bentos) == 2

    runner = CliRunner()
    cli = create_bentoml_cli()
    print(cli.commands['delete'])
    runner.invoke(
        cli.commands['delete'],
        [
            f'{bento_service.name}:{version_two},{bento_service.name}:{version_three}',
            '-y',
        ],
    )
    bentos = yc.repository.list()
    assert len(bentos) == 0
    # Clean up existing bentos
    yc.repository.delete(prune=True)
    def pull(self, bento):
        """
        Pull a BentoService from a remote yatai service. The BentoService will be saved
        and registered with local yatai service.

        Args:
            bento: a BentoService identifier in the form of NAME:VERSION

        Returns:
            BentoService saved path

        Example:

        >>> remote_yatai_client = get_yatai_client('remote_yatai_service_address')
        >>> saved_path = remote_yatai_client.repository.pull('MyService:version')
        """
        track('py-api-pull')
        if isinstance(self.yatai_service, YataiService):
            raise BentoMLException('need set yatai_service_url')
        bento_pb = self.get(bento)
        with TempDirectory() as tmpdir:
            # Create a non-exist directory for safe_retrieve
            target_bundle_path = os.path.join(tmpdir, 'bundle')
            self.download_to_directory(bento_pb, target_bundle_path)

            from bentoml.yatai.client import get_yatai_client

            local_yc = get_yatai_client()
            return local_yc.repository.upload_from_dir(target_bundle_path)
    def pull(self, bento):
        """
        Pull a BentoService from a remote yatai service. The BentoService will be saved
        and registered with local yatai service.

        Args:
            bento: a BentoService identifier in the form of NAME:VERSION

        Returns:
            BentoService saved path

        Example:

        >>> client = get_yatai_client('127.0.0.1:50051')
        >>> saved_path = client.repository.pull('MyService:')
        """
        track('py-api-pull')

        bento_pb = self.get(bento)
        with TempDirectory() as tmpdir:
            # Create a non-exist directory for safe_retrieve
            target_bundle_path = os.path.join(tmpdir, 'bundle')
            self.download_to_directory(bento_pb, target_bundle_path)

            from bentoml.yatai.client import get_yatai_client

            labels = (dict(bento_pb.bento_service_metadata.labels)
                      if bento_pb.bento_service_metadata.labels else None)

            local_yc = get_yatai_client()
            return local_yc.repository.upload_from_dir(target_bundle_path,
                                                       labels=labels)
Exemple #13
0
def test_push_and_pull():
    with yatai_service_container() as yatai_server_url:
        svc = ExampleBentoService()
        bento_tag = f'{svc.name}:{svc.version}'
        saved_path = svc.save()
        yc = get_yatai_client(yatai_server_url)

        pushed_path = yc.repository.push(bento_tag)
        assert pushed_path != saved_path

        local_yc = get_yatai_client()
        delete_result = local_yc.repository.delete(bento_tag)
        assert delete_result is None
        assert os.path.exists(saved_path) is False

        pull_result = yc.repository.pull(bento_tag)
        assert pull_result == saved_path
def test_pull_with_labels(yatai_service_url, example_bento_service_class):
    yc = get_yatai_client(yatai_service_url)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    saved_path = svc.save(
        yatai_url=yatai_service_url, labels={'foo': 'bar', 'abc': '123'}
    )

    pulled_local_path = yc.repository.pull(f'{svc.name}:{svc.version}')
    assert pulled_local_path != saved_path
    local_yc = get_yatai_client()
    local_bento_pb = local_yc.repository.get(f'{svc.name}:{svc.version}')
    assert local_bento_pb.bento_service_metadata.labels
    labels = dict(local_bento_pb.bento_service_metadata.labels)
    assert labels['foo'] == 'bar'
    assert labels['abc'] == '123'
Exemple #15
0
def test_yatai_server_containerize_without_push(example_bento_service_class):
    svc = example_bento_service_class()
    svc.save()

    yc = get_yatai_client()
    image_tag = 'mytag'
    built_tag = yc.repository.containerize(bento=svc.tag, tag=image_tag)
    assert built_tag == f'{image_tag}:{svc.version}'
def test_load(yatai_service_url, example_bento_service_class):
    yc = get_yatai_client(yatai_service_url)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    svc.save(yatai_url=yatai_service_url)

    loaded_svc = yc.repository.load(f'{svc.name}:{svc.version}')
    assert loaded_svc.name == svc.name
def test_get(yatai_service_url, example_bento_service_class):
    yc = get_yatai_client(yatai_service_url)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    svc.save(yatai_url=yatai_service_url)
    svc_pb = yc.repository.get(f'{svc.name}:{svc.version}')
    assert svc_pb.bento_service_metadata.name == svc.name
    assert svc_pb.bento_service_metadata.version == svc.version
def test_pull(yatai_service_url, example_bento_service_class):
    yc = get_yatai_client(yatai_service_url)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    saved_path = svc.save(yatai_url=yatai_service_url)

    pulled_local_path = yc.repository.pull(f'{svc.name}:{svc.version}')
    assert pulled_local_path != saved_path
def test_load_from_dir(example_bento_service_class):
    yc = get_yatai_client()
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    saved_path = svc.save()

    loaded_svc = yc.repository.load(saved_path)
    assert loaded_svc.name == svc.name
def test_delete_all_bentos(bento_service):
    bento_service.save(version=uuid.uuid4().hex[0:8])
    bento_service.save(version=uuid.uuid4().hex[0:8])
    bento_service.save(version=uuid.uuid4().hex[0:8])

    yc = get_yatai_client()
    yc.repository.delete(prune=True)
    bentos = yc.repository.list()
    assert len(bentos) == 0
def test_list_by_name(yatai_service_url):
    class ListByNameSvc(bentoml.BentoService):
        pass

    yc = get_yatai_client(yatai_service_url)
    svc = ListByNameSvc()
    svc.save(yatai_url=yatai_service_url)

    bentos = yc.repository.list(bento_name=svc.name)
    assert len(bentos) == 1
Exemple #22
0
    def containerize(bento, push, tag, build_arg, yatai_url):
        """Containerize specified BentoService.

        BENTO is the target BentoService to be containerized, referenced by its name
        and version in format of name:version. For example: "iris_classifier:v1.2.0"

        `bentoml containerize` command also supports the use of the `latest` tag
        which will automatically use the last built version of your Bento.

        You can provide a tag for the image built by Bento using the
        `--tag` flag. Additionally, you can provide a `--push` flag,
        which will push the built image to the Docker repository specified by the
        image tag.

        You can also prefixing the tag with a hostname for the repository you wish
        to push to.
        e.g. `bentoml containerize IrisClassifier:latest --push --tag
        repo-address.com:username/iris` would build a Docker image called
        `username/iris:latest` and push that to docker repository at repo-address.com.

        By default, the `containerize` command will use the current credentials
        provided by Docker daemon.
        """
        saved_bundle_path = resolve_bundle_path(bento,
                                                pip_installed_bundle_path,
                                                yatai_url)

        _echo(f"Found Bento: {saved_bundle_path}")

        # fmt: off
        bento_metadata: "BentoServiceMetadata" = load_bento_service_metadata(
            saved_bundle_path)  # noqa: E501
        # fmt: on

        bento_tag = f'{bento_metadata.name}:{bento_metadata.version}'
        yatai_client: "YataiClient" = get_yatai_client(yatai_url)
        docker_build_args = {}
        if build_arg:
            for arg in build_arg:
                key, value = arg.split("=", 1)
                docker_build_args[key] = value
        if yatai_url is not None:
            spinner_message = f'Sending containerize RPC to YataiService at {yatai_url}'
        else:
            spinner_message = (
                f'Containerizing {bento_tag} with local YataiService and docker '
                f'daemon from local environment')
        with Spinner(spinner_message):
            tag: str = yatai_client.repository.containerize(
                bento=bento_tag,
                tag=tag,
                build_args=docker_build_args,
                push=push,
            )
            _echo(f'\nBuild container image: {tag}', CLI_COLOR_SUCCESS)
Exemple #23
0
def test_yatai_server_containerize_without_push():
    svc = ExampleBentoService()
    svc.pack('model', [1, 2, 3])
    logger.info('Saving bento service to local yatai server')
    svc.save()

    yc = get_yatai_client()
    tag = 'mytag'
    built_tag = yc.repository.containerize(bento=f'{svc.name}:{svc.version}',
                                           tag=tag)
    assert built_tag == f'{tag}:{svc.version}'
Exemple #24
0
 def list_bentos(limit, offset, labels, order_by, ascending_order,
                 yatai_url, output):
     yc = get_yatai_client(yatai_url)
     result = yc.repository.list(
         limit=limit,
         offset=offset,
         labels=labels,
         order_by=order_by,
         ascending_order=ascending_order,
     )
     _print_bentos_info(result, output)
def test_load(yatai_server_container, example_bento_service_class):
    example_bento_service_class = bentoml.ver(
        major=2, minor=5)(example_bento_service_class)
    yc = get_yatai_client(yatai_server_container)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    svc.save(yatai_url=yatai_server_container)

    loaded_svc = yc.repository.load(f'{svc.name}:{svc.version}')
    assert loaded_svc.name == svc.name
def test_list(yatai_server_container, example_bento_service_class):
    example_bento_service_class = bentoml.ver(
        major=2, minor=5)(example_bento_service_class)
    yc = get_yatai_client(yatai_server_container)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    svc.save(yatai_url=yatai_server_container)

    bentos = yc.repository.list(bento_name=svc.name)
    assert len(bentos) == 5
def test_delete_bentos_base_on_labels(bento_service):
    yc = get_yatai_client()
    yc.repository.delete(prune=True)
    bento_service.save(version=uuid.uuid4().hex[0:8], labels={'cohort': '100'})
    bento_service.save(version=uuid.uuid4().hex[0:8], labels={'cohort': '110'})
    bento_service.save(version=uuid.uuid4().hex[0:8], labels={'cohort': '120'})

    yc.repository.delete(labels='cohort in (100, 110)')
    bentos = yc.repository.list()
    assert len(bentos) == 1
    # Clean up existing bentos
    yc.repository.delete(prune=True)
def test_pull(yatai_server_container, example_bento_service_class):
    example_bento_service_class = bentoml.ver(
        major=2, minor=3)(example_bento_service_class)

    yc = get_yatai_client(yatai_server_container)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    saved_path = svc.save(yatai_url=yatai_server_container)

    pulled_local_path = yc.repository.pull(f'{svc.name}:{svc.version}')
    assert pulled_local_path != saved_path
def test_get(yatai_server_container, example_bento_service_class):
    example_bento_service_class = bentoml.ver(
        major=2, minor=4)(example_bento_service_class)

    yc = get_yatai_client(yatai_server_container)
    test_model = TestModel()
    svc = example_bento_service_class()
    svc.pack('model', test_model)
    svc.save(yatai_url=yatai_server_container)
    svc_pb = yc.repository.get(f'{svc.name}:{svc.version}')
    assert svc_pb.bento_service_metadata.name == svc.name
    assert svc_pb.bento_service_metadata.version == svc.version
def test_delete_bentos_base_on_name(bento_service):
    yc = get_yatai_client()
    yc.repository.delete(prune=True)
    bento_service.save(version=uuid.uuid4().hex[0:8])
    bento_service.save(version=uuid.uuid4().hex[0:8])
    iris = IrisClassifier()
    iris.save()

    yc.repository.delete(bento_name=bento_service.name)
    bentos = yc.repository.list()
    assert len(bentos) == 1
    # Clean up existing bentos
    yc.repository.delete(prune=True)