def DescribeDeployment(self, request, context=None): try: request.namespace = request.namespace or self.default_namespace deployment_pb = self.deployment_store.get( request.deployment_name, request.namespace ) if deployment_pb: operator = get_deployment_operator(deployment_pb) response = operator.describe(deployment_pb, self) if response.status.status_code == status_pb2.Status.OK: with self.deployment_store.update_deployment( request.deployment_name, request.namespace ) as deployment: deployment.state = ProtoMessageToDict(response.state) return response else: return DescribeDeploymentResponse( status=Status.NOT_FOUND( 'Deployment "{}" in namespace "{}" not found'.format( request.deployment_name, request.namespace ) ) ) except BentoMLException as e: logger.error("INTERNAL ERROR: %s", e) return DescribeDeploymentResponse(Status.INTERNAL(str(e)))
def describe(self, deployment_pb): try: deployment_spec = deployment_pb.spec sagemaker_config = deployment_spec.sagemaker_operator_config sagemaker_client = boto3.client('sagemaker', sagemaker_config.region) _, _, sagemaker_endpoint_name = _get_sagemaker_resource_names(deployment_pb) try: endpoint_status_response = sagemaker_client.describe_endpoint( EndpointName=sagemaker_endpoint_name ) except ClientError as e: raise _aws_client_error_to_bentoml_exception( e, f"Failed to fetch current status of sagemaker endpoint " f"'{sagemaker_endpoint_name}'", ) logger.debug("AWS describe endpoint response: %s", endpoint_status_response) endpoint_status = endpoint_status_response["EndpointStatus"] service_state = ENDPOINT_STATUS_TO_STATE[endpoint_status] deployment_state = DeploymentState( state=service_state, info_json=json.dumps(endpoint_status_response, default=str), ) deployment_state.timestamp.GetCurrentTime() return DescribeDeploymentResponse( state=deployment_state, status=Status.OK() ) except BentoMLException as error: return DescribeDeploymentResponse(status=error.status_proto)
def describe(self, deployment_pb, repo=None): deployment_spec = deployment_pb.spec sagemaker_config = deployment_spec.sagemaker_operator_config if sagemaker_config is None: raise BentoMLDeploymentException( 'Sagemaker configuration is missing.') sagemaker_client = boto3.client('sagemaker', sagemaker_config.region) endpoint_name = generate_aws_compatible_string( deployment_pb.namespace + '-' + deployment_spec.bento_name) try: endpoint_status_response = sagemaker_client.describe_endpoint( EndpointName=endpoint_name) except ClientError as e: status = _parse_aws_client_exception_or_raise(e) status.error_message = ( 'Failed to describe SageMaker deployment: %s', status.error_message, ) return DescribeDeploymentResponse(status=status) logger.debug("AWS describe endpoint response: %s", endpoint_status_response) endpoint_status = endpoint_status_response["EndpointStatus"] service_state = ENDPOINT_STATUS_TO_STATE[endpoint_status] deployment_state = DeploymentState( state=service_state, info_json=json.dumps(endpoint_status_response, default=str), ) return DescribeDeploymentResponse(state=deployment_state, status=Status.OK())
def describe(self, deployment_pb, yatai_service=None): try: deployment_spec = deployment_pb.spec aws_config = deployment_spec.aws_lambda_operator_config info_json = {'endpoints': []} bento_pb = yatai_service.GetBento( GetBentoRequest( bento_name=deployment_spec.bento_name, bento_version=deployment_spec.bento_version, ) ) bento_service_metadata = bento_pb.bento.bento_service_metadata api_names = ( [aws_config.api_name] if aws_config.api_name else [api.name for api in bento_service_metadata.apis] ) try: cloud_formation_stack_result = boto3.client( 'cloudformation' ).describe_stacks( StackName='{name}-{ns}'.format( ns=deployment_pb.namespace, name=deployment_pb.name ) ) outputs = cloud_formation_stack_result.get('Stacks')[0]['Outputs'] except Exception as error: state = DeploymentState( state=DeploymentState.ERROR, error_message=str(error) ) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse( status=Status.INTERNAL(str(error)), state=state ) base_url = '' for output in outputs: if output['OutputKey'] == 'ServiceEndpoint': base_url = output['OutputValue'] break if base_url: info_json['endpoints'] = [ base_url + '/' + api_name for api_name in api_names ] state = DeploymentState( state=DeploymentState.RUNNING, info_json=json.dumps(info_json) ) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse(status=Status.OK(), state=state) except BentoMLException as error: return DescribeDeploymentResponse(status=exception_to_return_status(error))
def describe(self, deployment_pb, repo=None): deployment_spec = deployment_pb.spec aws_config = deployment_spec.aws_lambda_operator_config bento_path = repo.get(deployment_spec.bento_name, deployment_spec.bento_version) bento_config = load_bentoml_config(bento_path) with TemporaryServerlessConfig( archive_path=bento_path, deployment_name=deployment_pb.name, region=aws_config.region, stage=deployment_pb.namespace, provider_name='aws', functions=generate_aws_handler_functions_config( bento_config['apis']), ) as tempdir: try: response = call_serverless_command(["serverless", "info"], tempdir) info_json = parse_serverless_info_response_to_json_string( response) state = DeploymentState(state=DeploymentState.RUNNING, info_json=info_json) except BentoMLException as e: state = DeploymentState(state=DeploymentState.ERROR, error_message=str(e)) return DescribeDeploymentResponse(status=Status.OK(), state=state)
def create_yatai_service_mock(): yatai_service_mock = Mock() yatai_service_mock.ApplyDeployment.return_value = ApplyDeploymentResponse() yatai_service_mock.DeleteDeployment.return_value = DeleteDeploymentResponse() yatai_service_mock.DescribeDeployment.return_value = DescribeDeploymentResponse() yatai_service_mock.GetDeployment.return_value = GetDeploymentResponse( status=Status.NOT_FOUND() ) yatai_service_mock.ListDeployments.return_value = ListDeploymentsResponse() return yatai_service_mock
def describe(self, deployment_pb, yatai_service=None): try: deployment_spec = deployment_pb.spec gcp_config = deployment_spec.gcp_function_operator_config bento_pb = yatai_service.GetBento( GetBentoRequest( bento_name=deployment_spec.bento_name, bento_version=deployment_spec.bento_version, )) bento_service_metadata = bento_pb.bento.bento_service_metadata api_names = ([gcp_config.api_name] if gcp_config.api_name else [api.name for api in bento_service_metadata.apis]) with TempDirectory() as serverless_project_dir: generate_gcp_function_serverless_config( deployment_pb.name, api_names, serverless_project_dir, gcp_config.region, # BentoML namespace is mapping to serverless stage. stage=deployment_pb.namespace, ) try: response = call_serverless_command(["info"], serverless_project_dir) info_json = parse_serverless_info_response_to_json_string( response) state = DeploymentState(state=DeploymentState.RUNNING, info_json=info_json) state.timestamp.GetCurrentTime() except BentoMLException as e: state = DeploymentState(state=DeploymentState.ERROR, error_message=str(e)) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse(status=Status.OK(), state=state) except BentoMLException as error: return DescribeDeploymentResponse( status=exception_to_return_status(error))
def describe(self, deployment_pb): try: deployment_spec = deployment_pb.spec lambda_deployment_config = deployment_spec.aws_lambda_operator_config lambda_deployment_config.region = (lambda_deployment_config.region or get_default_aws_region()) if not lambda_deployment_config.region: raise InvalidArgument('AWS region is missing') bento_pb = self.yatai_service.GetBento( GetBentoRequest( bento_name=deployment_spec.bento_name, bento_version=deployment_spec.bento_version, )) bento_service_metadata = bento_pb.bento.bento_service_metadata api_names = ([lambda_deployment_config.api_name] if lambda_deployment_config.api_name else [api.name for api in bento_service_metadata.apis]) try: cf_client = boto3.client('cloudformation', lambda_deployment_config.region) cloud_formation_stack_result = cf_client.describe_stacks( StackName='{ns}-{name}'.format(ns=deployment_pb.namespace, name=deployment_pb.name)) stack_result = cloud_formation_stack_result.get('Stacks')[0] # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/\ # using-cfn-describing-stacks.html success_status = ['CREATE_COMPLETE', 'UPDATE_COMPLETE'] if stack_result['StackStatus'] in success_status: if stack_result.get('Outputs'): outputs = stack_result['Outputs'] else: return DescribeDeploymentResponse( status=Status.ABORTED( '"Outputs" field is not present'), state=DeploymentState( state=DeploymentState.ERROR, error_message='"Outputs" field is not present', ), ) elif stack_result[ 'StackStatus'] in FAILED_CLOUDFORMATION_STACK_STATUS: state = DeploymentState(state=DeploymentState.FAILED) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse(status=Status.OK(), state=state) else: state = DeploymentState(state=DeploymentState.PENDING) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse(status=Status.OK(), state=state) except Exception as error: # pylint: disable=broad-except state = DeploymentState(state=DeploymentState.ERROR, error_message=str(error)) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse(status=Status.INTERNAL( str(error)), state=state) outputs = {o['OutputKey']: o['OutputValue'] for o in outputs} info_json = {} if 'EndpointUrl' in outputs: info_json['endpoints'] = [ outputs['EndpointUrl'] + '/' + api_name for api_name in api_names ] if 'S3Bucket' in outputs: info_json['s3_bucket'] = outputs['S3Bucket'] state = DeploymentState(state=DeploymentState.RUNNING, info_json=json.dumps(info_json)) state.timestamp.GetCurrentTime() return DescribeDeploymentResponse(status=Status.OK(), state=state) except BentoMLException as error: return DescribeDeploymentResponse(status=error.status_proto)