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

     1  package runtimeoverrides
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema"
     9  	"github.com/kyma-project/kyma-environment-broker/internal"
    10  	"github.com/kyma-project/kyma-environment-broker/internal/ptr"
    11  	coreV1 "k8s.io/api/core/v1"
    12  	"sigs.k8s.io/controller-runtime/pkg/client"
    13  )
    14  
    15  const (
    16  	namespace                   = "kcp-system"
    17  	componentNameLabel          = "component"
    18  	overridesVersionLabelPrefix = "overrides-version-"
    19  	overridesPlanLabelPrefix    = "overrides-plan-"
    20  	overridesSecretLabel        = "runtime-override"
    21  )
    22  
    23  type InputAppender interface {
    24  	AppendOverrides(component string, overrides []*gqlschema.ConfigEntryInput) internal.ProvisionerInputCreator
    25  	AppendGlobalOverrides(overrides []*gqlschema.ConfigEntryInput) internal.ProvisionerInputCreator
    26  }
    27  
    28  type runtimeOverrides struct {
    29  	ctx       context.Context
    30  	k8sClient client.Client
    31  }
    32  
    33  func NewRuntimeOverrides(ctx context.Context, cli client.Client) *runtimeOverrides {
    34  	return &runtimeOverrides{
    35  		ctx:       ctx,
    36  		k8sClient: cli,
    37  	}
    38  }
    39  
    40  func (ro *runtimeOverrides) Append(input InputAppender, planName, overridesVersion string) error {
    41  	{
    42  		componentsOverrides, globalOverrides, err := ro.collectFromSecrets()
    43  		if err != nil {
    44  			return fmt.Errorf("cannot collect overrides from secrets: %w", err)
    45  		}
    46  
    47  		appendOverrides(input, componentsOverrides, globalOverrides)
    48  	}
    49  
    50  	{
    51  		componentsOverrides, globalOverrides, err := ro.collectFromConfigMaps(planName, overridesVersion)
    52  		if err != nil {
    53  			return fmt.Errorf("cannot collect overrides from config maps: %w", err)
    54  		}
    55  
    56  		if len(globalOverrides) == 0 {
    57  			return fmt.Errorf("no global overrides for plan '%s' and version '%s'", planName, overridesVersion)
    58  		}
    59  
    60  		appendOverrides(input, componentsOverrides, globalOverrides)
    61  	}
    62  
    63  	return nil
    64  }
    65  
    66  func (ro *runtimeOverrides) collectFromSecrets() (map[string][]*gqlschema.ConfigEntryInput, []*gqlschema.ConfigEntryInput, error) {
    67  	componentsOverrides := make(map[string][]*gqlschema.ConfigEntryInput, 0)
    68  	globalOverrides := make([]*gqlschema.ConfigEntryInput, 0)
    69  
    70  	secrets := &coreV1.SecretList{}
    71  	listOpts := secretListOptions()
    72  
    73  	if err := ro.k8sClient.List(ro.ctx, secrets, listOpts...); err != nil {
    74  		return componentsOverrides, globalOverrides, fmt.Errorf("cannot fetch list of secrets: %w", err)
    75  	}
    76  
    77  	for _, secret := range secrets.Items {
    78  		component, global := getComponent(secret.Labels)
    79  		for key, value := range secret.Data {
    80  			if global {
    81  				globalOverrides = append(globalOverrides, &gqlschema.ConfigEntryInput{
    82  					Key:    key,
    83  					Value:  string(value),
    84  					Secret: ptr.Bool(true),
    85  				})
    86  			} else {
    87  				componentsOverrides[component] = append(componentsOverrides[component], &gqlschema.ConfigEntryInput{
    88  					Key:    key,
    89  					Value:  string(value),
    90  					Secret: ptr.Bool(true),
    91  				})
    92  			}
    93  		}
    94  	}
    95  
    96  	return componentsOverrides, globalOverrides, nil
    97  }
    98  
    99  func (ro *runtimeOverrides) collectFromConfigMaps(planName, overridesVersion string) (map[string][]*gqlschema.ConfigEntryInput, []*gqlschema.ConfigEntryInput, error) {
   100  	componentsOverrides := make(map[string][]*gqlschema.ConfigEntryInput, 0)
   101  	globalOverrides := make([]*gqlschema.ConfigEntryInput, 0)
   102  
   103  	configMaps := &coreV1.ConfigMapList{}
   104  	listOpts := configMapListOptions(planName, overridesVersion)
   105  
   106  	if err := ro.k8sClient.List(ro.ctx, configMaps, listOpts...); err != nil {
   107  		return componentsOverrides, globalOverrides, fmt.Errorf("cannot fetch list of config maps: %w", err)
   108  	}
   109  
   110  	for _, cm := range configMaps.Items {
   111  		component, global := getComponent(cm.Labels)
   112  		for key, value := range cm.Data {
   113  			if global {
   114  				globalOverrides = append(globalOverrides, &gqlschema.ConfigEntryInput{
   115  					Key:   key,
   116  					Value: value,
   117  				})
   118  			} else {
   119  				componentsOverrides[component] = append(componentsOverrides[component], &gqlschema.ConfigEntryInput{
   120  					Key:   key,
   121  					Value: value,
   122  				})
   123  			}
   124  		}
   125  	}
   126  
   127  	return componentsOverrides, globalOverrides, nil
   128  }
   129  
   130  func secretListOptions() []client.ListOption {
   131  	label := map[string]string{
   132  		overridesSecretLabel: "true",
   133  	}
   134  
   135  	return []client.ListOption{
   136  		client.InNamespace(namespace),
   137  		client.MatchingLabels(label),
   138  	}
   139  }
   140  
   141  func configMapListOptions(plan string, version string) []client.ListOption {
   142  	planLabel := overridesPlanLabelPrefix + plan
   143  	versionLabel := overridesVersionLabelPrefix + strings.ToLower(version)
   144  
   145  	label := map[string]string{
   146  		planLabel:    "true",
   147  		versionLabel: "true",
   148  	}
   149  
   150  	return []client.ListOption{
   151  		client.InNamespace(namespace),
   152  		client.MatchingLabels(label),
   153  	}
   154  }
   155  
   156  func getComponent(labels map[string]string) (string, bool) {
   157  	for name, value := range labels {
   158  		if name == componentNameLabel {
   159  			return value, false
   160  		}
   161  	}
   162  	return "", true
   163  }
   164  
   165  func appendOverrides(input InputAppender, componentsOverrides map[string][]*gqlschema.ConfigEntryInput, globalOverrides []*gqlschema.ConfigEntryInput) {
   166  	for component, overrides := range componentsOverrides {
   167  		input.AppendOverrides(component, overrides)
   168  	}
   169  
   170  	if len(globalOverrides) > 0 {
   171  		input.AppendGlobalOverrides(globalOverrides)
   172  	}
   173  }