github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/process/input/input.go (about)

     1  package input
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"regexp"
     7  	"strings"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/kyma-project/kyma-environment-broker/internal/networking"
    12  
    13  	"github.com/kyma-project/kyma-environment-broker/internal/ptr"
    14  
    15  	reconcilerApi "github.com/kyma-incubator/reconciler/pkg/keb"
    16  	"github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema"
    17  	"github.com/kyma-project/kyma-environment-broker/common/gardener"
    18  	"github.com/kyma-project/kyma-environment-broker/internal"
    19  	"github.com/kyma-project/kyma-environment-broker/internal/broker"
    20  	"github.com/kyma-project/kyma-environment-broker/internal/runtime"
    21  )
    22  
    23  const (
    24  	trialSuffixLength    = 5
    25  	maxRuntimeNameLength = 36
    26  )
    27  
    28  type Config struct {
    29  	URL                           string
    30  	ProvisioningTimeout           time.Duration          `envconfig:"default=6h"`
    31  	DeprovisioningTimeout         time.Duration          `envconfig:"default=5h"`
    32  	KubernetesVersion             string                 `envconfig:"default=1.16.9"`
    33  	DefaultGardenerShootPurpose   string                 `envconfig:"default=development"`
    34  	MachineImage                  string                 `envconfig:"optional"`
    35  	MachineImageVersion           string                 `envconfig:"optional"`
    36  	TrialNodesNumber              int                    `envconfig:"optional"`
    37  	DefaultTrialProvider          internal.CloudProvider `envconfig:"default=Azure"` // could be: Azure, AWS, GCP, Openstack, unknown
    38  	OpenstackFloatingPoolName     string                 `envconfig:"default=FloatingIP-external-cp-kyma"`
    39  	AutoUpdateKubernetesVersion   bool                   `envconfig:"default=false"`
    40  	AutoUpdateMachineImageVersion bool                   `envconfig:"default=false"`
    41  	MultiZoneCluster              bool                   `envconfig:"default=false"`
    42  	ControlPlaneFailureTolerance  string                 `envconfig:"optional"`
    43  }
    44  
    45  type RuntimeInput struct {
    46  	muOptionalComponents sync.Mutex
    47  	muLabels             sync.Mutex
    48  	muOverrides          sync.Mutex
    49  
    50  	provisionRuntimeInput gqlschema.ProvisionRuntimeInput
    51  	upgradeRuntimeInput   gqlschema.UpgradeRuntimeInput
    52  	upgradeShootInput     gqlschema.UpgradeShootInput
    53  	overrides             map[string][]*gqlschema.ConfigEntryInput
    54  	labels                map[string]string
    55  	globalOverrides       []*gqlschema.ConfigEntryInput
    56  
    57  	config                    *internal.ConfigForPlan
    58  	hyperscalerInputProvider  HyperscalerInputProvider
    59  	optionalComponentsService OptionalComponentService
    60  	provisioningParameters    internal.ProvisioningParameters
    61  	shootName                 *string
    62  
    63  	componentsDisabler        ComponentsDisabler
    64  	enabledOptionalComponents map[string]struct{}
    65  	oidcDefaultValues         internal.OIDCConfigDTO
    66  	oidcLastValues            gqlschema.OIDCConfigInput
    67  
    68  	trialNodesNumber  int
    69  	instanceID        string
    70  	runtimeID         string
    71  	kubeconfig        string
    72  	shootDomain       string
    73  	shootDnsProviders gardener.DNSProvidersData
    74  	clusterName       string
    75  	modules           internal.ModulesDTO
    76  }
    77  
    78  func (r *RuntimeInput) Configuration() *internal.ConfigForPlan {
    79  	return r.config
    80  }
    81  
    82  func (r *RuntimeInput) EnableOptionalComponent(componentName string) internal.ProvisionerInputCreator {
    83  	r.muOptionalComponents.Lock()
    84  	defer r.muOptionalComponents.Unlock()
    85  	r.enabledOptionalComponents[componentName] = struct{}{}
    86  	return r
    87  }
    88  
    89  func (r *RuntimeInput) DisableOptionalComponent(componentName string) internal.ProvisionerInputCreator {
    90  	r.muOptionalComponents.Lock()
    91  	defer r.muOptionalComponents.Unlock()
    92  
    93  	r.optionalComponentsService.AddComponentToDisable(componentName, runtime.NewGenericComponentDisabler(componentName))
    94  	delete(r.enabledOptionalComponents, componentName)
    95  	return r
    96  }
    97  
    98  func (r *RuntimeInput) SetProvisioningParameters(params internal.ProvisioningParameters) internal.ProvisionerInputCreator {
    99  	r.provisioningParameters = params
   100  	return r
   101  }
   102  
   103  func (r *RuntimeInput) SetShootName(name string) internal.ProvisionerInputCreator {
   104  	r.shootName = &name
   105  	return r
   106  }
   107  
   108  func (r *RuntimeInput) SetShootDomain(name string) internal.ProvisionerInputCreator {
   109  	r.shootDomain = name
   110  	return r
   111  }
   112  
   113  func (r *RuntimeInput) SetShootDNSProviders(dnsProviders gardener.DNSProvidersData) internal.ProvisionerInputCreator {
   114  	r.shootDnsProviders = dnsProviders
   115  	return r
   116  }
   117  
   118  func (r *RuntimeInput) SetInstanceID(instanceID string) internal.ProvisionerInputCreator {
   119  	r.instanceID = instanceID
   120  	return r
   121  }
   122  
   123  func (r *RuntimeInput) SetRuntimeID(runtimeID string) internal.ProvisionerInputCreator {
   124  	r.runtimeID = runtimeID
   125  	return r
   126  }
   127  
   128  func (r *RuntimeInput) SetKubeconfig(kubeconfig string) internal.ProvisionerInputCreator {
   129  	r.kubeconfig = kubeconfig
   130  	return r
   131  }
   132  
   133  func (r *RuntimeInput) SetClusterName(name string) internal.ProvisionerInputCreator {
   134  	if name != "" {
   135  		r.clusterName = name
   136  	}
   137  	return r
   138  }
   139  
   140  func (r *RuntimeInput) SetOIDCLastValues(oidcConfig gqlschema.OIDCConfigInput) internal.ProvisionerInputCreator {
   141  	r.oidcLastValues = oidcConfig
   142  	return r
   143  }
   144  
   145  // SetOverrides sets the overrides for the given component and discard the previous ones.
   146  //
   147  // Deprecated: use AppendOverrides
   148  func (r *RuntimeInput) SetOverrides(component string, overrides []*gqlschema.ConfigEntryInput) internal.ProvisionerInputCreator {
   149  	// currently same as in AppendOverrides function, as we working on the same underlying object.
   150  	r.muOverrides.Lock()
   151  	defer r.muOverrides.Unlock()
   152  
   153  	r.overrides[component] = overrides
   154  	return r
   155  }
   156  
   157  // AppendOverrides appends overrides for the given components, the existing overrides are preserved.
   158  func (r *RuntimeInput) AppendOverrides(component string, overrides []*gqlschema.ConfigEntryInput) internal.ProvisionerInputCreator {
   159  	r.muOverrides.Lock()
   160  	defer r.muOverrides.Unlock()
   161  
   162  	for _, o2 := range overrides {
   163  		found := false
   164  		for i, o1 := range r.overrides[component] {
   165  			if o1.Key == o2.Key {
   166  				found = true
   167  				r.overrides[component][i].Secret = o2.Secret
   168  				r.overrides[component][i].Value = o2.Value
   169  			}
   170  		}
   171  		if !found {
   172  			r.overrides[component] = append(r.overrides[component], o2)
   173  		}
   174  	}
   175  	return r
   176  }
   177  
   178  // AppendGlobalOverrides appends overrides, the existing overrides are preserved.
   179  func (r *RuntimeInput) AppendGlobalOverrides(overrides []*gqlschema.ConfigEntryInput) internal.ProvisionerInputCreator {
   180  	r.muOverrides.Lock()
   181  	defer r.muOverrides.Unlock()
   182  
   183  	for _, o2 := range overrides {
   184  		found := false
   185  		for i, o1 := range r.globalOverrides {
   186  			if o1.Key == o2.Key {
   187  				found = true
   188  				r.globalOverrides[i].Secret = o2.Secret
   189  				r.globalOverrides[i].Value = o2.Value
   190  			}
   191  		}
   192  		if !found {
   193  			r.globalOverrides = append(r.globalOverrides, o2)
   194  		}
   195  	}
   196  	return r
   197  }
   198  
   199  func (r *RuntimeInput) SetLabel(key, value string) internal.ProvisionerInputCreator {
   200  	r.muLabels.Lock()
   201  	defer r.muLabels.Unlock()
   202  
   203  	if r.provisionRuntimeInput.RuntimeInput.Labels == nil {
   204  		r.provisionRuntimeInput.RuntimeInput.Labels = gqlschema.Labels{}
   205  	}
   206  
   207  	(r.provisionRuntimeInput.RuntimeInput.Labels)[key] = value
   208  	return r
   209  }
   210  
   211  func (r *RuntimeInput) CreateProvisionRuntimeInput() (gqlschema.ProvisionRuntimeInput, error) {
   212  	for _, step := range []struct {
   213  		name    string
   214  		execute func() error
   215  	}{
   216  		{
   217  			name:    "applying provisioning parameters customization",
   218  			execute: r.applyProvisioningParametersForProvisionRuntime,
   219  		},
   220  		{
   221  			name:    "disabling components",
   222  			execute: r.disableComponentsForProvisionRuntime,
   223  		},
   224  		{
   225  			name:    "disabling optional components that were not selected",
   226  			execute: r.resolveOptionalComponentsForProvisionRuntime,
   227  		},
   228  		{
   229  			name:    "applying components overrides",
   230  			execute: r.applyOverridesForProvisionRuntime,
   231  		},
   232  		{
   233  			name:    "applying global overrides",
   234  			execute: r.applyGlobalOverridesForProvisionRuntime,
   235  		},
   236  		{
   237  			name:    "applying global configuration",
   238  			execute: r.applyGlobalConfigurationForProvisionRuntime,
   239  		},
   240  		{
   241  			name:    "removing forbidden chars and adding random string to runtime name",
   242  			execute: r.adjustRuntimeName,
   243  		},
   244  		{
   245  			name:    "set number of nodes from configuration",
   246  			execute: r.setNodesForTrialProvision,
   247  		},
   248  		{
   249  			name:    "configure OIDC",
   250  			execute: r.configureOIDC,
   251  		},
   252  		{
   253  			name:    "configure DNS",
   254  			execute: r.configureDNS,
   255  		},
   256  		{
   257  			name:    "configure networking",
   258  			execute: r.configureNetworking,
   259  		},
   260  		{
   261  			name:    "configure modules",
   262  			execute: r.configureModules,
   263  		},
   264  	} {
   265  		if err := step.execute(); err != nil {
   266  			return gqlschema.ProvisionRuntimeInput{}, fmt.Errorf("while %s: %w", step.name, err)
   267  		}
   268  	}
   269  
   270  	return r.provisionRuntimeInput, nil
   271  }
   272  
   273  func (r *RuntimeInput) CreateUpgradeRuntimeInput() (gqlschema.UpgradeRuntimeInput, error) {
   274  	for _, step := range []struct {
   275  		name    string
   276  		execute func() error
   277  	}{
   278  		{
   279  			name:    "disabling components",
   280  			execute: r.disableComponentsForUpgradeRuntime,
   281  		},
   282  		{
   283  			name:    "disabling optional components that were not selected",
   284  			execute: r.resolveOptionalComponentsForUpgradeRuntime,
   285  		},
   286  		{
   287  			name:    "applying components overrides",
   288  			execute: r.applyOverridesForUpgradeRuntime,
   289  		},
   290  		{
   291  			name:    "applying global overrides",
   292  			execute: r.applyGlobalOverridesForUpgradeRuntime,
   293  		},
   294  		{
   295  			name:    "applying global configuration",
   296  			execute: r.applyGlobalConfigurationForUpgradeRuntime,
   297  		},
   298  		{
   299  			name:    "set number of nodes from configuration",
   300  			execute: r.setNodesForTrialProvision,
   301  		},
   302  	} {
   303  		if err := step.execute(); err != nil {
   304  			return gqlschema.UpgradeRuntimeInput{}, fmt.Errorf("while %s: %w", step.name, err)
   305  		}
   306  	}
   307  
   308  	return r.upgradeRuntimeInput, nil
   309  }
   310  
   311  func (r *RuntimeInput) CreateUpgradeShootInput() (gqlschema.UpgradeShootInput, error) {
   312  
   313  	for _, step := range []struct {
   314  		name    string
   315  		execute func() error
   316  	}{
   317  		{
   318  			name:    "applying provisioning parameters customization",
   319  			execute: r.applyProvisioningParametersForUpgradeShoot,
   320  		},
   321  		{
   322  			name:    "setting number of trial nodes from configuration",
   323  			execute: r.setNodesForTrialUpgrade,
   324  		},
   325  		{
   326  			name:    "configure OIDC",
   327  			execute: r.configureOIDC,
   328  		},
   329  	} {
   330  		if err := step.execute(); err != nil {
   331  			return gqlschema.UpgradeShootInput{}, fmt.Errorf("while %s: %w", step.name, err)
   332  		}
   333  	}
   334  	return r.upgradeShootInput, nil
   335  }
   336  
   337  func (r *RuntimeInput) Provider() internal.CloudProvider {
   338  	return r.hyperscalerInputProvider.Provider()
   339  }
   340  
   341  func (r *RuntimeInput) CreateClusterConfiguration() (reconcilerApi.Cluster, error) {
   342  	data, err := r.CreateProvisionRuntimeInput()
   343  	if err != nil {
   344  		return reconcilerApi.Cluster{}, err
   345  	}
   346  
   347  	if r.runtimeID == "" {
   348  		return reconcilerApi.Cluster{}, fmt.Errorf("missing runtime ID")
   349  	}
   350  	if r.instanceID == "" {
   351  		return reconcilerApi.Cluster{}, fmt.Errorf("missing instance ID")
   352  	}
   353  	if r.shootName == nil {
   354  		return reconcilerApi.Cluster{}, fmt.Errorf("missing shoot name")
   355  	}
   356  	if r.kubeconfig == "" {
   357  		return reconcilerApi.Cluster{}, fmt.Errorf("missing kubeconfig")
   358  	}
   359  
   360  	var componentConfigs []reconcilerApi.Component
   361  	for _, cmp := range data.KymaConfig.Components {
   362  		configs := []reconcilerApi.Configuration{
   363  			// because there is no section like global configuration, all "global" settings must
   364  			// be present in all component configurations.
   365  			{Key: "global.domainName", Value: r.shootDomain},
   366  		}
   367  		for _, globalCfg := range data.KymaConfig.Configuration {
   368  			configs = append(configs, reconcilerApi.Configuration{
   369  				Key:    globalCfg.Key,
   370  				Value:  resolveValueType(globalCfg.Value),
   371  				Secret: falseIfNil(globalCfg.Secret)})
   372  		}
   373  
   374  		for _, c := range cmp.Configuration {
   375  			configuration := reconcilerApi.Configuration{
   376  				Key:    c.Key,
   377  				Value:  resolveValueType(c.Value),
   378  				Secret: falseIfNil(c.Secret),
   379  			}
   380  			configs = append(configs, configuration)
   381  		}
   382  
   383  		componentConfig := reconcilerApi.Component{
   384  			Component:     cmp.Component,
   385  			Namespace:     cmp.Namespace,
   386  			Configuration: configs,
   387  		}
   388  		if cmp.SourceURL != nil {
   389  			componentConfig.URL = *cmp.SourceURL
   390  		}
   391  		componentConfigs = append(componentConfigs, componentConfig)
   392  	}
   393  
   394  	result := reconcilerApi.Cluster{
   395  		RuntimeID: r.runtimeID,
   396  		RuntimeInput: reconcilerApi.RuntimeInput{
   397  			Name:        r.provisionRuntimeInput.RuntimeInput.Name,
   398  			Description: emptyIfNil(data.RuntimeInput.Description),
   399  		},
   400  		KymaConfig: reconcilerApi.KymaConfig{
   401  			Version:        r.provisionRuntimeInput.KymaConfig.Version,
   402  			Profile:        string(*data.KymaConfig.Profile),
   403  			Components:     componentConfigs,
   404  			Administrators: data.ClusterConfig.Administrators,
   405  		},
   406  		Metadata: reconcilerApi.Metadata{
   407  			GlobalAccountID: r.provisioningParameters.ErsContext.GlobalAccountID,
   408  			SubAccountID:    r.provisioningParameters.ErsContext.SubAccountID,
   409  			ServiceID:       r.provisioningParameters.ServiceID,
   410  			ServicePlanID:   r.provisioningParameters.PlanID,
   411  			ServicePlanName: broker.PlanNamesMapping[r.provisioningParameters.PlanID],
   412  			ShootName:       *r.shootName,
   413  			InstanceID:      r.instanceID,
   414  		},
   415  		Kubeconfig: r.kubeconfig,
   416  	}
   417  
   418  	if r.provisionRuntimeInput.ClusterConfig != nil && r.provisionRuntimeInput.ClusterConfig.GardenerConfig != nil {
   419  		result.Metadata.Region = r.provisionRuntimeInput.ClusterConfig.GardenerConfig.Region
   420  	}
   421  
   422  	return result, nil
   423  }
   424  
   425  func emptyIfNil(p *string) string {
   426  	if p == nil {
   427  		return ""
   428  	}
   429  	return *p
   430  }
   431  
   432  func falseIfNil(p *bool) bool {
   433  	if p == nil {
   434  		return false
   435  	}
   436  	return *p
   437  }
   438  
   439  func (r *RuntimeInput) CreateProvisionClusterInput() (gqlschema.ProvisionRuntimeInput, error) {
   440  	result, err := r.CreateProvisionRuntimeInput()
   441  	if err != nil {
   442  		return gqlschema.ProvisionRuntimeInput{}, nil
   443  	}
   444  	result.KymaConfig = nil
   445  	return result, nil
   446  }
   447  
   448  func (r *RuntimeInput) applyProvisioningParametersForProvisionRuntime() error {
   449  	params := r.provisioningParameters.Parameters
   450  	updateString(&r.provisionRuntimeInput.RuntimeInput.Name, &params.Name)
   451  
   452  	if r.provisioningParameters.PlanID == broker.OwnClusterPlanID {
   453  		return nil
   454  	}
   455  
   456  	updateInt(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.MaxUnavailable, params.MaxUnavailable)
   457  	updateInt(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.MaxSurge, params.MaxSurge)
   458  	updateInt(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.AutoScalerMin, params.AutoScalerMin)
   459  	updateInt(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.AutoScalerMax, params.AutoScalerMax)
   460  	updateInt(r.provisionRuntimeInput.ClusterConfig.GardenerConfig.VolumeSizeGb, params.VolumeSizeGb)
   461  	updateString(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.Name, r.shootName)
   462  	if params.Region != nil && *params.Region != "" {
   463  		updateString(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.Region, params.Region)
   464  	}
   465  	updateString(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.MachineType, params.MachineType)
   466  	updateString(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.TargetSecret, params.TargetSecret)
   467  	updateString(r.provisionRuntimeInput.ClusterConfig.GardenerConfig.Purpose, params.Purpose)
   468  	if params.LicenceType != nil {
   469  		r.provisionRuntimeInput.ClusterConfig.GardenerConfig.LicenceType = params.LicenceType
   470  	}
   471  
   472  	// admins parameter check
   473  	if len(r.provisioningParameters.Parameters.RuntimeAdministrators) == 0 {
   474  		// default admin set from UserID in ERSContext
   475  		r.provisionRuntimeInput.ClusterConfig.Administrators = []string{r.provisioningParameters.ErsContext.UserID}
   476  	} else {
   477  		// set admins for new runtime
   478  		r.provisionRuntimeInput.ClusterConfig.Administrators = []string{}
   479  		r.provisionRuntimeInput.ClusterConfig.Administrators = append(
   480  			r.provisionRuntimeInput.ClusterConfig.Administrators,
   481  			r.provisioningParameters.Parameters.RuntimeAdministrators...,
   482  		)
   483  	}
   484  
   485  	r.hyperscalerInputProvider.ApplyParameters(r.provisionRuntimeInput.ClusterConfig, r.provisioningParameters)
   486  
   487  	return nil
   488  }
   489  
   490  func (r *RuntimeInput) applyProvisioningParametersForUpgradeShoot() error {
   491  	if len(r.provisioningParameters.Parameters.RuntimeAdministrators) != 0 {
   492  		// prepare new admins list for existing runtime
   493  		newAdministrators := make([]string, 0, len(r.provisioningParameters.Parameters.RuntimeAdministrators))
   494  		newAdministrators = append(newAdministrators, r.provisioningParameters.Parameters.RuntimeAdministrators...)
   495  		r.upgradeShootInput.Administrators = newAdministrators
   496  	} else {
   497  		if r.provisioningParameters.ErsContext.UserID != "" {
   498  			// get default admin (user_id from provisioning operation)
   499  			r.upgradeShootInput.Administrators = []string{r.provisioningParameters.ErsContext.UserID}
   500  		} else {
   501  			// some old clusters does not have an user_id
   502  			r.upgradeShootInput.Administrators = []string{}
   503  		}
   504  	}
   505  
   506  	updateInt(r.upgradeShootInput.GardenerConfig.MaxSurge, r.provisioningParameters.Parameters.MaxSurge)
   507  	updateInt(r.upgradeShootInput.GardenerConfig.MaxUnavailable, r.provisioningParameters.Parameters.MaxUnavailable)
   508  
   509  	return nil
   510  }
   511  
   512  func (r *RuntimeInput) resolveOptionalComponentsForProvisionRuntime() error {
   513  	r.muOptionalComponents.Lock()
   514  	defer r.muOptionalComponents.Unlock()
   515  
   516  	componentsToInstall := []string{}
   517  	componentsToInstall = append(componentsToInstall, r.provisioningParameters.Parameters.OptionalComponentsToInstall...)
   518  	for name := range r.enabledOptionalComponents {
   519  		componentsToInstall = append(componentsToInstall, name)
   520  	}
   521  	toDisable := r.optionalComponentsService.ComputeComponentsToDisable(componentsToInstall)
   522  
   523  	filterOut, err := r.optionalComponentsService.ExecuteDisablers(r.provisionRuntimeInput.KymaConfig.Components, toDisable...)
   524  	if err != nil {
   525  		return fmt.Errorf("while disabling components %v: %w", toDisable, err)
   526  	}
   527  
   528  	r.provisionRuntimeInput.KymaConfig.Components = filterOut
   529  
   530  	return nil
   531  }
   532  
   533  func (r *RuntimeInput) resolveOptionalComponentsForUpgradeRuntime() error {
   534  	r.muOptionalComponents.Lock()
   535  	defer r.muOptionalComponents.Unlock()
   536  
   537  	componentsToInstall := []string{}
   538  	componentsToInstall = append(componentsToInstall, r.provisioningParameters.Parameters.OptionalComponentsToInstall...)
   539  	for name := range r.enabledOptionalComponents {
   540  		componentsToInstall = append(componentsToInstall, name)
   541  	}
   542  	toDisable := r.optionalComponentsService.ComputeComponentsToDisable(componentsToInstall)
   543  
   544  	filterOut, err := r.optionalComponentsService.ExecuteDisablers(r.upgradeRuntimeInput.KymaConfig.Components, toDisable...)
   545  	if err != nil {
   546  		return fmt.Errorf("while disabling components %v: %w", toDisable, err)
   547  	}
   548  
   549  	r.upgradeRuntimeInput.KymaConfig.Components = filterOut
   550  
   551  	return nil
   552  }
   553  
   554  func (r *RuntimeInput) disableComponentsForProvisionRuntime() error {
   555  	filterOut, err := r.componentsDisabler.DisableComponents(r.provisionRuntimeInput.KymaConfig.Components)
   556  	if err != nil {
   557  		return err
   558  	}
   559  
   560  	r.provisionRuntimeInput.KymaConfig.Components = filterOut
   561  
   562  	return nil
   563  }
   564  
   565  func (r *RuntimeInput) disableComponentsForUpgradeRuntime() error {
   566  	filterOut, err := r.componentsDisabler.DisableComponents(r.upgradeRuntimeInput.KymaConfig.Components)
   567  	if err != nil {
   568  		return err
   569  	}
   570  
   571  	r.upgradeRuntimeInput.KymaConfig.Components = filterOut
   572  
   573  	return nil
   574  }
   575  
   576  func (r *RuntimeInput) applyOverridesForProvisionRuntime() error {
   577  	for i := range r.provisionRuntimeInput.KymaConfig.Components {
   578  		if entry, found := r.overrides[r.provisionRuntimeInput.KymaConfig.Components[i].Component]; found {
   579  			r.provisionRuntimeInput.KymaConfig.Components[i].Configuration = []*gqlschema.ConfigEntryInput{}
   580  			r.provisionRuntimeInput.KymaConfig.Components[i].Configuration = append(r.provisionRuntimeInput.KymaConfig.Components[i].Configuration, entry...)
   581  		}
   582  	}
   583  
   584  	return nil
   585  }
   586  
   587  func (r *RuntimeInput) applyOverridesForUpgradeRuntime() error {
   588  	for i := range r.upgradeRuntimeInput.KymaConfig.Components {
   589  		if entry, found := r.overrides[r.upgradeRuntimeInput.KymaConfig.Components[i].Component]; found {
   590  			r.upgradeRuntimeInput.KymaConfig.Components[i].Configuration = []*gqlschema.ConfigEntryInput{}
   591  			r.upgradeRuntimeInput.KymaConfig.Components[i].Configuration = append(r.upgradeRuntimeInput.KymaConfig.Components[i].Configuration, entry...)
   592  		}
   593  	}
   594  
   595  	return nil
   596  }
   597  
   598  func (r *RuntimeInput) applyGlobalOverridesForProvisionRuntime() error {
   599  	r.provisionRuntimeInput.KymaConfig.Configuration = r.globalOverrides
   600  	return nil
   601  }
   602  
   603  func (r *RuntimeInput) applyGlobalOverridesForUpgradeRuntime() error {
   604  	r.upgradeRuntimeInput.KymaConfig.Configuration = r.globalOverrides
   605  	return nil
   606  }
   607  
   608  func (r *RuntimeInput) applyGlobalConfigurationForProvisionRuntime() error {
   609  	strategy := gqlschema.ConflictStrategyReplace
   610  	r.provisionRuntimeInput.KymaConfig.ConflictStrategy = &strategy
   611  	return nil
   612  }
   613  
   614  func (r *RuntimeInput) applyGlobalConfigurationForUpgradeRuntime() error {
   615  	strategy := gqlschema.ConflictStrategyReplace
   616  	r.upgradeRuntimeInput.KymaConfig.ConflictStrategy = &strategy
   617  	return nil
   618  }
   619  
   620  func (r *RuntimeInput) adjustRuntimeName() error {
   621  	// if the cluster name was created before, it must be used instead of generating one
   622  	if r.clusterName != "" {
   623  		r.provisionRuntimeInput.RuntimeInput.Name = r.clusterName
   624  		return nil
   625  	}
   626  
   627  	reg, err := regexp.Compile("[^a-zA-Z0-9\\-\\.]+")
   628  	if err != nil {
   629  		return fmt.Errorf("while compiling regexp: %w", err)
   630  	}
   631  
   632  	name := strings.ToLower(reg.ReplaceAllString(r.provisionRuntimeInput.RuntimeInput.Name, ""))
   633  	modifiedLength := len(name) + trialSuffixLength + 1
   634  	if modifiedLength > maxRuntimeNameLength {
   635  		name = trimLastCharacters(name, modifiedLength-maxRuntimeNameLength)
   636  	}
   637  
   638  	r.provisionRuntimeInput.RuntimeInput.Name = fmt.Sprintf("%s-%s", name, randomString(trialSuffixLength))
   639  	return nil
   640  }
   641  
   642  func (r *RuntimeInput) configureDNS() error {
   643  	dnsParamsToSet := gqlschema.DNSConfigInput{}
   644  
   645  	// if dns providers is given
   646  	if len(r.shootDnsProviders.Providers) != 0 {
   647  		for _, v := range r.shootDnsProviders.Providers {
   648  			dnsParamsToSet.Providers = append(dnsParamsToSet.Providers, &gqlschema.DNSProviderInput{
   649  				DomainsInclude: v.DomainsInclude,
   650  				Primary:        v.Primary,
   651  				SecretName:     v.SecretName,
   652  				Type:           v.Type,
   653  			})
   654  		}
   655  	}
   656  
   657  	dnsParamsToSet.Domain = r.shootDomain
   658  
   659  	if r.provisionRuntimeInput.ClusterConfig != nil &&
   660  		r.provisionRuntimeInput.ClusterConfig.GardenerConfig != nil {
   661  		r.provisionRuntimeInput.ClusterConfig.GardenerConfig.DNSConfig = &dnsParamsToSet
   662  	}
   663  
   664  	return nil
   665  }
   666  
   667  func (r *RuntimeInput) configureOIDC() error {
   668  	// set default or provided params to provisioning/update input (if exists)
   669  	// This method could be used for:
   670  	// provisioning (upgradeShootInput.GardenerConfig is nil)
   671  	// or upgrade (provisionRuntimeInput.ClusterConfig is nil)
   672  
   673  	if r.provisionRuntimeInput.ClusterConfig != nil {
   674  		oidcParamsToSet := r.setOIDCForProvisioning()
   675  		r.provisionRuntimeInput.ClusterConfig.GardenerConfig.OidcConfig = oidcParamsToSet
   676  	}
   677  	if r.upgradeShootInput.GardenerConfig != nil {
   678  		oidcParamsToSet := r.setOIDCForUpgrade()
   679  		r.upgradeShootInput.GardenerConfig.OidcConfig = oidcParamsToSet
   680  	}
   681  	return nil
   682  }
   683  
   684  func (r *RuntimeInput) configureNetworking() error {
   685  	if r.provisioningParameters.Parameters.Networking == nil {
   686  		return nil
   687  	}
   688  	updateString(&r.provisionRuntimeInput.ClusterConfig.GardenerConfig.WorkerCidr,
   689  		&r.provisioningParameters.Parameters.Networking.NodesCidr)
   690  
   691  	// if the Networking section is set, then
   692  	r.provisionRuntimeInput.ClusterConfig.GardenerConfig.PodsCidr = ptr.String(networking.DefaultPodsCIDR)
   693  	updateString(r.provisionRuntimeInput.ClusterConfig.GardenerConfig.PodsCidr,
   694  		r.provisioningParameters.Parameters.Networking.PodsCidr)
   695  
   696  	r.provisionRuntimeInput.ClusterConfig.GardenerConfig.ServicesCidr = ptr.String(networking.DefaultServicesCIDR)
   697  	updateString(r.provisionRuntimeInput.ClusterConfig.GardenerConfig.ServicesCidr,
   698  		r.provisioningParameters.Parameters.Networking.ServicesCidr)
   699  
   700  	return nil
   701  }
   702  
   703  func (r *RuntimeInput) setNodesForTrialProvision() error {
   704  	// parameter with number of notes for trial plan is optional; if parameter is not set value is equal to 0
   705  	if r.trialNodesNumber == 0 {
   706  		return nil
   707  	}
   708  	if broker.IsTrialPlan(r.provisioningParameters.PlanID) {
   709  		r.provisionRuntimeInput.ClusterConfig.GardenerConfig.AutoScalerMin = r.trialNodesNumber
   710  		r.provisionRuntimeInput.ClusterConfig.GardenerConfig.AutoScalerMax = r.trialNodesNumber
   711  	}
   712  	return nil
   713  }
   714  
   715  func (r *RuntimeInput) setNodesForTrialUpgrade() error {
   716  	// parameter with number of nodes for trial plan is optional; if parameter is not set value is equal to 0
   717  	if r.trialNodesNumber == 0 {
   718  		return nil
   719  	}
   720  	if broker.IsTrialPlan(r.provisioningParameters.PlanID) {
   721  		r.upgradeShootInput.GardenerConfig.AutoScalerMin = &r.trialNodesNumber
   722  		r.upgradeShootInput.GardenerConfig.AutoScalerMax = &r.trialNodesNumber
   723  	}
   724  	return nil
   725  }
   726  
   727  func (r *RuntimeInput) setOIDCForProvisioning() *gqlschema.OIDCConfigInput {
   728  	oidcConfig := &gqlschema.OIDCConfigInput{
   729  		ClientID:       r.oidcDefaultValues.ClientID,
   730  		GroupsClaim:    r.oidcDefaultValues.GroupsClaim,
   731  		IssuerURL:      r.oidcDefaultValues.IssuerURL,
   732  		SigningAlgs:    r.oidcDefaultValues.SigningAlgs,
   733  		UsernameClaim:  r.oidcDefaultValues.UsernameClaim,
   734  		UsernamePrefix: r.oidcDefaultValues.UsernamePrefix,
   735  	}
   736  
   737  	if r.provisioningParameters.Parameters.OIDC.IsProvided() {
   738  		r.setOIDCFromProvisioningParameters(oidcConfig)
   739  	}
   740  
   741  	return oidcConfig
   742  }
   743  
   744  func (r *RuntimeInput) setOIDCForUpgrade() *gqlschema.OIDCConfigInput {
   745  	oidcConfig := r.oidcLastValues
   746  	r.setOIDCDefaultValuesIfEmpty(&oidcConfig)
   747  
   748  	if r.provisioningParameters.Parameters.OIDC.IsProvided() {
   749  		r.setOIDCFromProvisioningParameters(&oidcConfig)
   750  	}
   751  
   752  	return &oidcConfig
   753  }
   754  
   755  func (r *RuntimeInput) setOIDCFromProvisioningParameters(oidcConfig *gqlschema.OIDCConfigInput) {
   756  	providedOIDC := r.provisioningParameters.Parameters.OIDC
   757  	oidcConfig.ClientID = providedOIDC.ClientID
   758  	oidcConfig.IssuerURL = providedOIDC.IssuerURL
   759  	if len(providedOIDC.GroupsClaim) != 0 {
   760  		oidcConfig.GroupsClaim = providedOIDC.GroupsClaim
   761  	}
   762  	if len(providedOIDC.SigningAlgs) != 0 {
   763  		oidcConfig.SigningAlgs = providedOIDC.SigningAlgs
   764  	}
   765  	if len(providedOIDC.UsernameClaim) != 0 {
   766  		oidcConfig.UsernameClaim = providedOIDC.UsernameClaim
   767  	}
   768  	if len(providedOIDC.UsernamePrefix) != 0 {
   769  		oidcConfig.UsernamePrefix = providedOIDC.UsernamePrefix
   770  	}
   771  }
   772  
   773  func (r *RuntimeInput) setOIDCDefaultValuesIfEmpty(oidcConfig *gqlschema.OIDCConfigInput) {
   774  	if oidcConfig.ClientID == "" {
   775  		oidcConfig.ClientID = r.oidcDefaultValues.ClientID
   776  	}
   777  	if oidcConfig.IssuerURL == "" {
   778  		oidcConfig.IssuerURL = r.oidcDefaultValues.IssuerURL
   779  	}
   780  	if oidcConfig.GroupsClaim == "" {
   781  		oidcConfig.GroupsClaim = r.oidcDefaultValues.GroupsClaim
   782  	}
   783  	if len(oidcConfig.SigningAlgs) == 0 {
   784  		oidcConfig.SigningAlgs = r.oidcDefaultValues.SigningAlgs
   785  	}
   786  	if oidcConfig.UsernameClaim == "" {
   787  		oidcConfig.UsernameClaim = r.oidcDefaultValues.UsernameClaim
   788  	}
   789  	if oidcConfig.UsernamePrefix == "" {
   790  		oidcConfig.UsernamePrefix = r.oidcDefaultValues.UsernamePrefix
   791  	}
   792  }
   793  
   794  func (r *RuntimeInput) configureModules() error {
   795  	if r.provisioningParameters.Parameters.Modules != nil {
   796  		r.modules = *r.provisioningParameters.Parameters.Modules
   797  	}
   798  	return nil
   799  }
   800  
   801  func updateString(toUpdate *string, value *string) {
   802  	if value != nil {
   803  		*toUpdate = *value
   804  	}
   805  }
   806  
   807  func updateInt(toUpdate *int, value *int) {
   808  	if value != nil {
   809  		*toUpdate = *value
   810  	}
   811  }
   812  
   813  func randomString(n int) string {
   814  	var letters = []rune("abcdefghijklmnopqrstuvwxyz")
   815  
   816  	b := make([]rune, n)
   817  	for i := range b {
   818  		b[i] = letters[rand.Intn(len(letters))]
   819  	}
   820  	return string(b)
   821  }
   822  
   823  func trimLastCharacters(s string, count int) string {
   824  	s = s[:len(s)-count]
   825  	return s
   826  }
   827  
   828  func resolveValueType(v interface{}) interface{} {
   829  	// this is a workaround. Finally we have to obtain the type during the reading overrides
   830  	var val interface{}
   831  	switch v {
   832  	case "true":
   833  		val = true
   834  	case "false":
   835  		val = false
   836  	default:
   837  		val = v
   838  	}
   839  
   840  	return val
   841  }