Browse Source

Set metadata to external secrets managed by cluster external secrets (#2413)

Signed-off-by: shuheiktgw <s-kitagawa@mercari.com>
Shuhei Kitagawa 2 years ago
parent
commit
9dd4186df1

+ 13 - 0
apis/externalsecrets/v1beta1/clusterexternalsecret_types.go

@@ -28,6 +28,10 @@ type ClusterExternalSecretSpec struct {
 	// +optional
 	// +optional
 	ExternalSecretName string `json:"externalSecretName"`
 	ExternalSecretName string `json:"externalSecretName"`
 
 
+	// The metadata of the external secrets to be created
+	// +optional
+	ExternalSecretMetadata ExternalSecretMetadata `json:"externalSecretMetadata"`
+
 	// The labels to select by to find the Namespaces to create the ExternalSecrets in.
 	// The labels to select by to find the Namespaces to create the ExternalSecrets in.
 	NamespaceSelector metav1.LabelSelector `json:"namespaceSelector"`
 	NamespaceSelector metav1.LabelSelector `json:"namespaceSelector"`
 
 
@@ -35,6 +39,15 @@ type ClusterExternalSecretSpec struct {
 	RefreshInterval *metav1.Duration `json:"refreshTime,omitempty"`
 	RefreshInterval *metav1.Duration `json:"refreshTime,omitempty"`
 }
 }
 
 
+// ExternalSecretMetadata defines metadata fields for the ExternalSecret generated by the ClusterExternalSecret.
+type ExternalSecretMetadata struct {
+	// +optional
+	Annotations map[string]string `json:"annotations,omitempty"`
+
+	// +optional
+	Labels map[string]string `json:"labels,omitempty"`
+}
+
 type ClusterExternalSecretConditionType string
 type ClusterExternalSecretConditionType string
 
 
 const (
 const (

+ 30 - 0
apis/externalsecrets/v1beta1/zz_generated.deepcopy.go

@@ -492,6 +492,7 @@ func (in *ClusterExternalSecretNamespaceFailure) DeepCopy() *ClusterExternalSecr
 func (in *ClusterExternalSecretSpec) DeepCopyInto(out *ClusterExternalSecretSpec) {
 func (in *ClusterExternalSecretSpec) DeepCopyInto(out *ClusterExternalSecretSpec) {
 	*out = *in
 	*out = *in
 	in.ExternalSecretSpec.DeepCopyInto(&out.ExternalSecretSpec)
 	in.ExternalSecretSpec.DeepCopyInto(&out.ExternalSecretSpec)
+	in.ExternalSecretMetadata.DeepCopyInto(&out.ExternalSecretMetadata)
 	in.NamespaceSelector.DeepCopyInto(&out.NamespaceSelector)
 	in.NamespaceSelector.DeepCopyInto(&out.NamespaceSelector)
 	if in.RefreshInterval != nil {
 	if in.RefreshInterval != nil {
 		in, out := &in.RefreshInterval, &out.RefreshInterval
 		in, out := &in.RefreshInterval, &out.RefreshInterval
@@ -856,6 +857,35 @@ func (in *ExternalSecretList) DeepCopyObject() runtime.Object {
 }
 }
 
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ExternalSecretMetadata) DeepCopyInto(out *ExternalSecretMetadata) {
+	*out = *in
+	if in.Annotations != nil {
+		in, out := &in.Annotations, &out.Annotations
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretMetadata.
+func (in *ExternalSecretMetadata) DeepCopy() *ExternalSecretMetadata {
+	if in == nil {
+		return nil
+	}
+	out := new(ExternalSecretMetadata)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ExternalSecretRewrite) DeepCopyInto(out *ExternalSecretRewrite) {
 func (in *ExternalSecretRewrite) DeepCopyInto(out *ExternalSecretRewrite) {
 	*out = *in
 	*out = *in
 	if in.Regexp != nil {
 	if in.Regexp != nil {

+ 12 - 0
config/crds/bases/external-secrets.io_clusterexternalsecrets.yaml

@@ -51,6 +51,18 @@ spec:
           spec:
           spec:
             description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret.
             description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret.
             properties:
             properties:
+              externalSecretMetadata:
+                description: The metadata of the external secrets to be created
+                properties:
+                  annotations:
+                    additionalProperties:
+                      type: string
+                    type: object
+                  labels:
+                    additionalProperties:
+                      type: string
+                    type: object
+                type: object
               externalSecretName:
               externalSecretName:
                 description: The name of the external secrets to be created defaults
                 description: The name of the external secrets to be created defaults
                   to the name of the ClusterExternalSecret
                   to the name of the ClusterExternalSecret

+ 12 - 0
deploy/crds/bundle.yaml

@@ -46,6 +46,18 @@ spec:
             spec:
             spec:
               description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret.
               description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret.
               properties:
               properties:
+                externalSecretMetadata:
+                  description: The metadata of the external secrets to be created
+                  properties:
+                    annotations:
+                      additionalProperties:
+                        type: string
+                      type: object
+                    labels:
+                      additionalProperties:
+                        type: string
+                      type: object
+                  type: object
                 externalSecretName:
                 externalSecretName:
                   description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret
                   description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret
                   type: string
                   type: string

+ 69 - 0
docs/api/spec.md

@@ -1160,6 +1160,20 @@ string
 </tr>
 </tr>
 <tr>
 <tr>
 <td>
 <td>
+<code>externalSecretMetadata</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretMetadata">
+ExternalSecretMetadata
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>The metadata of the external secrets to be created</p>
+</td>
+</tr>
+<tr>
+<td>
 <code>namespaceSelector</code></br>
 <code>namespaceSelector</code></br>
 <em>
 <em>
 <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#labelselector-v1-meta">
 <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#labelselector-v1-meta">
@@ -1310,6 +1324,20 @@ string
 </tr>
 </tr>
 <tr>
 <tr>
 <td>
 <td>
+<code>externalSecretMetadata</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.ExternalSecretMetadata">
+ExternalSecretMetadata
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>The metadata of the external secrets to be created</p>
+</td>
+</tr>
+<tr>
+<td>
 <code>namespaceSelector</code></br>
 <code>namespaceSelector</code></br>
 <em>
 <em>
 <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#labelselector-v1-meta">
 <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#labelselector-v1-meta">
@@ -2342,6 +2370,47 @@ ExternalSecretDecodingStrategy
 </tr>
 </tr>
 </tbody>
 </tbody>
 </table>
 </table>
+<h3 id="external-secrets.io/v1beta1.ExternalSecretMetadata">ExternalSecretMetadata
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.ClusterExternalSecretSpec">ClusterExternalSecretSpec</a>)
+</p>
+<p>
+<p>ExternalSecretMetadata defines metadata fields for the ExternalSecret generated by the ClusterExternalSecret.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>annotations</code></br>
+<em>
+map[string]string
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+</td>
+</tr>
+<tr>
+<td>
+<code>labels</code></br>
+<em>
+map[string]string
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1beta1.ExternalSecretMetadataPolicy">ExternalSecretMetadataPolicy
 <h3 id="external-secrets.io/v1beta1.ExternalSecretMetadataPolicy">ExternalSecretMetadataPolicy
 (<code>string</code> alias)</p></h3>
 (<code>string</code> alias)</p></h3>
 <p>
 <p>

+ 6 - 4
pkg/controllers/clusterexternalsecret/clusterexternalsecret_controller.go

@@ -118,7 +118,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 			continue
 			continue
 		}
 		}
 
 
-		if result, err := r.resolveExternalSecret(ctx, &clusterExternalSecret, &existingES, namespace, esName); err != nil {
+		if result, err := r.resolveExternalSecret(ctx, &clusterExternalSecret, &existingES, namespace, esName, clusterExternalSecret.Spec.ExternalSecretMetadata); err != nil {
 			log.Error(err, result)
 			log.Error(err, result)
 			failedNamespaces[namespace.Name] = result
 			failedNamespaces[namespace.Name] = result
 			continue
 			continue
@@ -139,7 +139,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 	return ctrl.Result{RequeueAfter: refreshInt}, nil
 	return ctrl.Result{RequeueAfter: refreshInt}, nil
 }
 }
 
 
-func (r *Reconciler) resolveExternalSecret(ctx context.Context, clusterExternalSecret *esv1beta1.ClusterExternalSecret, existingES *esv1beta1.ExternalSecret, namespace v1.Namespace, esName string) (string, error) {
+func (r *Reconciler) resolveExternalSecret(ctx context.Context, clusterExternalSecret *esv1beta1.ClusterExternalSecret, existingES *esv1beta1.ExternalSecret, namespace v1.Namespace, esName string, esMetadata esv1beta1.ExternalSecretMetadata) (string, error) {
 	// this means the existing ES does not belong to us
 	// this means the existing ES does not belong to us
 	if err := controllerutil.SetControllerReference(clusterExternalSecret, existingES, r.Scheme); err != nil {
 	if err := controllerutil.SetControllerReference(clusterExternalSecret, existingES, r.Scheme); err != nil {
 		return errSetCtrlReference, err
 		return errSetCtrlReference, err
@@ -147,8 +147,10 @@ func (r *Reconciler) resolveExternalSecret(ctx context.Context, clusterExternalS
 
 
 	externalSecret := esv1beta1.ExternalSecret{
 	externalSecret := esv1beta1.ExternalSecret{
 		ObjectMeta: metav1.ObjectMeta{
 		ObjectMeta: metav1.ObjectMeta{
-			Name:      esName,
-			Namespace: namespace.Name,
+			Name:        esName,
+			Namespace:   namespace.Name,
+			Labels:      esMetadata.Labels,
+			Annotations: esMetadata.Annotations,
 		},
 		},
 		Spec: clusterExternalSecret.Spec.ExternalSecretSpec,
 		Spec: clusterExternalSecret.Spec.ExternalSecretSpec,
 	}
 	}

+ 12 - 4
pkg/controllers/clusterexternalsecret/clusterexternalsecret_controller_test.go

@@ -94,10 +94,6 @@ var _ = Describe("ClusterExternalSecret controller", func() {
 		ExternalSecretName             = "test-es"
 		ExternalSecretName             = "test-es"
 		ExternalSecretStore            = "test-store"
 		ExternalSecretStore            = "test-store"
 		ExternalSecretTargetSecretName = "test-secret"
 		ExternalSecretTargetSecretName = "test-secret"
-		ClusterSecretStoreNamespace    = "css-test-ns"
-		FakeManager                    = "fake.manager"
-		FooValue                       = "map-foo-value"
-		BarValue                       = "map-bar-value"
 	)
 	)
 
 
 	var ExternalSecretNamespaceTargets = []testNamespace{
 	var ExternalSecretNamespaceTargets = []testNamespace{
@@ -203,6 +199,17 @@ var _ = Describe("ClusterExternalSecret controller", func() {
 		}
 		}
 	}
 	}
 
 
+	syncWithESMetadata := func(tc *testCase) {
+		tc.clusterExternalSecret.Spec.ExternalSecretMetadata = esv1beta1.ExternalSecretMetadata{
+			Labels:      map[string]string{"test-label-key1": "test-label-value1", "test-label-key2": "test-label-value2"},
+			Annotations: map[string]string{"test-annotation-key1": "test-annotation-value1", "test-annotation-key2": "test-annotation-value2"},
+		}
+		tc.checkExternalSecret = func(ces *esv1beta1.ClusterExternalSecret, es *esv1beta1.ExternalSecret) {
+			Expect(es.ObjectMeta.Labels).To(Equal(map[string]string{"test-label-key1": "test-label-value1", "test-label-key2": "test-label-value2"}))
+			Expect(es.ObjectMeta.Annotations).To(Equal(map[string]string{"test-annotation-key1": "test-annotation-value1", "test-annotation-key2": "test-annotation-value2"}))
+		}
+	}
+
 	doNotOverwriteExistingES := func(tc *testCase) {
 	doNotOverwriteExistingES := func(tc *testCase) {
 		tc.preTest = func() {
 		tc.preTest = func() {
 			es := &esv1beta1.ExternalSecret{
 			es := &esv1beta1.ExternalSecret{
@@ -366,6 +373,7 @@ var _ = Describe("ClusterExternalSecret controller", func() {
 		},
 		},
 
 
 		Entry("Should use cluster external secret name if external secret name isn't defined", syncWithoutESName),
 		Entry("Should use cluster external secret name if external secret name isn't defined", syncWithoutESName),
+		Entry("Should set external secret metadata if the field is set", syncWithESMetadata),
 		Entry("Should not overwrite existing external secrets and error out if one is present", doNotOverwriteExistingES),
 		Entry("Should not overwrite existing external secrets and error out if one is present", doNotOverwriteExistingES),
 		Entry("Should have list of all provisioned namespaces", populatedProvisionedNamespaces),
 		Entry("Should have list of all provisioned namespaces", populatedProvisionedNamespaces),
 		Entry("Should delete external secrets when namespaces no longer match", deleteESInNonMatchingNS),
 		Entry("Should delete external secrets when namespaces no longer match", deleteESInNonMatchingNS),