externalsecret_controller_template.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package externalsecret
  13. import (
  14. "context"
  15. "fmt"
  16. "maps"
  17. v1 "k8s.io/api/core/v1"
  18. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  19. "github.com/external-secrets/external-secrets/pkg/controllers/templating"
  20. "github.com/external-secrets/external-secrets/pkg/template"
  21. "github.com/external-secrets/external-secrets/pkg/utils"
  22. _ "github.com/external-secrets/external-secrets/pkg/provider/register" // Loading registered providers.
  23. )
  24. // merge template in the following order:
  25. // * template.Data (highest precedence)
  26. // * template.TemplateFrom
  27. // * secret via es.data or es.dataFrom (if template.MergePolicy is Merge, or there is no template)
  28. // * existing secret keys (if CreationPolicy is Merge).
  29. func (r *Reconciler) applyTemplate(ctx context.Context, es *esv1beta1.ExternalSecret, secret *v1.Secret, dataMap map[string][]byte) error {
  30. // update metadata (labels, annotations) of the secret
  31. if err := setMetadata(secret, es); err != nil {
  32. return err
  33. }
  34. // we only keep existing keys if creation policy is Merge, otherwise we clear the secret
  35. if es.Spec.Target.CreationPolicy != esv1beta1.CreatePolicyMerge {
  36. secret.Data = make(map[string][]byte)
  37. }
  38. // no template: copy data and return
  39. if es.Spec.Target.Template == nil {
  40. maps.Insert(secret.Data, maps.All(dataMap))
  41. return nil
  42. }
  43. // set the secret type if it is defined in the template, otherwise keep the existing type
  44. if es.Spec.Target.Template.Type != "" {
  45. secret.Type = es.Spec.Target.Template.Type
  46. }
  47. // when TemplateMergePolicy is Merge, or there is no data template, we include the keys from `dataMap`
  48. noTemplate := len(es.Spec.Target.Template.Data) == 0 && len(es.Spec.Target.Template.TemplateFrom) == 0
  49. if es.Spec.Target.Template.MergePolicy == esv1beta1.MergePolicyMerge || noTemplate {
  50. maps.Insert(secret.Data, maps.All(dataMap))
  51. }
  52. execute, err := template.EngineForVersion(es.Spec.Target.Template.EngineVersion)
  53. if err != nil {
  54. return err
  55. }
  56. p := templating.Parser{
  57. Client: r.Client,
  58. TargetSecret: secret,
  59. DataMap: dataMap,
  60. Exec: execute,
  61. }
  62. // apply templates defined in template.templateFrom
  63. err = p.MergeTemplateFrom(ctx, es.Namespace, es.Spec.Target.Template)
  64. if err != nil {
  65. return fmt.Errorf(errFetchTplFrom, err)
  66. }
  67. // explicitly defined template.Data takes precedence over templateFrom
  68. err = p.MergeMap(es.Spec.Target.Template.Data, esv1beta1.TemplateTargetData)
  69. if err != nil {
  70. return fmt.Errorf(errExecTpl, err)
  71. }
  72. // get template data for labels
  73. err = p.MergeMap(es.Spec.Target.Template.Metadata.Labels, esv1beta1.TemplateTargetLabels)
  74. if err != nil {
  75. return fmt.Errorf(errExecTpl, err)
  76. }
  77. // get template data for annotations
  78. err = p.MergeMap(es.Spec.Target.Template.Metadata.Annotations, esv1beta1.TemplateTargetAnnotations)
  79. if err != nil {
  80. return fmt.Errorf(errExecTpl, err)
  81. }
  82. return nil
  83. }
  84. // setMetadata sets Labels and Annotations to the given secret.
  85. func setMetadata(secret *v1.Secret, es *esv1beta1.ExternalSecret) error {
  86. // ensure that Labels and Annotations are not nil
  87. // so it is safe to merge them
  88. if secret.Labels == nil {
  89. secret.Labels = make(map[string]string)
  90. }
  91. if secret.Annotations == nil {
  92. secret.Annotations = make(map[string]string)
  93. }
  94. // remove any existing labels managed by this external secret
  95. // this is to ensure that we don't have any stale labels
  96. labelKeys, err := templating.GetManagedLabelKeys(secret, es.Name)
  97. if err != nil {
  98. return err
  99. }
  100. for _, key := range labelKeys {
  101. delete(secret.ObjectMeta.Labels, key)
  102. }
  103. annotationKeys, err := templating.GetManagedAnnotationKeys(secret, es.Name)
  104. if err != nil {
  105. return err
  106. }
  107. for _, key := range annotationKeys {
  108. delete(secret.ObjectMeta.Annotations, key)
  109. }
  110. // if no template is defined, copy labels and annotations from the ExternalSecret
  111. if es.Spec.Target.Template == nil {
  112. utils.MergeStringMap(secret.ObjectMeta.Labels, es.ObjectMeta.Labels)
  113. utils.MergeStringMap(secret.ObjectMeta.Annotations, es.ObjectMeta.Annotations)
  114. return nil
  115. }
  116. // copy labels and annotations from the template
  117. utils.MergeStringMap(secret.ObjectMeta.Labels, es.Spec.Target.Template.Metadata.Labels)
  118. utils.MergeStringMap(secret.ObjectMeta.Annotations, es.Spec.Target.Template.Metadata.Annotations)
  119. return nil
  120. }