github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/process/provisioning/override_kyma_modules.go (about) 1 package provisioning 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/kyma-project/kyma-environment-broker/internal" 8 "github.com/kyma-project/kyma-environment-broker/internal/process" 9 "github.com/kyma-project/kyma-environment-broker/internal/process/steps" 10 "github.com/kyma-project/kyma-environment-broker/internal/storage" 11 "github.com/sirupsen/logrus" 12 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 13 ) 14 15 type OverrideKymaModules struct { 16 operationManager *process.OperationManager 17 logger logrus.FieldLogger 18 } 19 20 var _ process.Step = &OverrideKymaModules{} 21 22 func (k *OverrideKymaModules) Name() string { 23 return "Override_Kyma_Modules" 24 } 25 26 func NewOverrideKymaModules(os storage.Operations) *OverrideKymaModules { 27 return &OverrideKymaModules{operationManager: process.NewOperationManager(os)} 28 } 29 30 // Cases: 31 // 1 case -> if 'default' is false, then we don't install anything, no modules 32 // 2 case -> if 'list' is given and not empty, we override passed modules 33 // 3 case -> if 'list' is given and is empty, then we don't install anything, no modules 34 // default behaviour is when default = true, then default modules will be installed, also it applies to all other scenarios than mentioned in 1,2,3 point. 35 36 func (k *OverrideKymaModules) Run(operation internal.Operation, logger logrus.FieldLogger) (internal.Operation, time.Duration, error) { 37 k.logger = logger 38 if operation.Type != internal.OperationTypeProvision { 39 k.logger.Infof("%s is supposed to run only for Provisioning, skipping logic.", k.Name()) 40 return operation, 0, nil 41 } 42 43 modulesParams := operation.ProvisioningParameters.Parameters.Modules 44 if modulesParams != nil { 45 defaultModulesSetToFalse := modulesParams.Default != nil && !*modulesParams.Default // 1 case 46 customModulesListPassed := modulesParams.Default == nil && modulesParams.List != nil // 2 & 3 case 47 overrideModules := defaultModulesSetToFalse || customModulesListPassed 48 if overrideModules { 49 k.logger.Info("custom modules parameters are set, the content of list will replace current modules section. Default settings will be overriden.") 50 return k.handleModulesOverride(operation, *modulesParams) 51 } 52 } 53 54 // default behaviour 55 k.logger.Infof("Kyma will be created with default modules. %s didn't perform any action. %s", k.Name()) 56 return operation, 0, nil 57 } 58 59 func (k *OverrideKymaModules) handleModulesOverride(operation internal.Operation, modulesParams internal.ModulesDTO) (internal.Operation, time.Duration, error) { 60 decodeKymaTemplate, err := steps.DecodeKymaTemplate(operation.KymaTemplate) 61 if err != nil { 62 k.logger.Errorf("while decoding Kyma template from previous step: %s", err.Error()) 63 return k.operationManager.OperationFailed(operation, "while decoding Kyma template from previous step", err, k.logger) 64 } 65 if decodeKymaTemplate == nil { 66 k.logger.Errorf("while decoding Kyma template from previous step: object is nil") 67 return k.operationManager.OperationFailed(operation, "while decoding Kyma template from previous step: ", fmt.Errorf("object is nil"), k.logger) 68 } 69 70 if err := k.replaceModulesSpec(decodeKymaTemplate, modulesParams); err != nil { 71 k.logger.Errorf("unable to append modules to Kyma template: %s", err.Error()) 72 return k.operationManager.OperationFailed(operation, "unable to append modules to Kyma template:", err, k.logger) 73 } 74 updatedKymaTemplate, err := steps.EncodeKymaTemplate(decodeKymaTemplate) 75 if err != nil { 76 k.logger.Errorf("unable to create yaml Kyma template with custom custom modules: %s", err.Error()) 77 return k.operationManager.OperationFailed(operation, "unable to create yaml Kyma template within added modules", err, k.logger) 78 } 79 80 k.logger.Info("encoded Kyma template with custom modules with success") 81 return k.operationManager.UpdateOperation(operation, func(op *internal.Operation) { 82 op.KymaResourceNamespace = decodeKymaTemplate.GetNamespace() 83 op.KymaTemplate = updatedKymaTemplate 84 }, k.logger) 85 } 86 87 // To consider using -> unstructured.SetNestedSlice() 88 func (k *OverrideKymaModules) replaceModulesSpec(kymaTemplate *unstructured.Unstructured, modulesParams internal.ModulesDTO) error { 89 const ( 90 specKey = "spec" 91 modulesKey = "modules" 92 ) 93 94 content := kymaTemplate.Object 95 specSection, ok := content[specKey] 96 if !ok { 97 return fmt.Errorf("getting spec content of kyma template") 98 } 99 spec, ok := specSection.(map[string]interface{}) 100 if !ok { 101 return fmt.Errorf("converting spec of kyma template") 102 } 103 modulesSection, ok := spec[modulesKey] 104 if !ok { 105 return fmt.Errorf("getting modules content of kyma template") 106 } 107 108 if modulesParams.List == nil || len(modulesParams.List) == 0 { 109 if modulesParams.List == nil { 110 modulesParams.List = make([]*internal.ModuleDTO, 0) 111 } 112 k.logger.Info("empty list with custom modules passed to KEB, 0 modules will be installed - default config will be ignored") 113 } else { 114 k.logger.Info("not empty list with custom modules passed to KEB. Number of modules: %d", len(modulesParams.List)) 115 } 116 117 modulesSection = modulesParams.List 118 spec[modulesKey] = modulesSection 119 kymaTemplate.Object[specKey] = specSection 120 121 k.logger.Info("custom modules replaced in Kyma template successfully.") 122 return nil 123 }