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 }