-
Notifications
You must be signed in to change notification settings - Fork 774
feat: Multi StackConfigPolicy per cluster #8793
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
d528988
e8a95dc
706aca4
f18b19e
e35848f
35d4caf
cc21222
a1b9c6c
a2563fd
8445011
9ea2fae
f7613d2
4813911
dc6a49c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,6 +7,7 @@ package filesettings | |||||||||
| import ( | ||||||||||
| "fmt" | ||||||||||
| "path/filepath" | ||||||||||
| "sort" | ||||||||||
|
|
||||||||||
| "k8s.io/apimachinery/pkg/types" | ||||||||||
|
|
||||||||||
|
|
@@ -80,10 +81,39 @@ func newEmptySettingsState() SettingsState { | |||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // updateStateFromPolicies merges settings from multiple StackConfigPolicies based on their weights. | ||||||||||
| // Lower weight policies override higher weight policies for conflicting settings. | ||||||||||
| func (s *Settings) updateStateFromPolicies(es types.NamespacedName, policies []policyv1alpha1.StackConfigPolicy) error { | ||||||||||
| if len(policies) == 0 { | ||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| sortedPolicies := make([]policyv1alpha1.StackConfigPolicy, len(policies)) | ||||||||||
| copy(sortedPolicies, policies) | ||||||||||
|
|
||||||||||
| // sort by weight (descending order) | ||||||||||
| sort.SliceStable(sortedPolicies, func(i, j int) bool { | ||||||||||
| return sortedPolicies[i].Spec.Weight > sortedPolicies[j].Spec.Weight | ||||||||||
| }) | ||||||||||
|
|
||||||||||
| for _, policy := range sortedPolicies { | ||||||||||
| if err := s.updateState(es, policy); err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // updateState updates the Settings state from a StackConfigPolicy for a given Elasticsearch. | ||||||||||
| func (s *Settings) updateState(es types.NamespacedName, policy policyv1alpha1.StackConfigPolicy) error { | ||||||||||
| p := policy.DeepCopy() // be sure to not mutate the original policy | ||||||||||
| state := newEmptySettingsState() | ||||||||||
|
|
||||||||||
| // Initialize state if not already done | ||||||||||
| if s.State.ClusterSettings == nil { | ||||||||||
| s.State = newEmptySettingsState() | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // mutate Snapshot Repositories | ||||||||||
| if p.Spec.Elasticsearch.SnapshotRepositories != nil { | ||||||||||
| for name, untypedDefinition := range p.Spec.Elasticsearch.SnapshotRepositories.Data { | ||||||||||
|
|
@@ -97,34 +127,59 @@ func (s *Settings) updateState(es types.NamespacedName, policy policyv1alpha1.St | |||||||||
| } | ||||||||||
| p.Spec.Elasticsearch.SnapshotRepositories.Data[name] = repoSettings | ||||||||||
| } | ||||||||||
| state.SnapshotRepositories = p.Spec.Elasticsearch.SnapshotRepositories | ||||||||||
| s.mergeConfig(s.State.SnapshotRepositories, p.Spec.Elasticsearch.SnapshotRepositories) | ||||||||||
| } | ||||||||||
| // just copy other settings | ||||||||||
| // merge other settings | ||||||||||
| if p.Spec.Elasticsearch.ClusterSettings != nil { | ||||||||||
| state.ClusterSettings = p.Spec.Elasticsearch.ClusterSettings | ||||||||||
| s.mergeConfig(s.State.ClusterSettings, p.Spec.Elasticsearch.ClusterSettings) | ||||||||||
| } | ||||||||||
| if p.Spec.Elasticsearch.SnapshotLifecyclePolicies != nil { | ||||||||||
| state.SLM = p.Spec.Elasticsearch.SnapshotLifecyclePolicies | ||||||||||
| s.mergeConfig(s.State.SLM, p.Spec.Elasticsearch.SnapshotLifecyclePolicies) | ||||||||||
| } | ||||||||||
| if p.Spec.Elasticsearch.SecurityRoleMappings != nil { | ||||||||||
| state.RoleMappings = p.Spec.Elasticsearch.SecurityRoleMappings | ||||||||||
| s.mergeConfig(s.State.RoleMappings, p.Spec.Elasticsearch.SecurityRoleMappings) | ||||||||||
| } | ||||||||||
| if p.Spec.Elasticsearch.IndexLifecyclePolicies != nil { | ||||||||||
| state.IndexLifecyclePolicies = p.Spec.Elasticsearch.IndexLifecyclePolicies | ||||||||||
| s.mergeConfig(s.State.IndexLifecyclePolicies, p.Spec.Elasticsearch.IndexLifecyclePolicies) | ||||||||||
| } | ||||||||||
| if p.Spec.Elasticsearch.IngestPipelines != nil { | ||||||||||
| state.IngestPipelines = p.Spec.Elasticsearch.IngestPipelines | ||||||||||
| s.mergeConfig(s.State.IngestPipelines, p.Spec.Elasticsearch.IngestPipelines) | ||||||||||
| } | ||||||||||
| if p.Spec.Elasticsearch.IndexTemplates.ComposableIndexTemplates != nil { | ||||||||||
| state.IndexTemplates.ComposableIndexTemplates = p.Spec.Elasticsearch.IndexTemplates.ComposableIndexTemplates | ||||||||||
| s.mergeConfig(s.State.IndexTemplates.ComposableIndexTemplates, p.Spec.Elasticsearch.IndexTemplates.ComposableIndexTemplates) | ||||||||||
| } | ||||||||||
| if p.Spec.Elasticsearch.IndexTemplates.ComponentTemplates != nil { | ||||||||||
| state.IndexTemplates.ComponentTemplates = p.Spec.Elasticsearch.IndexTemplates.ComponentTemplates | ||||||||||
| s.mergeConfig(s.State.IndexTemplates.ComponentTemplates, p.Spec.Elasticsearch.IndexTemplates.ComponentTemplates) | ||||||||||
| } | ||||||||||
| s.State = state | ||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // mergeConfig merges source config into target config, with source taking precedence | ||||||||||
| // For map-type values (like snapshot repositories), individual entries are merged rather than replaced | ||||||||||
| func (s *Settings) mergeConfig(target, source *commonv1.Config) { | ||||||||||
|
||||||||||
| if source == nil || source.Data == nil { | ||||||||||
| return | ||||||||||
|
||||||||||
| return | |
| func (s *Settings) mergeConfig(target, source *commonv1.Config) *commonv1.Config { | |
| if source == nil || source.Data == nil { | |
| return target |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a valid copilot observation. Also I would expect unit tests for this kind of functionality. We do have more advanced merging through the CanonicalConfig abstraction in the code base. But there might be some gotchas with the more complex configuration objects that stack config policies support that might not be thinking of right now.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems too simplistic given that for example cluster settings can both be in nested and flat syntax. Also it only merges one level deep?
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -39,6 +39,85 @@ func NewSettingsSecretWithVersion(es types.NamespacedName, currentSecret *corev1 | |||||||||||||||||||||
| return newSettingsSecret(newVersion, es, currentSecret, policy, meta) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // NewSettingsSecretWithVersionFromPolicies returns a new SettingsSecret for a given Elasticsearch from multiple policies. | ||||||||||||||||||||||
| // Policies are merged based on their weights, with higher weights taking precedence. | ||||||||||||||||||||||
| func NewSettingsSecretWithVersionFromPolicies(es types.NamespacedName, currentSecret *corev1.Secret, policies []policyv1alpha1.StackConfigPolicy, meta metadata.Metadata) (corev1.Secret, int64, error) { | ||||||||||||||||||||||
| newVersion := time.Now().UnixNano() | ||||||||||||||||||||||
| return NewSettingsSecretFromPolicies(newVersion, es, currentSecret, policies, meta) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // NewSettingsSecretFromPolicies returns a new SettingsSecret for a given Elasticsearch from multiple StackConfigPolicies. | ||||||||||||||||||||||
tehbooom marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||
| func NewSettingsSecretFromPolicies(version int64, es types.NamespacedName, currentSecret *corev1.Secret, policies []policyv1alpha1.StackConfigPolicy, meta metadata.Metadata) (corev1.Secret, int64, error) { | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be only called from |
||||||||||||||||||||||
| settings := NewEmptySettings(version) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // update the settings according to the config policies | ||||||||||||||||||||||
| if len(policies) > 0 { | ||||||||||||||||||||||
| err := settings.updateStateFromPolicies(es, policies) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return corev1.Secret{}, 0, err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // do not update version if hash hasn't changed | ||||||||||||||||||||||
| if currentSecret != nil && !hasChanged(*currentSecret, settings) { | ||||||||||||||||||||||
| currentVersion, err := extractVersion(*currentSecret) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return corev1.Secret{}, 0, err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| version = currentVersion | ||||||||||||||||||||||
| settings.Metadata.Version = strconv.FormatInt(currentVersion, 10) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // prepare the SettingsSecret | ||||||||||||||||||||||
| secretMeta := meta.Merge(metadata.Metadata{ | ||||||||||||||||||||||
| Annotations: map[string]string{ | ||||||||||||||||||||||
| commonannotation.SettingsHashAnnotationName: settings.hash(), | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| settingsBytes, err := json.Marshal(settings) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return corev1.Secret{}, 0, err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| settingsSecret := &corev1.Secret{ | ||||||||||||||||||||||
| ObjectMeta: metav1.ObjectMeta{ | ||||||||||||||||||||||
| Namespace: es.Namespace, | ||||||||||||||||||||||
| Name: esv1.FileSettingsSecretName(es.Name), | ||||||||||||||||||||||
| Labels: secretMeta.Labels, | ||||||||||||||||||||||
| Annotations: secretMeta.Annotations, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| Data: map[string][]byte{ | ||||||||||||||||||||||
| SettingsSecretKey: settingsBytes, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Store all policy references in the secret | ||||||||||||||||||||||
| policyRefs := make([]PolicyRef, 0, len(policies)) | ||||||||||||||||||||||
| for _, policy := range policies { | ||||||||||||||||||||||
| policyRefs = append(policyRefs, PolicyRef{ | ||||||||||||||||||||||
| Name: policy.Name, | ||||||||||||||||||||||
| Namespace: policy.Namespace, | ||||||||||||||||||||||
| Weight: policy.Spec.Weight, | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| if err := SetPolicyRefs(settingsSecret, policyRefs); err != nil { | ||||||||||||||||||||||
| return corev1.Secret{}, 0, err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Add secure settings from all policies | ||||||||||||||||||||||
| if err := setSecureSettingsFromPolicies(settingsSecret, policies); err != nil { | ||||||||||||||||||||||
| return corev1.Secret{}, 0, err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Add a label to reset secret on deletion of the stack config policy | ||||||||||||||||||||||
| if settingsSecret.Labels == nil { | ||||||||||||||||||||||
| settingsSecret.Labels = make(map[string]string) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| settingsSecret.Labels[commonlabel.StackConfigPolicyOnDeleteLabelName] = commonlabel.OrphanSecretResetOnPolicyDelete | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return *settingsSecret, version, nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // NewSettingsSecret returns a new SettingsSecret for a given Elasticsearch and StackConfigPolicy. | ||||||||||||||||||||||
| func newSettingsSecret(version int64, es types.NamespacedName, currentSecret *corev1.Secret, policy *policyv1alpha1.StackConfigPolicy, meta metadata.Metadata) (corev1.Secret, int64, error) { | ||||||||||||||||||||||
| settings := NewEmptySettings(version) | ||||||||||||||||||||||
|
|
@@ -160,6 +239,35 @@ func setSecureSettings(settingsSecret *corev1.Secret, policy policyv1alpha1.Stac | |||||||||||||||||||||
| return nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // setSecureSettingsFromPolicies sets secure settings from multiple policies into the settings secret | ||||||||||||||||||||||
| func setSecureSettingsFromPolicies(settingsSecret *corev1.Secret, policies []policyv1alpha1.StackConfigPolicy) error { | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is almost identical to |
||||||||||||||||||||||
| var allSecretSources []commonv1.NamespacedSecretSource | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| for _, policy := range policies { | ||||||||||||||||||||||
| // Common secureSettings field, this is mainly there to maintain backwards compatibility | ||||||||||||||||||||||
| //nolint:staticcheck | ||||||||||||||||||||||
| for _, src := range policy.Spec.SecureSettings { | ||||||||||||||||||||||
| allSecretSources = append(allSecretSources, commonv1.NamespacedSecretSource{Namespace: policy.GetNamespace(), SecretName: src.SecretName, Entries: src.Entries}) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // SecureSettings field under Elasticsearch in the StackConfigPolicy | ||||||||||||||||||||||
| for _, src := range policy.Spec.Elasticsearch.SecureSettings { | ||||||||||||||||||||||
| allSecretSources = append(allSecretSources, commonv1.NamespacedSecretSource{Namespace: policy.GetNamespace(), SecretName: src.SecretName, Entries: src.Entries}) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if len(allSecretSources) == 0 { | ||||||||||||||||||||||
| return nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| bytes, err := json.Marshal(allSecretSources) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| settingsSecret.Annotations[commonannotation.SecureSettingsSecretsAnnotationName] = string(bytes) | ||||||||||||||||||||||
| return nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // CanBeOwnedBy return true if the Settings Secret can be owned by the given StackConfigPolicy, either because the Secret | ||||||||||||||||||||||
| // belongs to no one or because it already belongs to the given policy. | ||||||||||||||||||||||
| func CanBeOwnedBy(settingsSecret corev1.Secret, policy policyv1alpha1.StackConfigPolicy) (reconciler.SoftOwnerRef, bool) { | ||||||||||||||||||||||
|
|
@@ -173,6 +281,94 @@ func CanBeOwnedBy(settingsSecret corev1.Secret, policy policyv1alpha1.StackConfi | |||||||||||||||||||||
| return currentOwner, canBeOwned | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // PolicyRef represents a reference to a StackConfigPolicy with its weight | ||||||||||||||||||||||
| type PolicyRef struct { | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I take it that these refs are intended as some kind of tracking mechanism to know which policy contributed to the effective settings. However what I am missing is a replacement of the owner references that we had in the single policy approach. This implemenation leaks secrets once you have deleted the policy there is no mechanism in place to clean up the secrets. |
||||||||||||||||||||||
| Name string | ||||||||||||||||||||||
| Namespace string | ||||||||||||||||||||||
| Weight int32 | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
Comment on lines
+285
to
+289
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // GetPolicyRefs extracts all policy references from a secret's annotations | ||||||||||||||||||||||
| func GetPolicyRefs(secret corev1.Secret) ([]PolicyRef, error) { | ||||||||||||||||||||||
| if secret.Annotations == nil { | ||||||||||||||||||||||
| return nil, nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| policiesData, ok := secret.Annotations["stackconfigpolicy.k8s.elastic.co/policies"] | ||||||||||||||||||||||
| if !ok { | ||||||||||||||||||||||
| return nil, nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| var policies []PolicyRef | ||||||||||||||||||||||
| if err := json.Unmarshal([]byte(policiesData), &policies); err != nil { | ||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return policies, nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // SetPolicyRefs stores policy references in a secret's annotations | ||||||||||||||||||||||
| func SetPolicyRefs(secret *corev1.Secret, policies []PolicyRef) error { | ||||||||||||||||||||||
| if secret.Annotations == nil { | ||||||||||||||||||||||
| secret.Annotations = make(map[string]string) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| data, err := json.Marshal(policies) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| secret.Annotations["stackconfigpolicy.k8s.elastic.co/policies"] = string(data) | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a constant. |
||||||||||||||||||||||
| return nil | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // AddOrUpdatePolicyRef adds or updates a policy reference in the secret | ||||||||||||||||||||||
| func AddOrUpdatePolicyRef(secret *corev1.Secret, policy policyv1alpha1.StackConfigPolicy) error { | ||||||||||||||||||||||
| policies, err := GetPolicyRefs(*secret) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| policyRef := PolicyRef{ | ||||||||||||||||||||||
| Name: policy.Name, | ||||||||||||||||||||||
| Namespace: policy.Namespace, | ||||||||||||||||||||||
| Weight: policy.Spec.Weight, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Update existing policy or add new one | ||||||||||||||||||||||
| found := false | ||||||||||||||||||||||
| for i, p := range policies { | ||||||||||||||||||||||
| if p.Name == policy.Name && p.Namespace == policy.Namespace { | ||||||||||||||||||||||
| policies[i] = policyRef | ||||||||||||||||||||||
| found = true | ||||||||||||||||||||||
| break | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if !found { | ||||||||||||||||||||||
| policies = append(policies, policyRef) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return SetPolicyRefs(secret, policies) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // RemovePolicyRef removes a policy reference from the secret | ||||||||||||||||||||||
| func RemovePolicyRef(secret *corev1.Secret, policyName, policyNamespace string) error { | ||||||||||||||||||||||
| policies, err := GetPolicyRefs(*secret) | ||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||
| return err | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| var filtered []PolicyRef | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would a map keyed on namespace/name not be more convenient here? |
||||||||||||||||||||||
| for _, p := range policies { | ||||||||||||||||||||||
| if !(p.Name == policyName && p.Namespace == policyNamespace) { | ||||||||||||||||||||||
| filtered = append(filtered, p) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return SetPolicyRefs(secret, filtered) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // getSecureSettings returns the SecureSettings Secret sources stores in an annotation of the given file settings Secret. | ||||||||||||||||||||||
| func getSecureSettings(settingsSecret corev1.Secret) ([]commonv1.NamespacedSecretSource, error) { | ||||||||||||||||||||||
| rawString, ok := settingsSecret.Annotations[commonannotation.SecureSettingsSecretsAnnotationName] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cosmetic nit, I found it useful to have the weight in a column, feel free to ignore if you think otherwise:
Result: