Ejemplo n.º 1
0
def apply_deployment(deployment_info, yatai_service=None):
    if yatai_service is None:
        from bentoml.yatai import get_yatai_service

        yatai_service = get_yatai_service()

    try:
        if isinstance(deployment_info, dict):
            deployment_pb = deployment_dict_to_pb(deployment_info)
        elif isinstance(deployment_info, str):
            deployment_pb = deployment_yaml_string_to_pb(deployment_info)
        else:
            raise YataiDeploymentException(
                'Unexpected argument type, expect deployment info to be str in yaml '
                'format or a dict, instead got: {}'.format(
                    str(type(deployment_info))))

        validation_errors = validate_deployment_pb_schema(deployment_pb)
        if validation_errors:
            return ApplyDeploymentResponse(status=Status.INVALID_ARGUMENT(
                'Failed to validate deployment: {errors}'.format(
                    errors=validation_errors)))

        return yatai_service.ApplyDeployment(
            ApplyDeploymentRequest(deployment=deployment_pb))
    except BentoMLException as error:
        return ApplyDeploymentResponse(status=Status.INTERNAL(str(error)))
Ejemplo n.º 2
0
def exception_to_return_status(error):
    from bentoml.yatai.status import Status

    if type(error) is BentoMLInvalidArgumentException:
        return Status.INVALID_ARGUMENT(str(error))
    else:
        return Status.INTERNAL(str(error))
Ejemplo n.º 3
0
    def ApplyDeployment(self, request, context=None):
        try:
            # apply default namespace if not set
            request.deployment.namespace = (
                request.deployment.namespace or self.default_namespace
            )

            validation_errors = validate_deployment_pb_schema(request.deployment)
            if validation_errors:
                return ApplyDeploymentResponse(
                    status=Status.INVALID_ARGUMENT(
                        'Failed to validate deployment. {errors}'.format(
                            errors=validation_errors
                        )
                    )
                )

            previous_deployment = self.deployment_store.get(
                request.deployment.name, request.deployment.namespace
            )
            if previous_deployment:
                # check deployment platform
                if (
                    previous_deployment.spec.operator
                    != request.deployment.spec.operator
                ):
                    return ApplyDeploymentResponse(
                        status=Status.ABORTED(
                            'Can not change the target deploy platform of existing '
                            'active deployment. Try delete existing deployment and '
                            'deploy to new target platform again'
                        )
                    )
                request.deployment.state.state = DeploymentState.PENDING
            else:
                request.deployment.created_at.GetCurrentTime()

            request.deployment.last_updated_at.GetCurrentTime()

            self.deployment_store.insert_or_update(request.deployment)
            # find deployment operator based on deployment spec
            operator = get_deployment_operator(request.deployment)

            # deploying to target platform
            response = operator.apply(request.deployment, self, previous_deployment)

            # update deployment state
            self.deployment_store.insert_or_update(response.deployment)

            return response

        except BentoMLException as e:
            logger.error("INTERNAL ERROR: %s", e)
            return ApplyDeploymentResponse(status=Status.INTERNAL(str(e)))
Ejemplo n.º 4
0
    def apply_deployment(self, deployment_info):
        if isinstance(deployment_info, dict):
            deployment_pb = deployment_dict_to_pb(deployment_info)
        elif isinstance(deployment_info, str):
            deployment_pb = deployment_yaml_string_to_pb(deployment_info)
        elif isinstance(deployment_info, Deployment):
            deployment_pb = deployment_info
        else:
            raise YataiDeploymentException(
                'Unexpected argument type, expect deployment info to be str in yaml '
                'format or a dict or a deployment protobuf obj, instead got: {}'
                .format(str(type(deployment_info))))

        validation_errors = validate_deployment_pb_schema(deployment_pb)
        if validation_errors:
            return ApplyDeploymentResponse(status=Status.INVALID_ARGUMENT(
                'Failed to validate deployment: {errors}'.format(
                    errors=validation_errors)))

        return self.yatai_service.ApplyDeployment(
            ApplyDeploymentRequest(deployment=deployment_pb))
Ejemplo n.º 5
0
def create_deployment(
    deployment_name,
    namespace,
    bento_name,
    bento_version,
    platform,
    operator_spec,
    labels=None,
    annotations=None,
    yatai_service=None,
):
    if yatai_service is None:
        from bentoml.yatai import get_yatai_service

        yatai_service = get_yatai_service()

    # Make sure there is no active deployment with the same deployment name
    get_deployment_pb = yatai_service.GetDeployment(
        GetDeploymentRequest(deployment_name=deployment_name,
                             namespace=namespace))
    if get_deployment_pb.status.status_code == status_pb2.Status.OK:
        raise YataiDeploymentException(
            'Deployment "{name}" already existed, use Update or Apply for updating '
            'existing deployment, delete the deployment, or use a different deployment '
            'name'.format(name=deployment_name))
    if get_deployment_pb.status.status_code != status_pb2.Status.NOT_FOUND:
        raise YataiDeploymentException(
            'Failed accesing YataiService deployment store. {error_code}:'
            '{error_message}'.format(
                error_code=Status.Name(get_deployment_pb.status.status_code),
                error_message=get_deployment_pb.status.error_message,
            ))

    deployment_dict = {
        "name": deployment_name,
        "namespace": namespace
        or config().get('deployment', 'default_namespace'),
        "labels": labels,
        "annotations": annotations,
        "spec": {
            "bento_name": bento_name,
            "bento_version": bento_version,
            "operator": platform,
        },
    }

    operator = platform.replace('-', '_').upper()
    try:
        operator_value = DeploymentSpec.DeploymentOperator.Value(operator)
    except ValueError:
        return ApplyDeploymentResponse(status=Status.INVALID_ARGUMENT(
            'Invalid platform "{}"'.format(platform)))
    if operator_value == DeploymentSpec.AWS_SAGEMAKER:
        deployment_dict['spec']['sagemaker_operator_config'] = {
            'region':
            operator_spec.get('region')
            or config().get('aws', 'default_region'),
            'instance_count':
            operator_spec.get('instance_count'),
            'instance_type':
            operator_spec.get('instance_type'),
            'api_name':
            operator_spec.get('api_name', ''),
        }
        if operator_spec.get('num_of_gunicorn_workers_per_instance'):
            deployment_dict['spec']['sagemaker_operator_config'][
                'num_of_gunicorn_workers_per_instance'] = operator_spec.get(
                    'num_of_gunicorn_workers_per_instance')
    elif operator_value == DeploymentSpec.AWS_LAMBDA:
        deployment_dict['spec']['aws_lambda_operator_config'] = {
            'region':
            operator_spec.get('region')
            or config().get('aws', 'default_region')
        }
        for field in ['api_name', 'memory_size', 'timeout']:
            if operator_spec.get(field):
                deployment_dict['spec']['aws_lambda_operator_config'][
                    field] = operator_spec[field]
    elif operator_value == DeploymentSpec.KUBERNETES:
        deployment_dict['spec']['kubernetes_operator_config'] = {
            'kube_namespace': operator_spec.get('kube_namespace', ''),
            'replicas': operator_spec.get('replicas', 0),
            'service_name': operator_spec.get('service_name', ''),
            'service_type': operator_spec.get('service_type', ''),
        }
    else:
        raise YataiDeploymentException(
            'Platform "{}" is not supported in the current version of '
            'BentoML'.format(platform))

    apply_response = apply_deployment(deployment_dict, yatai_service)

    if apply_response.status.status_code == status_pb2.Status.OK:
        describe_response = describe_deployment(deployment_name, namespace,
                                                yatai_service)
        if describe_response.status.status_code == status_pb2.Status.OK:
            deployment_state = describe_response.state
            apply_response.deployment.state.CopyFrom(deployment_state)
            return apply_response

    return apply_response
Ejemplo n.º 6
0
def create_deployment(
    deployment_name,
    namespace,
    bento_name,
    bento_version,
    platform,
    operator_spec,
    labels=None,
    annotations=None,
    yatai_service=None,
):
    if yatai_service is None:
        from bentoml.yatai import get_yatai_service

        yatai_service = get_yatai_service()

    try:
        # Make sure there is no active deployment with the same deployment name
        get_deployment_pb = yatai_service.GetDeployment(
            GetDeploymentRequest(deployment_name=deployment_name, namespace=namespace)
        )
        if get_deployment_pb.status.status_code == status_pb2.Status.OK:
            raise BentoMLDeploymentException(
                'Deployment "{name}" already existed, use Update or Apply for updating'
                'existing deployment, or create the deployment with a different name or'
                'under a different deployment namespace'.format(name=deployment_name)
            )
        if get_deployment_pb.status.status_code != status_pb2.Status.NOT_FOUND:
            raise BentoMLDeploymentException(
                'Failed accesing YataiService deployment store. {error_code}:'
                '{error_message}'.format(
                    error_code=Status.Name(get_deployment_pb.status.status_code),
                    error_message=get_deployment_pb.status.error_message,
                )
            )

        deployment_dict = {
            "name": deployment_name,
            "namespace": namespace or config().get('deployment', 'default_namespace'),
            "labels": labels,
            "annotations": annotations,
            "spec": {
                "bento_name": bento_name,
                "bento_version": bento_version,
                "operator": platform,
            },
        }

        operator = platform.replace('-', '_').upper()
        try:
            operator_value = DeploymentSpec.DeploymentOperator.Value(operator)
        except ValueError:
            return ApplyDeploymentResponse(
                status=Status.INVALID_ARGUMENT('Invalid platform "{}"'.format(platform))
            )
        if operator_value == DeploymentSpec.AWS_SAGEMAKER:
            deployment_dict['spec']['sagemaker_operator_config'] = {
                'region': operator_spec.get('region')
                or config().get('aws', 'default_region'),
                'instance_count': operator_spec.get('instance_count')
                or config().getint('sagemaker', 'default_instance_count'),
                'instance_type': operator_spec.get('instance_type')
                or config().get('sagemaker', 'default_instance_type'),
                'api_name': operator_spec.get('api_name', ''),
            }
        elif operator_value == DeploymentSpec.AWS_LAMBDA:
            deployment_dict['spec']['aws_lambda_operator_config'] = {
                'region': operator_spec.get('region')
                or config().get('aws', 'default_region')
            }
            if operator_spec.get('api_name'):
                deployment_dict['spec']['aws_lambda_operator_config'][
                    'api_name'
                ] = operator_spec['api_name']
        elif operator_value == DeploymentSpec.GCP_FCUNTION:
            deployment_dict['spec']['gcp_function_operatorConfig'] = {
                'region': operator_spec.get('region')
                or config().get('google-cloud', 'default_region')
            }
            if operator_spec.get('api_name'):
                deployment_dict['spec']['gcp_function_operator_config'][
                    'api_name'
                ] = operator_spec['api_name']
        elif operator_value == DeploymentSpec.KUBERNETES:
            deployment_dict['spec']['kubernetes_operator_config'] = {
                'kube_namespace': operator_spec.get('kube_namespace', ''),
                'replicas': operator_spec.get('replicas', 0),
                'service_name': operator_spec.get('service_name', ''),
                'service_type': operator_spec.get('service_type', ''),
            }
        else:
            raise BentoMLDeploymentException(
                'Platform "{}" is not supported in the current version of '
                'BentoML'.format(platform)
            )

        return apply_deployment(deployment_dict, yatai_service)
    except BentoMLException as error:
        return ApplyDeploymentResponse(status=Status.INTERNAL(str(error)))