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

     1  package bundle
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
     7  
     8  	"github.com/kyma-incubator/compass/components/director/pkg/log"
     9  
    10  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    11  
    12  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    13  	"github.com/kyma-incubator/compass/components/director/internal/model"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  // BundleRepository missing godoc
    18  //
    19  //go:generate mockery --name=BundleRepository --output=automock --outpkg=automock --case=underscore --disable-version-string
    20  type BundleRepository interface {
    21  	Create(ctx context.Context, tenant string, item *model.Bundle) error
    22  	CreateGlobal(ctx context.Context, model *model.Bundle) error
    23  	Update(ctx context.Context, tenant string, item *model.Bundle) error
    24  	UpdateGlobal(ctx context.Context, model *model.Bundle) error
    25  	Delete(ctx context.Context, tenant, id string) error
    26  	DeleteGlobal(ctx context.Context, id string) error
    27  	Exists(ctx context.Context, tenant, id string) (bool, error)
    28  	GetByID(ctx context.Context, tenant, id string) (*model.Bundle, error)
    29  	GetByIDGlobal(ctx context.Context, id string) (*model.Bundle, error)
    30  	GetForApplication(ctx context.Context, tenant string, id string, applicationID string) (*model.Bundle, error)
    31  	ListByResourceIDNoPaging(ctx context.Context, tenantID, appID string, resourceType resource.Type) ([]*model.Bundle, error)
    32  	ListByApplicationIDs(ctx context.Context, tenantID string, applicationIDs []string, pageSize int, cursor string) ([]*model.BundlePage, error)
    33  }
    34  
    35  // UIDService missing godoc
    36  //
    37  //go:generate mockery --name=UIDService --output=automock --outpkg=automock --case=underscore --disable-version-string
    38  type UIDService interface {
    39  	Generate() string
    40  }
    41  
    42  type service struct {
    43  	bndlRepo    BundleRepository
    44  	apiSvc      APIService
    45  	eventSvc    EventService
    46  	documentSvc DocumentService
    47  
    48  	uidService UIDService
    49  }
    50  
    51  // NewService missing godoc
    52  func NewService(bndlRepo BundleRepository, apiSvc APIService, eventSvc EventService, documentSvc DocumentService, uidService UIDService) *service {
    53  	return &service{
    54  		bndlRepo:    bndlRepo,
    55  		apiSvc:      apiSvc,
    56  		eventSvc:    eventSvc,
    57  		documentSvc: documentSvc,
    58  		uidService:  uidService,
    59  	}
    60  }
    61  
    62  // Create missing godoc
    63  func (s *service) Create(ctx context.Context, resourceType resource.Type, resourceID string, in model.BundleCreateInput) (string, error) {
    64  	return s.CreateBundle(ctx, resourceType, resourceID, in, 0)
    65  }
    66  
    67  // CreateBundle Creates bundle for an application with given id
    68  func (s *service) CreateBundle(ctx context.Context, resourceType resource.Type, resourceID string, in model.BundleCreateInput, bndlHash uint64) (string, error) {
    69  	id := s.uidService.Generate()
    70  	bndl := in.ToBundle(id, resourceType, resourceID, bndlHash)
    71  
    72  	if err := s.createBundle(ctx, bndl, resourceType); err != nil {
    73  		return "", errors.Wrapf(err, "error occurred while creating a Bundle with id %s and name %s for %s with id %s", id, bndl.Name, resourceType, resourceID)
    74  	}
    75  
    76  	log.C(ctx).Infof("Successfully created a Bundle with id %s and name %s for %s with id %s", id, bndl.Name, resourceType, resourceID)
    77  
    78  	log.C(ctx).Infof("Creating related resources in Bundle with id %s and name %s for %s with id %s", id, bndl.Name, resourceType, resourceID)
    79  	if err := s.createRelatedResources(ctx, in, id, resourceType, resourceID); err != nil {
    80  		return "", errors.Wrapf(err, "while creating related resources for %s with id %s", resourceType, resourceID)
    81  	}
    82  
    83  	return id, nil
    84  }
    85  
    86  // CreateMultiple missing godoc
    87  func (s *service) CreateMultiple(ctx context.Context, resourceType resource.Type, resourceID string, in []*model.BundleCreateInput) error {
    88  	if in == nil {
    89  		return nil
    90  	}
    91  
    92  	for _, bndl := range in {
    93  		if bndl == nil {
    94  			continue
    95  		}
    96  
    97  		if _, err := s.Create(ctx, resourceType, resourceID, *bndl); err != nil {
    98  			return errors.Wrapf(err, "while creating Bundle for %s with id %s", resourceType, resourceID)
    99  		}
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  // Update missing godoc
   106  func (s *service) Update(ctx context.Context, resourceType resource.Type, id string, in model.BundleUpdateInput) error {
   107  	return s.UpdateBundle(ctx, resourceType, id, in, 0)
   108  }
   109  
   110  // UpdateBundle missing godoc
   111  func (s *service) UpdateBundle(ctx context.Context, resourceType resource.Type, id string, in model.BundleUpdateInput, bndlHash uint64) error {
   112  	bndl, err := s.getBundle(ctx, id, resourceType)
   113  	if err != nil {
   114  		return errors.Wrapf(err, "while getting Bundle with id %s", id)
   115  	}
   116  
   117  	bndl.SetFromUpdateInput(in, bndlHash)
   118  
   119  	if err = s.updateBundle(ctx, bndl, resourceType); err != nil {
   120  		return errors.Wrapf(err, "while updating Bundle with id %s", id)
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  // Delete deletes a bundle by id
   127  func (s *service) Delete(ctx context.Context, resourceType resource.Type, id string) error {
   128  	if err := s.deleteBundle(ctx, id, resourceType); err != nil {
   129  		return errors.Wrapf(err, "while deleting Bundle with id %s", id)
   130  	}
   131  
   132  	log.C(ctx).Infof("Successfully deleted a bundle with ID %s", id)
   133  
   134  	return nil
   135  }
   136  
   137  // Exist missing godoc
   138  func (s *service) Exist(ctx context.Context, id string) (bool, error) {
   139  	tnt, err := tenant.LoadFromContext(ctx)
   140  	if err != nil {
   141  		return false, errors.Wrap(err, "while loading tenant from context")
   142  	}
   143  
   144  	exist, err := s.bndlRepo.Exists(ctx, tnt, id)
   145  	if err != nil {
   146  		return false, errors.Wrapf(err, "while getting Bundle with ID: [%s]", id)
   147  	}
   148  
   149  	return exist, nil
   150  }
   151  
   152  // Get missing godoc
   153  func (s *service) Get(ctx context.Context, id string) (*model.Bundle, error) {
   154  	tnt, err := tenant.LoadFromContext(ctx)
   155  	if err != nil {
   156  		return nil, errors.Wrap(err, "while loading tenant from context")
   157  	}
   158  
   159  	bndl, err := s.bndlRepo.GetByID(ctx, tnt, id)
   160  	if err != nil {
   161  		return nil, errors.Wrapf(err, "while getting Bundle with ID: [%s]", id)
   162  	}
   163  
   164  	return bndl, nil
   165  }
   166  
   167  // GetForApplication missing godoc
   168  func (s *service) GetForApplication(ctx context.Context, id string, applicationID string) (*model.Bundle, error) {
   169  	tnt, err := tenant.LoadFromContext(ctx)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	bndl, err := s.bndlRepo.GetForApplication(ctx, tnt, id, applicationID)
   175  	if err != nil {
   176  		return nil, errors.Wrapf(err, "while getting Bundle with ID: [%s]", id)
   177  	}
   178  
   179  	return bndl, nil
   180  }
   181  
   182  // ListByApplicationIDNoPaging missing godoc
   183  func (s *service) ListByApplicationIDNoPaging(ctx context.Context, appID string) ([]*model.Bundle, error) {
   184  	tnt, err := tenant.LoadFromContext(ctx)
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	return s.bndlRepo.ListByResourceIDNoPaging(ctx, tnt, appID, resource.Application)
   190  }
   191  
   192  // ListByApplicationTemplateVersionIDNoPaging lists bundles by Application Template Version ID without tenant isolation
   193  func (s *service) ListByApplicationTemplateVersionIDNoPaging(ctx context.Context, appTemplateVersionID string) ([]*model.Bundle, error) {
   194  	return s.bndlRepo.ListByResourceIDNoPaging(ctx, "", appTemplateVersionID, resource.ApplicationTemplateVersion)
   195  }
   196  
   197  // ListByApplicationIDs missing godoc
   198  func (s *service) ListByApplicationIDs(ctx context.Context, applicationIDs []string, pageSize int, cursor string) ([]*model.BundlePage, error) {
   199  	tnt, err := tenant.LoadFromContext(ctx)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	if pageSize < 1 || pageSize > 200 {
   205  		return nil, apperrors.NewInvalidDataError("page size must be between 1 and 200")
   206  	}
   207  
   208  	return s.bndlRepo.ListByApplicationIDs(ctx, tnt, applicationIDs, pageSize, cursor)
   209  }
   210  
   211  func (s *service) createRelatedResources(ctx context.Context, in model.BundleCreateInput, bundleID string, resourceType resource.Type, resourceID string) error {
   212  	for i := range in.APIDefinitions {
   213  		if _, err := s.apiSvc.CreateInBundle(ctx, resourceType, resourceID, bundleID, *in.APIDefinitions[i], in.APISpecs[i]); err != nil {
   214  			return errors.Wrapf(err, "while creating APIs for bundle with id %q", bundleID)
   215  		}
   216  	}
   217  
   218  	for i := range in.EventDefinitions {
   219  		if _, err := s.eventSvc.CreateInBundle(ctx, resourceType, resourceID, bundleID, *in.EventDefinitions[i], in.EventSpecs[i]); err != nil {
   220  			return errors.Wrapf(err, "while creating Event for bundle with id %q", bundleID)
   221  		}
   222  	}
   223  
   224  	for _, document := range in.Documents {
   225  		if _, err := s.documentSvc.CreateInBundle(ctx, resourceType, resourceID, bundleID, *document); err != nil {
   226  			return errors.Wrapf(err, "while creating Document for bundle with id %q", bundleID)
   227  		}
   228  	}
   229  
   230  	return nil
   231  }
   232  
   233  func (s *service) createBundle(ctx context.Context, bundle *model.Bundle, resourceType resource.Type) error {
   234  	if resourceType.IsTenantIgnorable() {
   235  		return s.bndlRepo.CreateGlobal(ctx, bundle)
   236  	}
   237  
   238  	tnt, err := tenant.LoadFromContext(ctx)
   239  	if err != nil {
   240  		return err
   241  	}
   242  
   243  	return s.bndlRepo.Create(ctx, tnt, bundle)
   244  }
   245  
   246  func (s *service) getBundle(ctx context.Context, bundleID string, resourceType resource.Type) (*model.Bundle, error) {
   247  	if resourceType.IsTenantIgnorable() {
   248  		return s.bndlRepo.GetByIDGlobal(ctx, bundleID)
   249  	}
   250  
   251  	return s.Get(ctx, bundleID)
   252  }
   253  
   254  func (s *service) updateBundle(ctx context.Context, bndl *model.Bundle, resourceType resource.Type) error {
   255  	if resourceType.IsTenantIgnorable() {
   256  		return s.bndlRepo.UpdateGlobal(ctx, bndl)
   257  	}
   258  
   259  	tnt, err := tenant.LoadFromContext(ctx)
   260  	if err != nil {
   261  		return err
   262  	}
   263  
   264  	return s.bndlRepo.Update(ctx, tnt, bndl)
   265  }
   266  
   267  func (s *service) deleteBundle(ctx context.Context, bundleID string, resourceType resource.Type) error {
   268  	if resourceType.IsTenantIgnorable() {
   269  		return s.bndlRepo.DeleteGlobal(ctx, bundleID)
   270  	}
   271  
   272  	tnt, err := tenant.LoadFromContext(ctx)
   273  	if err != nil {
   274  		return err
   275  	}
   276  
   277  	return s.bndlRepo.Delete(ctx, tnt, bundleID)
   278  }