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 }