github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/storage/driver/memory/operation.go (about)

     1  package memory
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/kyma-project/kyma-environment-broker/common/orchestration"
    10  	"github.com/kyma-project/kyma-environment-broker/common/pagination"
    11  	"github.com/kyma-project/kyma-environment-broker/internal"
    12  	"github.com/kyma-project/kyma-environment-broker/internal/storage/dberr"
    13  	"github.com/kyma-project/kyma-environment-broker/internal/storage/dbmodel"
    14  
    15  	"github.com/pivotal-cf/brokerapi/v8/domain"
    16  )
    17  
    18  const (
    19  	Retrying   = "retrying" // to signal a retry sign before marking it to pending
    20  	Succeeded  = "succeeded"
    21  	Failed     = "failed"
    22  	InProgress = "in progress"
    23  )
    24  
    25  type operations struct {
    26  	mu sync.Mutex
    27  
    28  	operations               map[string]internal.Operation
    29  	upgradeClusterOperations map[string]internal.UpgradeClusterOperation
    30  	updateOperations         map[string]internal.UpdatingOperation
    31  }
    32  
    33  // NewOperation creates in-memory storage for OSB operations.
    34  func NewOperation() *operations {
    35  	return &operations{
    36  		operations:               make(map[string]internal.Operation, 0),
    37  		upgradeClusterOperations: make(map[string]internal.UpgradeClusterOperation, 0),
    38  		updateOperations:         make(map[string]internal.UpdatingOperation, 0),
    39  	}
    40  }
    41  
    42  func (s *operations) InsertProvisioningOperation(operation internal.ProvisioningOperation) error {
    43  	s.mu.Lock()
    44  	defer s.mu.Unlock()
    45  
    46  	id := operation.ID
    47  	if _, exists := s.operations[id]; exists {
    48  		return dberr.AlreadyExists("instance operation with id %s already exist", id)
    49  	}
    50  
    51  	s.operations[id] = operation.Operation
    52  	return nil
    53  }
    54  
    55  func (s *operations) InsertOperation(operation internal.Operation) error {
    56  	s.mu.Lock()
    57  	defer s.mu.Unlock()
    58  
    59  	id := operation.ID
    60  	if _, exists := s.operations[id]; exists {
    61  		return dberr.AlreadyExists("instance operation with id %s already exist", id)
    62  	}
    63  
    64  	s.operations[id] = operation
    65  	return nil
    66  }
    67  
    68  func (s *operations) GetProvisioningOperationByID(operationID string) (*internal.ProvisioningOperation, error) {
    69  	s.mu.Lock()
    70  	defer s.mu.Unlock()
    71  
    72  	op, exists := s.operations[operationID]
    73  	if !exists {
    74  		return nil, dberr.NotFound("instance provisioning operation with id %s not found", operationID)
    75  	}
    76  	return &internal.ProvisioningOperation{Operation: op}, nil
    77  }
    78  
    79  func (s *operations) GetProvisioningOperationByInstanceID(instanceID string) (*internal.ProvisioningOperation, error) {
    80  	s.mu.Lock()
    81  	defer s.mu.Unlock()
    82  
    83  	var result []internal.ProvisioningOperation
    84  
    85  	for _, op := range s.operations {
    86  		if op.InstanceID == instanceID && op.Type == internal.OperationTypeProvision {
    87  			result = append(result, internal.ProvisioningOperation{Operation: op})
    88  		}
    89  	}
    90  	if len(result) != 0 {
    91  		s.sortProvisioningByCreatedAtDesc(result)
    92  		return &result[0], nil
    93  	}
    94  
    95  	return nil, dberr.NotFound("instance provisioning operation with instanceID %s not found", instanceID)
    96  }
    97  
    98  func (s *operations) GetOperationByInstanceID(instanceID string) (*internal.Operation, error) {
    99  	s.mu.Lock()
   100  	defer s.mu.Unlock()
   101  
   102  	var result []internal.Operation
   103  
   104  	for _, op := range s.operations {
   105  		if op.InstanceID == instanceID {
   106  			result = append(result, op)
   107  		}
   108  	}
   109  	if len(result) != 0 {
   110  		s.sortOperationsByCreatedAtDesc(result)
   111  		return &result[0], nil
   112  	}
   113  
   114  	return nil, dberr.NotFound("instance provisioning operation with instanceID %s not found", instanceID)
   115  }
   116  
   117  func (s *operations) UpdateProvisioningOperation(op internal.ProvisioningOperation) (*internal.ProvisioningOperation, error) {
   118  	s.mu.Lock()
   119  	defer s.mu.Unlock()
   120  
   121  	oldOp, exists := s.operations[op.ID]
   122  	if !exists {
   123  		return nil, dberr.NotFound("instance operation with id %s not found", op.ID)
   124  	}
   125  	if oldOp.Version != op.Version {
   126  		return nil, dberr.Conflict("unable to update provisioning operation with id %s (for instance id %s) - conflict", op.ID, op.InstanceID)
   127  	}
   128  	op.Version = op.Version + 1
   129  	s.operations[op.ID] = op.Operation
   130  
   131  	return &op, nil
   132  }
   133  
   134  func (s *operations) UpdateOperation(op internal.Operation) (*internal.Operation, error) {
   135  	s.mu.Lock()
   136  	defer s.mu.Unlock()
   137  
   138  	oldOp, exists := s.operations[op.ID]
   139  	if !exists {
   140  		return nil, dberr.NotFound("instance operation with id %s not found", op.ID)
   141  	}
   142  	if oldOp.Version != op.Version {
   143  		return nil, dberr.Conflict("unable to update operation with id %s (for instance id %s) - conflict", op.ID, op.InstanceID)
   144  	}
   145  	op.Version = op.Version + 1
   146  	s.operations[op.ID] = op
   147  
   148  	return &op, nil
   149  }
   150  
   151  func (s *operations) ListProvisioningOperationsByInstanceID(instanceID string) ([]internal.ProvisioningOperation, error) {
   152  	s.mu.Lock()
   153  	defer s.mu.Unlock()
   154  
   155  	operations := make([]internal.ProvisioningOperation, 0)
   156  	for _, op := range s.operations {
   157  		if op.InstanceID == instanceID && op.Type == internal.OperationTypeProvision {
   158  			operations = append(operations, internal.ProvisioningOperation{Operation: op})
   159  		}
   160  	}
   161  
   162  	if len(operations) != 0 {
   163  		s.sortProvisioningByCreatedAtDesc(operations)
   164  		return operations, nil
   165  	}
   166  
   167  	return nil, dberr.NotFound("instance provisioning operations with instanceID %s not found", instanceID)
   168  }
   169  
   170  func (s *operations) ListOperationsByInstanceID(instanceID string) ([]internal.Operation, error) {
   171  	s.mu.Lock()
   172  	defer s.mu.Unlock()
   173  
   174  	operations := make([]internal.Operation, 0)
   175  	for _, op := range s.operations {
   176  		if op.InstanceID == instanceID {
   177  			operations = append(operations, op)
   178  		}
   179  	}
   180  
   181  	if len(operations) != 0 {
   182  		s.sortOperationsByCreatedAtDesc(operations)
   183  		return operations, nil
   184  	}
   185  
   186  	return nil, dberr.NotFound("instance provisioning operations with instanceID %s not found", instanceID)
   187  }
   188  
   189  func (s *operations) ListOperationsInTimeRange(from, to time.Time) ([]internal.Operation, error) {
   190  	panic("not implemented") //also not used in any tests
   191  	return nil, nil
   192  }
   193  
   194  func (s *operations) InsertDeprovisioningOperation(operation internal.DeprovisioningOperation) error {
   195  	s.mu.Lock()
   196  	defer s.mu.Unlock()
   197  
   198  	id := operation.ID
   199  	if _, exists := s.operations[id]; exists {
   200  		return dberr.AlreadyExists("instance operation with id %s already exist", id)
   201  	}
   202  
   203  	s.operations[id] = operation.Operation
   204  	return nil
   205  }
   206  
   207  func (s *operations) GetDeprovisioningOperationByID(operationID string) (*internal.DeprovisioningOperation, error) {
   208  	s.mu.Lock()
   209  	defer s.mu.Unlock()
   210  
   211  	op, exists := s.operations[operationID]
   212  	if !exists {
   213  		return nil, dberr.NotFound("instance deprovisioning operation with id %s not found", operationID)
   214  	}
   215  	return &internal.DeprovisioningOperation{Operation: op}, nil
   216  }
   217  
   218  func (s *operations) GetDeprovisioningOperationByInstanceID(instanceID string) (*internal.DeprovisioningOperation, error) {
   219  	s.mu.Lock()
   220  	defer s.mu.Unlock()
   221  
   222  	var result []internal.DeprovisioningOperation
   223  
   224  	for _, op := range s.operations {
   225  		if op.InstanceID == instanceID && op.Type == internal.OperationTypeDeprovision {
   226  			result = append(result, internal.DeprovisioningOperation{Operation: op})
   227  		}
   228  	}
   229  	if len(result) != 0 {
   230  		s.sortDeprovisioningByCreatedAtDesc(result)
   231  		return &result[0], nil
   232  	}
   233  
   234  	return nil, dberr.NotFound("instance deprovisioning operation with instanceID %s not found", instanceID)
   235  }
   236  
   237  func (s *operations) UpdateDeprovisioningOperation(op internal.DeprovisioningOperation) (*internal.DeprovisioningOperation, error) {
   238  	s.mu.Lock()
   239  	defer s.mu.Unlock()
   240  
   241  	oldOp, exists := s.operations[op.ID]
   242  	if !exists {
   243  		return nil, dberr.NotFound("instance operation with id %s not found", op.ID)
   244  	}
   245  	if oldOp.Version != op.Version {
   246  		return nil, dberr.Conflict("unable to update deprovisioning operation with id %s (for instance id %s) - conflict", op.ID, op.InstanceID)
   247  	}
   248  	op.Version = op.Version + 1
   249  	s.operations[op.ID] = op.Operation
   250  
   251  	return &op, nil
   252  }
   253  
   254  func (s *operations) ListDeprovisioningOperationsByInstanceID(instanceID string) ([]internal.DeprovisioningOperation, error) {
   255  	s.mu.Lock()
   256  	defer s.mu.Unlock()
   257  
   258  	operations := make([]internal.DeprovisioningOperation, 0)
   259  	for _, op := range s.operations {
   260  		if op.InstanceID == instanceID && op.Type == internal.OperationTypeDeprovision {
   261  			operations = append(operations, internal.DeprovisioningOperation{Operation: op})
   262  		}
   263  	}
   264  
   265  	if len(operations) != 0 {
   266  		s.sortDeprovisioningByCreatedAtDesc(operations)
   267  		return operations, nil
   268  	}
   269  
   270  	return nil, dberr.NotFound("instance deprovisioning operations with instanceID %s not found", instanceID)
   271  }
   272  
   273  func (s *operations) ListDeprovisioningOperations() ([]internal.DeprovisioningOperation, error) {
   274  	s.mu.Lock()
   275  	defer s.mu.Unlock()
   276  
   277  	operations := make([]internal.DeprovisioningOperation, 0)
   278  	for _, op := range s.operations {
   279  		if op.Type == internal.OperationTypeDeprovision {
   280  			operations = append(operations, internal.DeprovisioningOperation{Operation: op})
   281  		}
   282  	}
   283  
   284  	s.sortDeprovisioningByCreatedAtDesc(operations)
   285  	return operations, nil
   286  }
   287  
   288  func (s *operations) InsertUpgradeKymaOperation(operation internal.UpgradeKymaOperation) error {
   289  	s.mu.Lock()
   290  	defer s.mu.Unlock()
   291  
   292  	id := operation.Operation.ID
   293  	if _, exists := s.operations[id]; exists {
   294  		return dberr.AlreadyExists("instance operation with id %s already exist", id)
   295  	}
   296  
   297  	s.operations[id] = operation.Operation
   298  	return nil
   299  }
   300  
   301  func (s *operations) GetUpgradeKymaOperationByID(operationID string) (*internal.UpgradeKymaOperation, error) {
   302  	s.mu.Lock()
   303  	defer s.mu.Unlock()
   304  
   305  	op, exists := s.operations[operationID]
   306  	if !exists {
   307  		return nil, dberr.NotFound("instance upgradeKyma operation with id %s not found", operationID)
   308  	}
   309  	return &internal.UpgradeKymaOperation{Operation: op}, nil
   310  }
   311  
   312  func (s *operations) GetUpgradeKymaOperationByInstanceID(instanceID string) (*internal.UpgradeKymaOperation, error) {
   313  	s.mu.Lock()
   314  	defer s.mu.Unlock()
   315  
   316  	for _, op := range s.operations {
   317  		if op.InstanceID == instanceID && op.Type == internal.OperationTypeUpgradeKyma {
   318  			return &internal.UpgradeKymaOperation{Operation: op}, nil
   319  		}
   320  	}
   321  
   322  	return nil, dberr.NotFound("instance upgradeKyma operation with instanceID %s not found", instanceID)
   323  }
   324  
   325  func (s *operations) UpdateUpgradeKymaOperation(op internal.UpgradeKymaOperation) (*internal.UpgradeKymaOperation, error) {
   326  	s.mu.Lock()
   327  	defer s.mu.Unlock()
   328  
   329  	oldOp, exists := s.operations[op.Operation.ID]
   330  	if !exists {
   331  		return nil, dberr.NotFound("instance operation with id %s not found", op.Operation.ID)
   332  	}
   333  	if oldOp.Version != op.Version {
   334  		return nil, dberr.Conflict("unable to update upgradeKyma operation with id %s (for instance id %s) - conflict", op.Operation.ID, op.InstanceID)
   335  	}
   336  	op.Version = op.Version + 1
   337  	s.operations[op.Operation.ID] = op.Operation
   338  
   339  	return &op, nil
   340  }
   341  
   342  func (s *operations) InsertUpgradeClusterOperation(operation internal.UpgradeClusterOperation) error {
   343  	s.mu.Lock()
   344  	defer s.mu.Unlock()
   345  
   346  	id := operation.Operation.ID
   347  	if _, exists := s.upgradeClusterOperations[id]; exists {
   348  		return dberr.AlreadyExists("instance operation with id %s already exist", id)
   349  	}
   350  
   351  	s.upgradeClusterOperations[id] = operation
   352  	return nil
   353  }
   354  
   355  func (s *operations) GetUpgradeClusterOperationByID(operationID string) (*internal.UpgradeClusterOperation, error) {
   356  	s.mu.Lock()
   357  	defer s.mu.Unlock()
   358  
   359  	op, exists := s.upgradeClusterOperations[operationID]
   360  	if !exists {
   361  		return nil, dberr.NotFound("instance upgradeCluster operation with id %s not found", operationID)
   362  	}
   363  	return &op, nil
   364  }
   365  
   366  func (s *operations) UpdateUpgradeClusterOperation(op internal.UpgradeClusterOperation) (*internal.UpgradeClusterOperation, error) {
   367  	s.mu.Lock()
   368  	defer s.mu.Unlock()
   369  
   370  	oldOp, exists := s.upgradeClusterOperations[op.Operation.ID]
   371  	if !exists {
   372  		return nil, dberr.NotFound("instance operation with id %s not found", op.Operation.ID)
   373  	}
   374  	if oldOp.Version != op.Version {
   375  		return nil, dberr.Conflict("unable to update upgradeKyma operation with id %s (for instance id %s) - conflict", op.Operation.ID, op.InstanceID)
   376  	}
   377  	op.Version = op.Version + 1
   378  	s.upgradeClusterOperations[op.Operation.ID] = op
   379  
   380  	return &op, nil
   381  }
   382  
   383  func (s *operations) GetLastOperation(instanceID string) (*internal.Operation, error) {
   384  	s.mu.Lock()
   385  	defer s.mu.Unlock()
   386  
   387  	var rows []internal.Operation
   388  
   389  	for _, op := range s.operations {
   390  		if op.InstanceID == instanceID && op.State != orchestration.Pending {
   391  			rows = append(rows, op)
   392  		}
   393  	}
   394  	for _, op := range s.upgradeClusterOperations {
   395  		if op.InstanceID == instanceID && op.State != orchestration.Pending {
   396  			rows = append(rows, op.Operation)
   397  		}
   398  	}
   399  	for _, op := range s.updateOperations {
   400  		if op.InstanceID == instanceID && op.State != orchestration.Pending {
   401  			rows = append(rows, op.Operation)
   402  		}
   403  	}
   404  
   405  	if len(rows) == 0 {
   406  		return nil, dberr.NotFound("instance operation with instance_id %s not found", instanceID)
   407  	}
   408  
   409  	sort.Slice(rows, func(i, j int) bool {
   410  		return rows[i].CreatedAt.After(rows[j].CreatedAt)
   411  	})
   412  
   413  	return &rows[0], nil
   414  }
   415  
   416  func (s *operations) GetOperationByID(operationID string) (*internal.Operation, error) {
   417  	s.mu.Lock()
   418  	defer s.mu.Unlock()
   419  
   420  	var res *internal.Operation
   421  
   422  	provisionOp, exists := s.operations[operationID]
   423  	if exists {
   424  		res = &provisionOp
   425  	}
   426  	upgradeClusterOp, exists := s.upgradeClusterOperations[operationID]
   427  	if exists {
   428  		res = &upgradeClusterOp.Operation
   429  	}
   430  	updateOp, exists := s.updateOperations[operationID]
   431  	if exists {
   432  		res = &updateOp.Operation
   433  	}
   434  	op, exists := s.operations[operationID]
   435  	if exists {
   436  		res = &op
   437  	}
   438  
   439  	if res == nil {
   440  		return nil, dberr.NotFound("instance operation with id %s not found", operationID)
   441  	}
   442  
   443  	return res, nil
   444  }
   445  
   446  func (s *operations) GetNotFinishedOperationsByType(opType internal.OperationType) ([]internal.Operation, error) {
   447  	s.mu.Lock()
   448  	defer s.mu.Unlock()
   449  
   450  	ops := make([]internal.Operation, 0)
   451  	switch opType {
   452  	case internal.OperationTypeProvision:
   453  		for _, op := range s.operations {
   454  			if op.State == domain.InProgress {
   455  				ops = append(ops, op)
   456  			}
   457  		}
   458  	case internal.OperationTypeDeprovision:
   459  		for _, op := range s.operations {
   460  			if op.State == domain.InProgress {
   461  				ops = append(ops, op)
   462  			}
   463  		}
   464  	}
   465  
   466  	return ops, nil
   467  }
   468  
   469  func (s *operations) GetOperationsForIDs(opIdList []string) ([]internal.Operation, error) {
   470  	s.mu.Lock()
   471  	defer s.mu.Unlock()
   472  
   473  	ops := make([]internal.Operation, 0)
   474  	for _, opID := range opIdList {
   475  		for _, op := range s.updateOperations {
   476  			if op.Operation.ID == opID {
   477  				ops = append(ops, op.Operation)
   478  			}
   479  		}
   480  	}
   481  	for _, opID := range opIdList {
   482  		for _, op := range s.upgradeClusterOperations {
   483  			if op.Operation.ID == opID {
   484  				ops = append(ops, op.Operation)
   485  			}
   486  		}
   487  	}
   488  
   489  	for _, opID := range opIdList {
   490  		for _, op := range s.operations {
   491  			if op.ID == opID {
   492  				ops = append(ops, op)
   493  			}
   494  		}
   495  	}
   496  
   497  	if len(ops) == 0 {
   498  		return nil, dberr.NotFound("operations with ids from list %+q not exist", opIdList)
   499  	}
   500  
   501  	return ops, nil
   502  }
   503  
   504  func (s *operations) GetOperationStatsByPlan() (map[string]internal.OperationStats, error) {
   505  	s.mu.Lock()
   506  	defer s.mu.Unlock()
   507  
   508  	result := make(map[string]internal.OperationStats)
   509  
   510  	for _, op := range s.operations {
   511  		if op.ProvisioningParameters.PlanID == "" {
   512  			continue
   513  		}
   514  		if _, ok := result[op.ProvisioningParameters.PlanID]; !ok {
   515  			result[op.ProvisioningParameters.PlanID] = internal.OperationStats{
   516  				Provisioning:   make(map[domain.LastOperationState]int),
   517  				Deprovisioning: make(map[domain.LastOperationState]int),
   518  			}
   519  		}
   520  		switch op.Type {
   521  		case internal.OperationTypeProvision:
   522  			result[op.ProvisioningParameters.PlanID].Provisioning[op.State] += 1
   523  		case internal.OperationTypeDeprovision:
   524  			result[op.ProvisioningParameters.PlanID].Deprovisioning[op.State] += 1
   525  		}
   526  	}
   527  	return result, nil
   528  }
   529  
   530  func (s *operations) GetOperationStatsForOrchestration(orchestrationID string) (map[string]int, error) {
   531  	s.mu.Lock()
   532  	defer s.mu.Unlock()
   533  
   534  	result := map[string]int{
   535  		orchestration.Canceled:   0,
   536  		orchestration.Canceling:  0,
   537  		orchestration.InProgress: 0,
   538  		orchestration.Pending:    0,
   539  		orchestration.Succeeded:  0,
   540  		orchestration.Failed:     0,
   541  	}
   542  	opStatePerInstanceID := make(map[string][]string)
   543  	for _, op := range s.operations {
   544  		if op.OrchestrationID == orchestrationID && op.Type == internal.OperationTypeUpgradeKyma {
   545  			if op.State != Failed {
   546  				result[string(op.State)] = result[string(op.State)] + 1
   547  			}
   548  			opStatePerInstanceID[op.InstanceID] = append(opStatePerInstanceID[op.InstanceID], string(op.State))
   549  		}
   550  	}
   551  
   552  	for _, op := range s.upgradeClusterOperations {
   553  		if op.OrchestrationID == orchestrationID {
   554  			if op.State != Failed {
   555  				result[string(op.State)] = result[string(op.State)] + 1
   556  			}
   557  			opStatePerInstanceID[string(op.Operation.InstanceID)] = append(opStatePerInstanceID[string(op.Operation.InstanceID)], string(op.State))
   558  		}
   559  	}
   560  
   561  	_, failedum := s.calFailedStatusForOrchestration(opStatePerInstanceID)
   562  	result[Failed] = failedum
   563  
   564  	return result, nil
   565  }
   566  
   567  func (s *operations) calFailedStatusForOrchestration(opStatePerInstanceID map[string][]string) ([]string, int) {
   568  	var result []string
   569  
   570  	var invalidFailed, failedFound bool
   571  
   572  	for instanceID, statuses := range opStatePerInstanceID {
   573  
   574  		invalidFailed = false
   575  		failedFound = false
   576  		for _, status := range statuses {
   577  			if status == Failed {
   578  				failedFound = true
   579  			}
   580  			//In Progress/Retrying/Succeeded means new operation for same instance_id is ongoing/succeeded.
   581  			if status == Succeeded || status == Retrying || status == InProgress {
   582  				invalidFailed = true
   583  			}
   584  		}
   585  		if failedFound && !invalidFailed {
   586  			result = append(result, instanceID)
   587  		}
   588  	}
   589  
   590  	return result, len(result)
   591  }
   592  
   593  func (s *operations) ListOperations(filter dbmodel.OperationFilter) ([]internal.Operation, int, int, error) {
   594  	s.mu.Lock()
   595  	defer s.mu.Unlock()
   596  
   597  	result := make([]internal.Operation, 0)
   598  	offset := pagination.ConvertPageAndPageSizeToOffset(filter.PageSize, filter.Page)
   599  
   600  	operations, err := s.filterAll(filter)
   601  	if err != nil {
   602  		return nil, 0, 0, fmt.Errorf("while listing operations: %w", err)
   603  	}
   604  	s.sortByCreatedAt(operations)
   605  
   606  	for i := offset; (filter.PageSize < 1 || i < offset+filter.PageSize) && i < len(operations)+offset; i++ {
   607  		result = append(result, operations[i])
   608  	}
   609  
   610  	return result,
   611  		len(result),
   612  		len(operations),
   613  		nil
   614  }
   615  
   616  func (s *operations) ListUpgradeKymaOperations() ([]internal.UpgradeKymaOperation, error) {
   617  	s.mu.Lock()
   618  	defer s.mu.Unlock()
   619  
   620  	// Empty filter means get all
   621  	operations := s.filterUpgradeKyma("", dbmodel.OperationFilter{})
   622  	s.sortUpgradeKymaByCreatedAt(operations)
   623  
   624  	return operations, nil
   625  }
   626  
   627  func (s *operations) ListUpgradeKymaOperationsByOrchestrationID(orchestrationID string, filter dbmodel.OperationFilter) ([]internal.UpgradeKymaOperation, int, int, error) {
   628  	s.mu.Lock()
   629  	defer s.mu.Unlock()
   630  
   631  	result := make([]internal.UpgradeKymaOperation, 0)
   632  	offset := pagination.ConvertPageAndPageSizeToOffset(filter.PageSize, filter.Page)
   633  
   634  	operations := s.filterUpgradeKyma(orchestrationID, filter)
   635  	s.sortUpgradeKymaByCreatedAt(operations)
   636  
   637  	for i := offset; (filter.PageSize < 1 || i < offset+filter.PageSize) && i < len(operations); i++ {
   638  		result = append(result, internal.UpgradeKymaOperation{Operation: s.operations[operations[i].ID]})
   639  	}
   640  
   641  	return result,
   642  		len(result),
   643  		len(operations),
   644  		nil
   645  }
   646  
   647  func (s *operations) ListOperationsByOrchestrationID(orchestrationID string, filter dbmodel.OperationFilter) ([]internal.Operation, int, int, error) {
   648  	s.mu.Lock()
   649  	defer s.mu.Unlock()
   650  
   651  	result := make([]internal.Operation, 0)
   652  	offset := pagination.ConvertPageAndPageSizeToOffset(filter.PageSize, filter.Page)
   653  
   654  	operations := s.filterOperations(orchestrationID, filter)
   655  	s.sortByCreatedAt(operations)
   656  
   657  	for i := offset; (filter.PageSize < 1 || i < offset+filter.PageSize) && i < len(operations); i++ {
   658  		result = append(result, s.operations[operations[i].ID])
   659  	}
   660  
   661  	return result,
   662  		len(result),
   663  		len(operations),
   664  		nil
   665  }
   666  
   667  func (s *operations) ListUpgradeKymaOperationsByInstanceID(instanceID string) ([]internal.UpgradeKymaOperation, error) {
   668  	s.mu.Lock()
   669  	defer s.mu.Unlock()
   670  
   671  	// Empty filter means get all
   672  	operations := s.filterUpgradeKymaByInstanceID(instanceID, dbmodel.OperationFilter{})
   673  
   674  	if len(operations) != 0 {
   675  		s.sortUpgradeKymaByCreatedAtDesc(operations)
   676  		return operations, nil
   677  	}
   678  
   679  	return nil, dberr.NotFound("instance upgrade operations with instanceID %s not found", instanceID)
   680  }
   681  
   682  func (s *operations) ListUpgradeClusterOperationsByOrchestrationID(orchestrationID string, filter dbmodel.OperationFilter) ([]internal.UpgradeClusterOperation, int, int, error) {
   683  	s.mu.Lock()
   684  	defer s.mu.Unlock()
   685  
   686  	result := make([]internal.UpgradeClusterOperation, 0)
   687  	offset := pagination.ConvertPageAndPageSizeToOffset(filter.PageSize, filter.Page)
   688  
   689  	operations := s.filterUpgradeCluster(orchestrationID, filter)
   690  	s.sortUpgradeClusterByCreatedAt(operations)
   691  
   692  	for i := offset; (filter.PageSize < 1 || i < offset+filter.PageSize) && i < len(operations); i++ {
   693  		result = append(result, s.upgradeClusterOperations[operations[i].Operation.ID])
   694  	}
   695  
   696  	return result,
   697  		len(result),
   698  		len(operations),
   699  		nil
   700  }
   701  
   702  func (s *operations) ListUpgradeClusterOperationsByInstanceID(instanceID string) ([]internal.UpgradeClusterOperation, error) {
   703  	s.mu.Lock()
   704  	defer s.mu.Unlock()
   705  
   706  	// Empty filter means get all
   707  	operations := s.filterUpgradeClusterByInstanceID(instanceID, dbmodel.OperationFilter{})
   708  
   709  	if len(operations) != 0 {
   710  		s.sortUpgradeClusterByCreatedAtDesc(operations)
   711  		return operations, nil
   712  	}
   713  
   714  	return nil, dberr.NotFound("instance upgrade operations with instanceID %s not found", instanceID)
   715  }
   716  
   717  func (s *operations) InsertUpdatingOperation(operation internal.UpdatingOperation) error {
   718  	s.mu.Lock()
   719  	defer s.mu.Unlock()
   720  
   721  	id := operation.ID
   722  	if _, exists := s.updateOperations[id]; exists {
   723  		return dberr.AlreadyExists("instance operation with id %s already exist", id)
   724  	}
   725  
   726  	s.updateOperations[id] = operation
   727  	return nil
   728  }
   729  
   730  func (s *operations) GetUpdatingOperationByID(operationID string) (*internal.UpdatingOperation, error) {
   731  	s.mu.Lock()
   732  	defer s.mu.Unlock()
   733  
   734  	for _, op := range s.updateOperations {
   735  		if op.ID == operationID {
   736  			return &op, nil
   737  		}
   738  	}
   739  
   740  	return nil, dberr.NotFound("instance update operation with ID %s not found", operationID)
   741  }
   742  
   743  func (s *operations) UpdateUpdatingOperation(op internal.UpdatingOperation) (*internal.UpdatingOperation, error) {
   744  	s.mu.Lock()
   745  	defer s.mu.Unlock()
   746  
   747  	oldOp, exists := s.updateOperations[op.ID]
   748  	if !exists {
   749  		return nil, dberr.NotFound("instance operation with id %s not found", op.ID)
   750  	}
   751  	if oldOp.Version != op.Version {
   752  		return nil, dberr.Conflict("unable to update updating operation with id %s (for instance id %s) - conflict", op.ID, op.InstanceID)
   753  	}
   754  	op.Version = op.Version + 1
   755  	s.updateOperations[op.ID] = op
   756  
   757  	return &op, nil
   758  }
   759  
   760  func (s *operations) ListUpdatingOperationsByInstanceID(instanceID string) ([]internal.UpdatingOperation, error) {
   761  	s.mu.Lock()
   762  	defer s.mu.Unlock()
   763  
   764  	operations := make([]internal.UpdatingOperation, 0)
   765  	for _, v := range s.updateOperations {
   766  		if instanceID != v.InstanceID {
   767  			continue
   768  		}
   769  
   770  		operations = append(operations, v)
   771  	}
   772  
   773  	sort.Slice(operations, func(i, j int) bool {
   774  		return operations[i].CreatedAt.Before(operations[j].CreatedAt)
   775  	})
   776  
   777  	return operations, nil
   778  }
   779  
   780  func (s *operations) sortUpgradeKymaByCreatedAt(operations []internal.UpgradeKymaOperation) {
   781  	sort.Slice(operations, func(i, j int) bool {
   782  		return operations[i].CreatedAt.Before(operations[j].CreatedAt)
   783  	})
   784  }
   785  
   786  func (s *operations) sortUpgradeKymaByCreatedAtDesc(operations []internal.UpgradeKymaOperation) {
   787  	sort.Slice(operations, func(i, j int) bool {
   788  		return operations[i].CreatedAt.After(operations[j].CreatedAt)
   789  	})
   790  }
   791  
   792  func (s *operations) sortUpgradeClusterByCreatedAt(operations []internal.UpgradeClusterOperation) {
   793  	sort.Slice(operations, func(i, j int) bool {
   794  		return operations[i].CreatedAt.Before(operations[j].CreatedAt)
   795  	})
   796  }
   797  
   798  func (s *operations) sortUpgradeClusterByCreatedAtDesc(operations []internal.UpgradeClusterOperation) {
   799  	sort.Slice(operations, func(i, j int) bool {
   800  		return operations[i].CreatedAt.After(operations[j].CreatedAt)
   801  	})
   802  }
   803  
   804  func (s *operations) sortProvisioningByCreatedAtDesc(operations []internal.ProvisioningOperation) {
   805  	sort.Slice(operations, func(i, j int) bool {
   806  		return operations[i].CreatedAt.After(operations[j].CreatedAt)
   807  	})
   808  }
   809  
   810  func (s *operations) sortOperationsByCreatedAtDesc(operations []internal.Operation) {
   811  	sort.Slice(operations, func(i, j int) bool {
   812  		return operations[i].CreatedAt.After(operations[j].CreatedAt)
   813  	})
   814  }
   815  
   816  func (s *operations) sortDeprovisioningByCreatedAtDesc(operations []internal.DeprovisioningOperation) {
   817  	sort.Slice(operations, func(i, j int) bool {
   818  		return operations[i].CreatedAt.After(operations[j].CreatedAt)
   819  	})
   820  }
   821  
   822  func (s *operations) sortByCreatedAt(operations []internal.Operation) {
   823  	sort.Slice(operations, func(i, j int) bool {
   824  		return operations[i].CreatedAt.Before(operations[j].CreatedAt)
   825  	})
   826  }
   827  
   828  func (s *operations) getAll() ([]internal.Operation, error) {
   829  	ops := make([]internal.Operation, 0)
   830  	for _, op := range s.upgradeClusterOperations {
   831  		ops = append(ops, op.Operation)
   832  	}
   833  	for _, op := range s.operations {
   834  		ops = append(ops, op)
   835  	}
   836  	if len(ops) == 0 {
   837  		return nil, dberr.NotFound("operations not found")
   838  	}
   839  
   840  	return ops, nil
   841  }
   842  
   843  func (s *operations) filterAll(filter dbmodel.OperationFilter) ([]internal.Operation, error) {
   844  	result := make([]internal.Operation, 0)
   845  	ops, err := s.getAll()
   846  	if err != nil {
   847  		return nil, err
   848  	}
   849  	for _, op := range ops {
   850  		if ok := matchFilter(string(op.State), filter.States, s.equalFilter); !ok {
   851  			continue
   852  		}
   853  		result = append(result, op)
   854  	}
   855  	return result, nil
   856  }
   857  
   858  func (s *operations) filterUpgradeKyma(orchestrationID string, filter dbmodel.OperationFilter) []internal.UpgradeKymaOperation {
   859  	operations := make([]internal.UpgradeKymaOperation, 0, len(s.operations))
   860  	for _, v := range s.operations {
   861  		if orchestrationID != "" && orchestrationID != v.OrchestrationID && v.Type != internal.OperationTypeUpgradeKyma {
   862  			continue
   863  		}
   864  		if ok := matchFilter(string(v.State), filter.States, s.equalFilter); !ok {
   865  			continue
   866  		}
   867  
   868  		operations = append(operations, internal.UpgradeKymaOperation{Operation: v})
   869  	}
   870  
   871  	return operations
   872  }
   873  
   874  func (s *operations) filterOperations(orchestrationID string, filter dbmodel.OperationFilter) []internal.Operation {
   875  	operations := make([]internal.Operation, 0, len(s.operations))
   876  	for _, v := range s.operations {
   877  		if orchestrationID != "" && orchestrationID != v.OrchestrationID {
   878  			continue
   879  		}
   880  		if ok := matchFilter(string(v.State), filter.States, s.equalFilter); !ok {
   881  			continue
   882  		}
   883  
   884  		operations = append(operations, v)
   885  	}
   886  
   887  	return operations
   888  }
   889  
   890  func (s *operations) filterUpgradeKymaByInstanceID(instanceID string, filter dbmodel.OperationFilter) []internal.UpgradeKymaOperation {
   891  	operations := make([]internal.UpgradeKymaOperation, 0)
   892  	for _, v := range s.operations {
   893  		if instanceID != "" && instanceID != v.InstanceID {
   894  			continue
   895  		}
   896  		if v.Type != internal.OperationTypeUpgradeKyma {
   897  			continue
   898  		}
   899  		if ok := matchFilter(string(v.State), filter.States, s.equalFilter); !ok {
   900  			continue
   901  		}
   902  
   903  		operations = append(operations, internal.UpgradeKymaOperation{Operation: v})
   904  	}
   905  
   906  	return operations
   907  }
   908  
   909  func (s *operations) filterUpgradeCluster(orchestrationID string, filter dbmodel.OperationFilter) []internal.UpgradeClusterOperation {
   910  	operations := make([]internal.UpgradeClusterOperation, 0, len(s.upgradeClusterOperations))
   911  	for _, v := range s.upgradeClusterOperations {
   912  		if orchestrationID != "" && orchestrationID != v.OrchestrationID {
   913  			continue
   914  		}
   915  		if ok := matchFilter(string(v.State), filter.States, s.equalFilter); !ok {
   916  			continue
   917  		}
   918  
   919  		operations = append(operations, v)
   920  	}
   921  
   922  	return operations
   923  }
   924  
   925  func (s *operations) filterUpgradeClusterByInstanceID(instanceID string, filter dbmodel.OperationFilter) []internal.UpgradeClusterOperation {
   926  	operations := make([]internal.UpgradeClusterOperation, 0)
   927  	for _, v := range s.upgradeClusterOperations {
   928  		if instanceID != "" && instanceID != v.InstanceID {
   929  			continue
   930  		}
   931  		if ok := matchFilter(string(v.State), filter.States, s.equalFilter); !ok {
   932  			continue
   933  		}
   934  
   935  		operations = append(operations, v)
   936  	}
   937  
   938  	return operations
   939  }
   940  
   941  func (s *operations) equalFilter(a, b string) bool {
   942  	return a == b
   943  }