func()

in controllers/hosting/hostingdeployment_controller.go [151:259]


func (r *HostingDeploymentReconciler) reconcileHostingDeployment(ctx reconcileRequestContext) error {

	var err error
	// Set first-touch status.
	if ctx.Deployment.Status.EndpointStatus == "" {
		if err = r.updateStatus(ctx, InitializingJobStatus); err != nil {
			return err
		}
	}

	if err = r.initializeContext(&ctx); err != nil {
		return r.updateStatusAndReturnError(ctx, string(sagemaker.EndpointStatusFailed), errors.Wrap(err, "Unable to initialize operator"))
	}

	// Add finalizer if it's not marked for deletion.
	if !HasDeletionTimestamp(ctx.Deployment.ObjectMeta) {
		if !ContainsString(ctx.Deployment.ObjectMeta.GetFinalizers(), SageMakerResourceFinalizerName) {
			ctx.Deployment.ObjectMeta.Finalizers = append(ctx.Deployment.ObjectMeta.Finalizers, SageMakerResourceFinalizerName)
			if err := r.Update(ctx, ctx.Deployment); err != nil {
				return errors.Wrap(err, "Failed to add finalizer")
			}
			ctx.Log.Info("Finalizer added")
		}
	}

	// Get the EndpointConfigName so that status updates can show it.
	// If there is an error, ignore it.
	if ctx.EndpointConfigName, err = ctx.EndpointConfigReconciler.GetSageMakerEndpointConfigName(ctx, ctx.Deployment); err != nil {
		r.Log.Info("Unable to get EndpointConfigName", "err", err)
	}

	// Get the SageMaker model names so that status updates can show them.
	// If there is an error, ignore it.
	if ctx.ModelNames, err = ctx.ModelReconciler.GetSageMakerModelNames(ctx, ctx.Deployment); err != nil {
		r.Log.Info("Unable to get model names", "err", err)
	}

	// Get the EndpointDescription from SageMaker.
	if ctx.EndpointDescription, err = ctx.SageMakerClient.DescribeEndpoint(ctx, ctx.EndpointName); err != nil {
		return r.updateStatusAndReturnError(ctx, ReconcilingEndpointStatus, errors.Wrap(err, "Unable to describe SageMaker endpoint"))
	}

	// The Endpoint does not exist. If the HostingDeployment needs to be deleted, then delete.
	// Otherwise, create the Endpoint.
	if ctx.EndpointDescription == nil {

		if HasDeletionTimestamp(ctx.Deployment.ObjectMeta) {
			return r.cleanupAndRemoveFinalizer(ctx)
		}

		if err = r.createEndpoint(ctx); err != nil {
			return r.updateStatusAndReturnError(ctx, ReconcilingEndpointStatus, errors.Wrap(err, "Unable to create Endpoint"))
		}

		// Get description and continue
		if ctx.EndpointDescription, err = ctx.SageMakerClient.DescribeEndpoint(ctx, ctx.EndpointName); err != nil {
			return r.updateStatusAndReturnError(ctx, ReconcilingEndpointStatus, errors.Wrap(err, "Unable to describe SageMaker endpoint"))
		}
	}

	// Updates and deletions are only supported in SageMaker when the Endpoint is "InService" (update or deletion) or "Failed" (only deletion).
	// Thus, gate the updates/deletes according to status.
	switch *ctx.EndpointDescription.EndpointStatus {
	case sagemaker.EndpointStatusInService:

		// Only do updates if the object is not marked as deleted.
		if !HasDeletionTimestamp(ctx.Deployment.ObjectMeta) {
			if err = r.handleUpdates(ctx); err != nil {
				return r.updateStatusAndReturnError(ctx, ReconcilingEndpointStatus, errors.Wrap(err, "Unable to update SageMaker endpoint"))
			}
		}

		// Handle deletion by falling through.
		fallthrough
	case sagemaker.EndpointStatusFailed:
		if HasDeletionTimestamp(ctx.Deployment.ObjectMeta) {
			if _, err := ctx.SageMakerClient.DeleteEndpoint(ctx, &ctx.EndpointName); err != nil && !clientwrapper.IsDeleteEndpoint404Error(err) {
				return r.updateStatusAndReturnError(ctx, ReconcilingEndpointStatus, errors.Wrap(err, "Unable to delete Endpoint"))
			}
		}
		break
	case sagemaker.EndpointStatusCreating:
		fallthrough
	case sagemaker.EndpointStatusDeleting:
		fallthrough
	case sagemaker.EndpointStatusOutOfService:
		fallthrough
	case sagemaker.EndpointStatusRollingBack:
		fallthrough
	case sagemaker.EndpointStatusSystemUpdating:
		fallthrough
	case sagemaker.EndpointStatusUpdating:
		// The status will be updated after the switch statement.
		r.Log.Info("Noop action, endpoint status does not allow modifications", "status", ctx.EndpointDescription.EndpointStatus)
	}

	status := *ctx.EndpointDescription.EndpointStatus

	// Present to the user that the endpoint is being deleted after they delete the hosting deployment.
	if HasDeletionTimestamp(ctx.Deployment.ObjectMeta) && ctx.EndpointDescription.EndpointStatus != aws.String(sagemaker.EndpointStatusDeleting) {
		status = string(sagemaker.EndpointStatusDeleting)
	}

	if err = r.updateStatus(ctx, status); err != nil {
		return err
	}

	return nil
}