Explorar o código

Changes to PushSecret Definition.
Adds tests, adds labelSelector

Signed-off-by: Gustavo <gusfcarvalho@gmail.com>

Gustavo %!s(int64=3) %!d(string=hai) anos
pai
achega
6758c92979

+ 20 - 8
apis/externalsecrets/v1alpha1/pushsecret_types.go

@@ -25,9 +25,12 @@ const (
 )
 
 type PushSecretStoreRef struct {
-	// Name of the SecretStore resource
+	// Optionally, sync to the SecretStore of the given name
+	// +optional
 	Name string `json:"name"`
-
+	// Optionally, sync to secret stores with label selector
+	// +optional
+	LabelSelector *metav1.LabelSelector `json:"labelSelector"`
 	// Kind of the SecretStore resource (SecretStore or ClusterSecretStore)
 	// Defaults to `SecretStore`
 	// +optional
@@ -36,34 +39,43 @@ type PushSecretStoreRef struct {
 
 // PushSecretSpec configures the behavior of the PushSecret.
 type PushSecretSpec struct {
+	// The Interval to which External Secrets will try to push a secret definition
 	RefreshInterval *metav1.Duration     `json:"refreshInterval,omitempty"`
 	SecretStoreRefs []PushSecretStoreRef `json:"secretStoreRefs"`
-	Selector        PushSecretSelector   `json:"selector"`
-	Data            []PushSecretData     `json:"data,omitempty"`
+	// The Secret Selector (k8s source) for the Push Secret
+	Selector PushSecretSelector `json:"selector"`
+	// Secret Data that should be pushed to providers
+	Data []PushSecretData `json:"data,omitempty"`
 }
 
 type PushSecretSecret struct {
+	// Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest.
 	Name string `json:"name"`
 }
 
 type PushSecretSelector struct {
+	// Select a Secret to Push.
 	Secret PushSecretSecret `json:"secret"`
 }
 
-type PushSecretRemoteRefs struct {
+type PushSecretRemoteRef struct {
+	// Name of the resulting provider secret.
 	RemoteKey string `json:"remoteKey"`
 }
 
-func (r PushSecretRemoteRefs) GetRemoteKey() string {
+func (r PushSecretRemoteRef) GetRemoteKey() string {
 	return r.RemoteKey
 }
 
 type PushSecretMatch struct {
-	SecretKey  string                 `json:"secretKey"`
-	RemoteRefs []PushSecretRemoteRefs `json:"remoteRefs"`
+	// Secret Key to be pushed
+	SecretKey string `json:"secretKey"`
+	// Remote Refs to push to providers.
+	RemoteRef PushSecretRemoteRef `json:"remoteRef"`
 }
 
 type PushSecretData struct {
+	// Match a given Secret Key to be pushed to the provider.
 	Match PushSecretMatch `json:"match"`
 }
 

+ 15 - 14
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -1024,7 +1024,7 @@ func (in *PushSecret) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PushSecretData) DeepCopyInto(out *PushSecretData) {
 	*out = *in
-	in.Match.DeepCopyInto(&out.Match)
+	out.Match = in.Match
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretData.
@@ -1072,11 +1072,7 @@ func (in *PushSecretList) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PushSecretMatch) DeepCopyInto(out *PushSecretMatch) {
 	*out = *in
-	if in.RemoteRefs != nil {
-		in, out := &in.RemoteRefs, &out.RemoteRefs
-		*out = make([]PushSecretRemoteRefs, len(*in))
-		copy(*out, *in)
-	}
+	out.RemoteRef = in.RemoteRef
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretMatch.
@@ -1090,16 +1086,16 @@ func (in *PushSecretMatch) DeepCopy() *PushSecretMatch {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *PushSecretRemoteRefs) DeepCopyInto(out *PushSecretRemoteRefs) {
+func (in *PushSecretRemoteRef) DeepCopyInto(out *PushSecretRemoteRef) {
 	*out = *in
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretRemoteRefs.
-func (in *PushSecretRemoteRefs) DeepCopy() *PushSecretRemoteRefs {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretRemoteRef.
+func (in *PushSecretRemoteRef) DeepCopy() *PushSecretRemoteRef {
 	if in == nil {
 		return nil
 	}
-	out := new(PushSecretRemoteRefs)
+	out := new(PushSecretRemoteRef)
 	in.DeepCopyInto(out)
 	return out
 }
@@ -1146,15 +1142,15 @@ func (in *PushSecretSpec) DeepCopyInto(out *PushSecretSpec) {
 	if in.SecretStoreRefs != nil {
 		in, out := &in.SecretStoreRefs, &out.SecretStoreRefs
 		*out = make([]PushSecretStoreRef, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	out.Selector = in.Selector
 	if in.Data != nil {
 		in, out := &in.Data, &out.Data
 		*out = make([]PushSecretData, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
+		copy(*out, *in)
 	}
 }
 
@@ -1210,6 +1206,11 @@ func (in *PushSecretStatusCondition) DeepCopy() *PushSecretStatusCondition {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PushSecretStoreRef) DeepCopyInto(out *PushSecretStoreRef) {
 	*out = *in
+	if in.LabelSelector != nil {
+		in, out := &in.LabelSelector, &out.LabelSelector
+		*out = new(v1.LabelSelector)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretStoreRef.

+ 66 - 13
config/crds/bases/external-secrets.io_pushsecrets.yaml

@@ -43,23 +43,26 @@ spec:
             description: PushSecretSpec configures the behavior of the PushSecret.
             properties:
               data:
+                description: Secret Data that should be pushed to providers
                 items:
                   properties:
                     match:
+                      description: Match a given Secret Key to be pushed to the provider.
                       properties:
-                        remoteRefs:
-                          items:
-                            properties:
-                              remoteKey:
-                                type: string
-                            required:
-                            - remoteKey
-                            type: object
-                          type: array
+                        remoteRef:
+                          description: Remote Refs to push to providers.
+                          properties:
+                            remoteKey:
+                              description: Name of the resulting provider secret.
+                              type: string
+                          required:
+                          - remoteKey
+                          type: object
                         secretKey:
+                          description: Secret Key to be pushed
                           type: string
                       required:
-                      - remoteRefs
+                      - remoteRef
                       - secretKey
                       type: object
                   required:
@@ -67,6 +70,8 @@ spec:
                   type: object
                 type: array
               refreshInterval:
+                description: The Interval to which External Secrets will try to push
+                  a secret definition
                 type: string
               secretStoreRefs:
                 items:
@@ -75,18 +80,66 @@ spec:
                       description: Kind of the SecretStore resource (SecretStore or
                         ClusterSecretStore) Defaults to `SecretStore`
                       type: string
+                    labelSelector:
+                      description: Optionally, sync to secret stores with label selector
+                      properties:
+                        matchExpressions:
+                          description: matchExpressions is a list of label selector
+                            requirements. The requirements are ANDed.
+                          items:
+                            description: A label selector requirement is a selector
+                              that contains values, a key, and an operator that relates
+                              the key and values.
+                            properties:
+                              key:
+                                description: key is the label key that the selector
+                                  applies to.
+                                type: string
+                              operator:
+                                description: operator represents a key's relationship
+                                  to a set of values. Valid operators are In, NotIn,
+                                  Exists and DoesNotExist.
+                                type: string
+                              values:
+                                description: values is an array of string values.
+                                  If the operator is In or NotIn, the values array
+                                  must be non-empty. If the operator is Exists or
+                                  DoesNotExist, the values array must be empty. This
+                                  array is replaced during a strategic merge patch.
+                                items:
+                                  type: string
+                                type: array
+                            required:
+                            - key
+                            - operator
+                            type: object
+                          type: array
+                        matchLabels:
+                          additionalProperties:
+                            type: string
+                          description: matchLabels is a map of {key,value} pairs.
+                            A single {key,value} in the matchLabels map is equivalent
+                            to an element of matchExpressions, whose key field is
+                            "key", the operator is "In", and the values array contains
+                            only "value". The requirements are ANDed.
+                          type: object
+                      type: object
+                      x-kubernetes-map-type: atomic
                     name:
-                      description: Name of the SecretStore resource
+                      description: Optionally, sync to the SecretStore of the given
+                        name
                       type: string
-                  required:
-                  - name
                   type: object
                 type: array
               selector:
+                description: The Secret Selector (k8s source) for the Push Secret
                 properties:
                   secret:
+                    description: Select a Secret to Push.
                     properties:
                       name:
+                        description: Name of the Secret. The Secret must exist in
+                          the same namespace as the PushSecret manifest.
                         type: string
                     required:
                     - name

+ 49 - 13
deploy/crds/bundle.yaml

@@ -3294,23 +3294,26 @@ spec:
               description: PushSecretSpec configures the behavior of the PushSecret.
               properties:
                 data:
+                  description: Secret Data that should be pushed to providers
                   items:
                     properties:
                       match:
+                        description: Match a given Secret Key to be pushed to the provider.
                         properties:
-                          remoteRefs:
-                            items:
-                              properties:
-                                remoteKey:
-                                  type: string
-                              required:
-                                - remoteKey
-                              type: object
-                            type: array
+                          remoteRef:
+                            description: Remote Refs to push to providers.
+                            properties:
+                              remoteKey:
+                                description: Name of the resulting provider secret.
+                                type: string
+                            required:
+                              - remoteKey
+                            type: object
                           secretKey:
+                            description: Secret Key to be pushed
                             type: string
                         required:
-                          - remoteRefs
+                          - remoteRef
                           - secretKey
                         type: object
                     required:
@@ -3318,6 +3321,7 @@ spec:
                     type: object
                   type: array
                 refreshInterval:
+                  description: The Interval to which External Secrets will try to push a secret definition
                   type: string
                 secretStoreRefs:
                   items:
@@ -3325,18 +3329,50 @@ spec:
                       kind:
                         description: Kind of the SecretStore resource (SecretStore or ClusterSecretStore) Defaults to `SecretStore`
                         type: string
+                      labelSelector:
+                        description: Optionally, sync to secret stores with label selector
+                        properties:
+                          matchExpressions:
+                            description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+                            items:
+                              description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.
+                              properties:
+                                key:
+                                  description: key is the label key that the selector applies to.
+                                  type: string
+                                operator:
+                                  description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
+                                  type: string
+                                values:
+                                  description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
+                                  items:
+                                    type: string
+                                  type: array
+                              required:
+                                - key
+                                - operator
+                              type: object
+                            type: array
+                          matchLabels:
+                            additionalProperties:
+                              type: string
+                            description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
+                            type: object
+                        type: object
+                        x-kubernetes-map-type: atomic
                       name:
-                        description: Name of the SecretStore resource
+                        description: Optionally, sync to the SecretStore of the given name
                         type: string
-                    required:
-                      - name
                     type: object
                   type: array
                 selector:
+                  description: The Secret Selector (k8s source) for the Push Secret
                   properties:
                     secret:
+                      description: Select a Secret to Push.
                       properties:
                         name:
+                          description: Name of the Secret. The Secret must exist in the same namespace as the PushSecret manifest.
                           type: string
                       required:
                         - name

+ 1 - 1
design/002-pushsecret.md

@@ -24,7 +24,7 @@ The Secret Sink is a feature to allow Secrets from Kubernetes to be saved back i
 Secret Sink allows some inCluster generated secrets to also be available on a given secret provider. It also allows multiple Providers having the same secret (which means a way to perform failover in case a given secret provider is on downtime or compromised for whatever the reason).
 
 ### Goals
-- CRD Design for the PushSecret
+- CRD Design for the SecretSink
 - Define the need for a SinkStore
 -
 ### Non-Goals

+ 47 - 23
pkg/controllers/pushsecret/pushsecret_controller.go

@@ -93,7 +93,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 		r.recorder.Event(&ps, v1.EventTypeWarning, esapi.ReasonErrored, err.Error())
 		return ctrl.Result{}, err
 	}
-	err = r.SetSecretToProviders(ctx, secretStores, ps, secret)
+	err = r.PushSecretToProviders(ctx, secretStores, ps, secret)
 	if err != nil {
 		msg := fmt.Sprintf(errFailedSetSecret, err)
 		cond := NewPushSecretCondition(esapi.PushSecretReady, v1.ConditionFalse, esapi.ReasonErrored, msg)
@@ -109,7 +109,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 	return ctrl.Result{RequeueAfter: refreshInt}, nil
 }
 
-func (r *Reconciler) SetSecretToProviders(ctx context.Context, stores []v1beta1.GenericStore, ps esapi.PushSecret, secret *v1.Secret) error {
+func (r *Reconciler) PushSecretToProviders(ctx context.Context, stores []v1beta1.GenericStore, ps esapi.PushSecret, secret *v1.Secret) error {
 	for _, store := range stores {
 		provider, err := v1beta1.GetProvider(store)
 		if err != nil {
@@ -130,11 +130,9 @@ func (r *Reconciler) SetSecretToProviders(ctx context.Context, stores []v1beta1.
 			if !ok {
 				return fmt.Errorf("secret key %v does not exist", ref.Match.SecretKey)
 			}
-			for _, rK := range ref.Match.RemoteRefs {
-				err := client.SetSecret(ctx, secretValue, rK)
-				if err != nil {
-					return fmt.Errorf(errSetSecretFailed, ref.Match.SecretKey, store.GetName(), err)
-				}
+			err := client.SetSecret(ctx, secretValue, ref.Match.RemoteRef)
+			if err != nil {
+				return fmt.Errorf(errSetSecretFailed, ref.Match.SecretKey, store.GetName(), err)
 			}
 		}
 	}
@@ -154,26 +152,52 @@ func (r *Reconciler) GetSecret(ctx context.Context, ps esapi.PushSecret) (*v1.Se
 func (r *Reconciler) GetSecretStores(ctx context.Context, ps esapi.PushSecret) ([]v1beta1.GenericStore, error) {
 	stores := make([]v1beta1.GenericStore, 0)
 	for _, refStore := range ps.Spec.SecretStoreRefs {
-		ref := types.NamespacedName{
-			Name: refStore.Name,
-		}
-
-		if refStore.Kind == v1beta1.ClusterSecretStoreKind {
-			var store v1beta1.ClusterSecretStore
-			err := r.Get(ctx, ref, &store)
+		if refStore.LabelSelector != nil {
+			labelSelector, err := metav1.LabelSelectorAsSelector(refStore.LabelSelector)
 			if err != nil {
-				return nil, fmt.Errorf(errGetClusterSecretStore, ref.Name, err)
+				return nil, fmt.Errorf("could not convert labels: %w", err)
 			}
-			stores = append(stores, &store)
-		} else {
-			ref.Namespace = ps.Namespace
+			if refStore.Kind == v1beta1.ClusterSecretStoreKind {
+				clusterSecretStoreList := v1beta1.ClusterSecretStoreList{}
+				err = r.List(ctx, &clusterSecretStoreList, &client.ListOptions{LabelSelector: labelSelector})
+				if err != nil {
+					return nil, fmt.Errorf("could not list cluster Secret Stores: %w", err)
+				}
+				for i := range clusterSecretStoreList.Items {
+					stores = append(stores, &clusterSecretStoreList.Items[i])
+				}
+			} else {
+				secretStoreList := v1beta1.SecretStoreList{}
+				err = r.List(ctx, &secretStoreList, &client.ListOptions{LabelSelector: labelSelector})
+				if err != nil {
+					return nil, fmt.Errorf("could not list Secret Stores: %w", err)
+				}
+				for i := range secretStoreList.Items {
+					stores = append(stores, &secretStoreList.Items[i])
+				}
+			}
+		}
+		if refStore.Name != "" {
+			ref := types.NamespacedName{
+				Name: refStore.Name,
+			}
+			if refStore.Kind == v1beta1.ClusterSecretStoreKind {
+				var store v1beta1.ClusterSecretStore
+				err := r.Get(ctx, ref, &store)
+				if err != nil {
+					return nil, fmt.Errorf(errGetClusterSecretStore, ref.Name, err)
+				}
+				stores = append(stores, &store)
+			} else {
+				ref.Namespace = ps.Namespace
 
-			var store v1beta1.SecretStore
-			err := r.Get(ctx, ref, &store)
-			if err != nil {
-				return nil, fmt.Errorf(errGetSecretStore, ref.Name, err)
+				var store v1beta1.SecretStore
+				err := r.Get(ctx, ref, &store)
+				if err != nil {
+					return nil, fmt.Errorf(errGetSecretStore, ref.Name, err)
+				}
+				stores = append(stores, &store)
 			}
-			stores = append(stores, &store)
 		}
 	}
 	return stores, nil

+ 142 - 6
pkg/controllers/pushsecret/pushsecret_controller_test.go

@@ -111,6 +111,11 @@ var _ = Describe("ExternalSecret controller", func() {
 				Namespace: PushSecretNamespace,
 			},
 		})
+		k8sClient.Delete(context.Background(), &v1beta1.ClusterSecretStore{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: PushSecretStore,
+			},
+		})
 		k8sClient.Delete(context.Background(), &v1.Secret{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      SecretName,
@@ -142,10 +147,8 @@ var _ = Describe("ExternalSecret controller", func() {
 						{
 							Match: v1alpha1.PushSecretMatch{
 								SecretKey: "key",
-								RemoteRefs: []v1alpha1.PushSecretRemoteRefs{
-									{
-										RemoteKey: "path/to/key",
-									},
+								RemoteRef: v1alpha1.PushSecretRemoteRef{
+									RemoteKey: "path/to/key",
 								},
 							},
 						},
@@ -184,7 +187,73 @@ var _ = Describe("ExternalSecret controller", func() {
 		}
 		tc.assert = func(ps *v1alpha1.PushSecret, secret *v1.Secret) bool {
 			secretValue := secret.Data["key"]
-			providerValue := fakeProvider.SetSecretArgs[ps.Spec.Data[0].Match.RemoteRefs[0].RemoteKey].Value
+			providerValue := fakeProvider.SetSecretArgs[ps.Spec.Data[0].Match.RemoteRef.RemoteKey].Value
+			expected := v1alpha1.PushSecretStatusCondition{
+				Type:    v1alpha1.PushSecretReady,
+				Status:  v1.ConditionTrue,
+				Reason:  v1alpha1.ReasonSynced,
+				Message: "PushSecret synced successfully",
+			}
+			return bytes.Equal(secretValue, providerValue) && checkCondition(ps.Status, expected)
+		}
+	}
+	// if target Secret name is not specified it should use the ExternalSecret name.
+	syncMatchingLabels := func(tc *testCase) {
+		fakeProvider.SetSecretFn = func() error {
+			return nil
+		}
+		tc.pushsecret = &v1alpha1.PushSecret{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      PushSecretName,
+				Namespace: PushSecretNamespace,
+			},
+			Spec: v1alpha1.PushSecretSpec{
+				SecretStoreRefs: []v1alpha1.PushSecretStoreRef{
+					{
+						LabelSelector: &metav1.LabelSelector{
+							MatchLabels: map[string]string{
+								"foo": "bar",
+							},
+						},
+						Kind: "SecretStore",
+					},
+				},
+				Selector: v1alpha1.PushSecretSelector{
+					Secret: v1alpha1.PushSecretSecret{
+						Name: SecretName,
+					},
+				},
+				Data: []v1alpha1.PushSecretData{
+					{
+						Match: v1alpha1.PushSecretMatch{
+							SecretKey: "key",
+							RemoteRef: v1alpha1.PushSecretRemoteRef{
+								RemoteKey: "path/to/key",
+							},
+						},
+					},
+				},
+			},
+		}
+		tc.store = &v1beta1.SecretStore{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      PushSecretStore,
+				Namespace: PushSecretNamespace,
+				Labels: map[string]string{
+					"foo": "bar",
+				},
+			},
+			Spec: v1beta1.SecretStoreSpec{
+				Provider: &v1beta1.SecretStoreProvider{
+					Fake: &v1beta1.FakeProvider{
+						Data: []v1beta1.FakeProviderData{},
+					},
+				},
+			},
+		}
+		tc.assert = func(ps *v1alpha1.PushSecret, secret *v1.Secret) bool {
+			secretValue := secret.Data["key"]
+			providerValue := fakeProvider.SetSecretArgs[ps.Spec.Data[0].Match.RemoteRef.RemoteKey].Value
 			expected := v1alpha1.PushSecretStatusCondition{
 				Type:    v1alpha1.PushSecretReady,
 				Status:  v1.ConditionTrue,
@@ -213,7 +282,72 @@ var _ = Describe("ExternalSecret controller", func() {
 		tc.pushsecret.Spec.SecretStoreRefs[0].Kind = "ClusterSecretStore"
 		tc.assert = func(ps *v1alpha1.PushSecret, secret *v1.Secret) bool {
 			secretValue := secret.Data["key"]
-			providerValue := fakeProvider.SetSecretArgs[ps.Spec.Data[0].Match.RemoteRefs[0].RemoteKey].Value
+			providerValue := fakeProvider.SetSecretArgs[ps.Spec.Data[0].Match.RemoteRef.RemoteKey].Value
+			expected := v1alpha1.PushSecretStatusCondition{
+				Type:    v1alpha1.PushSecretReady,
+				Status:  v1.ConditionTrue,
+				Reason:  v1alpha1.ReasonSynced,
+				Message: "PushSecret synced successfully",
+			}
+			return bytes.Equal(secretValue, providerValue) && checkCondition(ps.Status, expected)
+		}
+	}
+	// if target Secret name is not specified it should use the ExternalSecret name.
+	syncWithClusterStoreMatchingLabels := func(tc *testCase) {
+		fakeProvider.SetSecretFn = func() error {
+			return nil
+		}
+		tc.pushsecret = &v1alpha1.PushSecret{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      PushSecretName,
+				Namespace: PushSecretNamespace,
+			},
+			Spec: v1alpha1.PushSecretSpec{
+				SecretStoreRefs: []v1alpha1.PushSecretStoreRef{
+					{
+						LabelSelector: &metav1.LabelSelector{
+							MatchLabels: map[string]string{
+								"foo": "bar",
+							},
+						},
+						Kind: "ClusterSecretStore",
+					},
+				},
+				Selector: v1alpha1.PushSecretSelector{
+					Secret: v1alpha1.PushSecretSecret{
+						Name: SecretName,
+					},
+				},
+				Data: []v1alpha1.PushSecretData{
+					{
+						Match: v1alpha1.PushSecretMatch{
+							SecretKey: "key",
+							RemoteRef: v1alpha1.PushSecretRemoteRef{
+								RemoteKey: "path/to/key",
+							},
+						},
+					},
+				},
+			},
+		}
+		tc.store = &v1beta1.ClusterSecretStore{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: PushSecretStore,
+				Labels: map[string]string{
+					"foo": "bar",
+				},
+			},
+			Spec: v1beta1.SecretStoreSpec{
+				Provider: &v1beta1.SecretStoreProvider{
+					Fake: &v1beta1.FakeProvider{
+						Data: []v1beta1.FakeProviderData{},
+					},
+				},
+			},
+		}
+		tc.assert = func(ps *v1alpha1.PushSecret, secret *v1.Secret) bool {
+			secretValue := secret.Data["key"]
+			providerValue := fakeProvider.SetSecretArgs[ps.Spec.Data[0].Match.RemoteRef.RemoteKey].Value
 			expected := v1alpha1.PushSecretStatusCondition{
 				Type:    v1alpha1.PushSecretReady,
 				Status:  v1.ConditionTrue,
@@ -349,7 +483,9 @@ var _ = Describe("ExternalSecret controller", func() {
 			// this must be optional so we can test faulty es configuration
 		},
 		Entry("should sync", syncSuccessfully),
+		Entry("should sync to stores matching labels", syncMatchingLabels),
 		Entry("should sync with ClusterStore", syncWithClusterStore),
+		Entry("should sync with ClusterStore matching labels", syncWithClusterStoreMatchingLabels),
 		Entry("should fail if Secret is not created", failNoSecret),
 		Entry("should fail if Secret Key does not exist", failNoSecretKey),
 		Entry("should fail if SetSecret fails", setSecretFail),

+ 1 - 1
pkg/provider/fake/fake_test.go

@@ -198,7 +198,7 @@ func TestSetSecret(t *testing.T) {
 				},
 			}, nil, "")
 			gomega.Expect(err).ToNot(gomega.HaveOccurred())
-			err = cl.SetSecret(context.TODO(), []byte(row.expValue), esv1alpha1.PushSecretRemoteRefs{
+			err = cl.SetSecret(context.TODO(), []byte(row.expValue), esv1alpha1.PushSecretRemoteRef{
 				RemoteKey: row.requestKey,
 			})
 			if row.expErr != "" {

+ 0 - 1
pkg/provider/gcp/secretmanager/client.go

@@ -85,7 +85,6 @@ type GoogleSecretManagerClient interface {
 var log = ctrl.Log.WithName("provider").WithName("gcp").WithName("secretsmanager")
 
 // SetSecret pushes a kubernetes secret key into gcp provider Secret.
-// funcName(variable type_of_variable, ...)
 func (c *Client) SetSecret(ctx context.Context, payload []byte, remoteRef esv1beta1.PushRemoteRef) error {
 	createSecretReq := &secretmanagerpb.CreateSecretRequest{
 		Parent:   fmt.Sprintf("projects/%s", c.store.ProjectID),