예제 #1
0
def test_validate_aws_lambda_schema():
    deployment_pb = _get_test_lambda_deployment_pb()
    assert validate_deployment_pb(deployment_pb) is None

    deployment_pb_with_bad_memory_size = _get_test_lambda_deployment_pb()
    deployment_pb_with_bad_memory_size.spec.aws_lambda_operator_config.timeout = 1000
    deployment_pb_with_bad_memory_size.spec.aws_lambda_operator_config.memory_size = 129
    errors = validate_deployment_pb(deployment_pb_with_bad_memory_size)
    aws_spec_fail_msg = errors['spec'][0]['aws_lambda_operator_config'][0]

    assert 'AWS Lambda memory' in aws_spec_fail_msg['memory_size'][0]
    assert 'max value is 900' in aws_spec_fail_msg['timeout'][0]
예제 #2
0
    def apply(self, deployment_info, wait):
        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(deployment_pb)
        if validation_errors:
            raise YataiDeploymentException(
                f'Failed to validate deployment {deployment_pb.name}: '
                f'{validation_errors}')

        apply_result = self.yatai_service.ApplyDeployment(
            ApplyDeploymentRequest(deployment=deployment_pb))
        if apply_result.status.status_code != status_pb2.Status.OK:
            error_code, error_message = status_pb_to_error_code_and_message(
                apply_result.status)
            raise YataiDeploymentException(f'{error_code}:{error_message}')
        if wait:
            self._wait_deployment_action_complete(deployment_pb.name,
                                                  deployment_pb.namespace)
        return self.get(namespace=deployment_pb.namespace,
                        name=deployment_pb.name)
예제 #3
0
def test_validate_deployment_pb_schema():
    deployment_pb = _get_test_sagemaker_deployment_pb()
    assert validate_deployment_pb(deployment_pb) is None

    deployment_pb_with_empty_name = _get_test_sagemaker_deployment_pb()
    deployment_pb_with_empty_name.name = ''
    errors = validate_deployment_pb(deployment_pb_with_empty_name)
    assert errors == {'name': ['required field']}

    deployment_pb_with_invalid_service_version = _get_test_sagemaker_deployment_pb(
    )
    deployment_pb_with_invalid_service_version.spec.bento_version = 'latest'
    errors = validate_deployment_pb(deployment_pb_with_invalid_service_version)
    assert errors['spec'][0]['bento_version'] == [
        'Must use specific "bento_version" in deployment, using "latest" is an '
        'anti-pattern.'
    ]
예제 #4
0
    def create(self, deployment_info, wait):
        from bentoml.yatai.validator import validate_deployment_pb

        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(deployment_pb)
        if validation_errors:
            raise YataiDeploymentException(
                f'Failed to validate deployment {deployment_pb.name}: '
                f'{validation_errors}'
            )
        # Make sure there is no active deployment with the same deployment name
        get_deployment_pb = self.yatai_service.GetDeployment(
            GetDeploymentRequest(
                deployment_name=deployment_pb.name, namespace=deployment_pb.namespace
            )
        )
        if get_deployment_pb.status.status_code != status_pb2.Status.NOT_FOUND:
            raise BentoMLException(
                f'Deployment "{deployment_pb.name}" already existed, use Update or '
                f'Apply for updating existing deployment, delete the deployment, '
                f'or use a different deployment name'
            )
        apply_result = self.yatai_service.ApplyDeployment(
            ApplyDeploymentRequest(deployment=deployment_pb)
        )
        if apply_result.status.status_code != status_pb2.Status.OK:
            error_code, error_message = status_pb_to_error_code_and_message(
                apply_result.status
            )
            raise YataiDeploymentException(f'{error_code}:{error_message}')
        if wait:
            self._wait_deployment_action_complete(
                deployment_pb.name, deployment_pb.namespace
            )
        return self.get(namespace=deployment_pb.namespace, name=deployment_pb.name)
예제 #5
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(request.deployment)
            if validation_errors:
                raise InvalidArgument(
                    'Failed to validate deployment. {errors}'.format(
                        errors=validation_errors))

            previous_deployment = self.deployment_store.get(
                request.deployment.name, request.deployment.namespace)
            if not previous_deployment:
                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(self, request.deployment)

            # deploying to target platform
            if previous_deployment:
                response = operator.update(request.deployment,
                                           previous_deployment)
            else:
                response = operator.add(request.deployment)

            if response.status.status_code == status_pb2.Status.OK:
                # update deployment state
                if response and response.deployment:
                    self.deployment_store.insert_or_update(response.deployment)
                else:
                    raise BentoMLException(
                        "DeploymentOperator Internal Error: failed to add or update "
                        "deployment metadata to database")
                logger.info(
                    "ApplyDeployment (%s, namespace %s) succeeded",
                    request.deployment.name,
                    request.deployment.namespace,
                )
            else:
                if not previous_deployment:
                    # When failed to create the deployment, delete it from active
                    # deployments records
                    self.deployment_store.delete(request.deployment.name,
                                                 request.deployment.namespace)
                logger.debug(
                    "ApplyDeployment (%s, namespace %s) failed: %s",
                    request.deployment.name,
                    request.deployment.namespace,
                    response.status.error_message,
                )

            return response

        except BentoMLException as e:
            logger.error("RPC ERROR ApplyDeployment: %s", e)
            return ApplyDeploymentResponse(status=e.status_proto)
        except Exception as e:
            logger.error("URPC ERROR ApplyDeployment: %s", e)
            return ApplyDeploymentResponse(status=Status.INTERNAL(str(e)))