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  }