github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formationassignment/status_service.go (about)

     1  package formationassignment
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
     8  	"github.com/kyma-incubator/compass/components/director/internal/model"
     9  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    10  	"github.com/kyma-incubator/compass/components/director/pkg/formationconstraint"
    11  	"github.com/kyma-incubator/compass/components/director/pkg/log"
    12  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  // formationAssignmentStatusService service encapsulates all the specifics around persisting the state reported by notification receiver for a formation assignment
    17  type formationAssignmentStatusService struct {
    18  	repo                  FormationAssignmentRepository
    19  	constraintEngine      constraintEngine
    20  	faNotificationService faNotificationService
    21  }
    22  
    23  // NewFormationAssignmentStatusService creates formation assignment status service
    24  func NewFormationAssignmentStatusService(repo FormationAssignmentRepository, constraintEngine constraintEngine, faNotificationService faNotificationService) *formationAssignmentStatusService {
    25  	return &formationAssignmentStatusService{
    26  		repo:                  repo,
    27  		constraintEngine:      constraintEngine,
    28  		faNotificationService: faNotificationService,
    29  	}
    30  }
    31  
    32  // UpdateWithConstraints updates a Formation Assignment and enforces NotificationStatusReturned constraints before and after the update
    33  func (fau *formationAssignmentStatusService) UpdateWithConstraints(ctx context.Context, fa *model.FormationAssignment, operation model.FormationOperation) error {
    34  	id := fa.ID
    35  
    36  	log.C(ctx).Infof("Updating formation assignment with ID: %q", id)
    37  
    38  	tenantID, err := tenant.LoadFromContext(ctx)
    39  	if err != nil {
    40  		return errors.Wrapf(err, "while loading tenant from context")
    41  	}
    42  
    43  	joinPointDetails, err := fau.faNotificationService.PrepareDetailsForNotificationStatusReturned(ctx, tenantID, fa, operation)
    44  	if err != nil {
    45  		return errors.Wrap(err, "while preparing details for NotificationStatusReturned")
    46  	}
    47  	joinPointDetails.Location = formationconstraint.PreNotificationStatusReturned
    48  	if err := fau.constraintEngine.EnforceConstraints(ctx, formationconstraint.PreNotificationStatusReturned, joinPointDetails, joinPointDetails.Formation.FormationTemplateID); err != nil {
    49  		return errors.Wrapf(err, "while enforcing constraints for target operation %q and constraint type %q", model.NotificationStatusReturned, model.PreOperation)
    50  	}
    51  
    52  	if exists, err := fau.repo.Exists(ctx, id, tenantID); err != nil {
    53  		return errors.Wrapf(err, "while ensuring formation assignment with ID: %q exists", id)
    54  	} else if !exists {
    55  		return apperrors.NewNotFoundError(resource.FormationAssignment, id)
    56  	}
    57  
    58  	if err = fau.repo.Update(ctx, fa); err != nil {
    59  		return errors.Wrapf(err, "while updating formation assignment with ID: %q", id)
    60  	}
    61  
    62  	joinPointDetails.Location = formationconstraint.PostNotificationStatusReturned
    63  	if err := fau.constraintEngine.EnforceConstraints(ctx, formationconstraint.PostNotificationStatusReturned, joinPointDetails, joinPointDetails.Formation.FormationTemplateID); err != nil {
    64  		return errors.Wrapf(err, "while enforcing constraints for target operation %q and constraint type %q", model.NotificationStatusReturned, model.PostOperation)
    65  	}
    66  
    67  	return nil
    68  }
    69  
    70  // SetAssignmentToErrorStateWithConstraints updates Formation Assignment state to error state using the errorMessage, errorCode and state parameters.
    71  // Also, it enforces NotificationStatusReturned constraints before and after the update.
    72  func (fau *formationAssignmentStatusService) SetAssignmentToErrorStateWithConstraints(ctx context.Context, assignment *model.FormationAssignment, errorMessage string, errorCode AssignmentErrorCode, state model.FormationAssignmentState, operation model.FormationOperation) error {
    73  	assignment.State = string(state)
    74  	assignmentError := AssignmentErrorWrapper{AssignmentError{
    75  		Message:   errorMessage,
    76  		ErrorCode: errorCode,
    77  	}}
    78  	marshaled, err := json.Marshal(assignmentError)
    79  	if err != nil {
    80  		return errors.Wrapf(err, "While preparing error message for assignment with ID %q", assignment.ID)
    81  	}
    82  	assignment.Value = marshaled
    83  	if err := fau.UpdateWithConstraints(ctx, assignment, operation); err != nil {
    84  		return errors.Wrapf(err, "While updating formation assignment with id %q", assignment.ID)
    85  	}
    86  	log.C(ctx).Infof("Assignment with ID %s set to state %s", assignment.ID, assignment.State)
    87  	return nil
    88  }
    89  
    90  // DeleteWithConstraints deletes a Formation Assignment matching ID `id` and enforces NotificationStatusReturned constraints before and after delete.
    91  func (fau *formationAssignmentStatusService) DeleteWithConstraints(ctx context.Context, id string) error {
    92  	log.C(ctx).Infof("Deleting formation assignment with ID: %q", id)
    93  
    94  	tenantID, err := tenant.LoadFromContext(ctx)
    95  	if err != nil {
    96  		return errors.Wrapf(err, "while loading tenant from context")
    97  	}
    98  
    99  	fa, err := fau.repo.Get(ctx, id, tenantID)
   100  	if err != nil {
   101  		return errors.Wrapf(err, "while getting formation assignment with id %q for tenant with id %q", id, tenantID)
   102  	}
   103  
   104  	joinPointDetails, err := fau.faNotificationService.PrepareDetailsForNotificationStatusReturned(ctx, tenantID, fa, model.UnassignFormation)
   105  	if err != nil {
   106  		return errors.Wrap(err, "while preparing details for NotificationStatusReturned")
   107  	}
   108  	joinPointDetails.Location = formationconstraint.PreNotificationStatusReturned
   109  	if err = fau.constraintEngine.EnforceConstraints(ctx, formationconstraint.PreNotificationStatusReturned, joinPointDetails, joinPointDetails.Formation.FormationTemplateID); err != nil {
   110  		return errors.Wrapf(err, "while enforcing constraints for target operation %q and constraint type %q", model.NotificationStatusReturned, model.PreOperation)
   111  	}
   112  
   113  	if err = fau.repo.Delete(ctx, id, tenantID); err != nil {
   114  		return errors.Wrapf(err, "while deleting formation assignment with ID: %q", id)
   115  	}
   116  
   117  	joinPointDetails.Location = formationconstraint.PostNotificationStatusReturned
   118  	if err = fau.constraintEngine.EnforceConstraints(ctx, formationconstraint.PostNotificationStatusReturned, joinPointDetails, joinPointDetails.Formation.FormationTemplateID); err != nil {
   119  		return errors.Wrapf(err, "while enforcing constraints for target operation %q and constraint type %q", model.NotificationStatusReturned, model.PostOperation)
   120  	}
   121  
   122  	return nil
   123  }