Просмотр исходного кода

Merge branch 'beach-team' of github.com:external-secrets/external-secrets into beach-team

Signed-off-by: Gustavo Carvalho <gusfcarvalho@gmail.com>
Gustavo Carvalho 3 лет назад
Родитель
Сommit
6cbb58de59

+ 3 - 4
apis/externalsecrets/v1alpha1/pushsecret_types.go

@@ -20,9 +20,8 @@ import (
 )
 )
 
 
 const (
 const (
-	ReasonSynced    = "Synced"
-	ReasonNotSynced = "NotSynced"
-	ReasonErrored   = "Errored"
+	ReasonSynced  = "Synced"
+	ReasonErrored = "Errored"
 )
 )
 
 
 type PushSecretStoreRef struct {
 type PushSecretStoreRef struct {
@@ -65,7 +64,7 @@ type PushSecretMatch struct {
 }
 }
 
 
 type PushSecretData struct {
 type PushSecretData struct {
-	Match []PushSecretMatch `json:"match"`
+	Match PushSecretMatch `json:"match"`
 }
 }
 
 
 // PushSecretConditionType indicates the condition of the PushSecret.
 // PushSecretConditionType indicates the condition of the PushSecret.

+ 1 - 7
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -994,13 +994,7 @@ func (in *PushSecret) 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 *PushSecretData) DeepCopyInto(out *PushSecretData) {
 func (in *PushSecretData) DeepCopyInto(out *PushSecretData) {
 	*out = *in
 	*out = *in
-	if in.Match != nil {
-		in, out := &in.Match, &out.Match
-		*out = make([]PushSecretMatch, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
+	in.Match.DeepCopyInto(&out.Match)
 }
 }
 
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretData.
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSecretData.

+ 1 - 0
config/crds/bases/external-secrets.io_clustersecretstores.yaml

@@ -1392,6 +1392,7 @@ spec:
       type: string
       type: string
     - jsonPath: .status.capabilities
     - jsonPath: .status.capabilities
       name: Capabilities
       name: Capabilities
+      type: string
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       name: Ready
       type: string
       type: string

+ 17 - 19
config/crds/bases/external-secrets.io_pushsecrets.yaml

@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: pushsecrets.external-secrets.io
   name: pushsecrets.external-secrets.io
 spec:
 spec:
@@ -46,24 +46,22 @@ spec:
                 items:
                 items:
                   properties:
                   properties:
                     match:
                     match:
-                      items:
-                        properties:
-                          remoteRefs:
-                            items:
-                              properties:
-                                remoteKey:
-                                  type: string
-                              required:
-                              - remoteKey
-                              type: object
-                            type: array
-                          secretKey:
-                            type: string
-                        required:
-                        - remoteRefs
-                        - secretKey
-                        type: object
-                      type: array
+                      properties:
+                        remoteRefs:
+                          items:
+                            properties:
+                              remoteKey:
+                                type: string
+                            required:
+                            - remoteKey
+                            type: object
+                          type: array
+                        secretKey:
+                          type: string
+                      required:
+                      - remoteRefs
+                      - secretKey
+                      type: object
                   required:
                   required:
                   - match
                   - match
                   type: object
                   type: object

+ 1 - 0
config/crds/bases/external-secrets.io_secretstores.yaml

@@ -1392,6 +1392,7 @@ spec:
       type: string
       type: string
     - jsonPath: .status.capabilities
     - jsonPath: .status.capabilities
       name: Capabilities
       name: Capabilities
+      type: string
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
     - jsonPath: .status.conditions[?(@.type=="Ready")].status
       name: Ready
       name: Ready
       type: string
       type: string

+ 21 - 19
deploy/crds/bundle.yaml

@@ -1407,6 +1407,9 @@ spec:
         - jsonPath: .status.conditions[?(@.type=="Ready")].reason
         - jsonPath: .status.conditions[?(@.type=="Ready")].reason
           name: Status
           name: Status
           type: string
           type: string
+        - jsonPath: .status.capabilities
+          name: Capabilities
+          type: string
         - jsonPath: .status.conditions[?(@.type=="Ready")].status
         - jsonPath: .status.conditions[?(@.type=="Ready")].status
           name: Ready
           name: Ready
           type: string
           type: string
@@ -3143,24 +3146,22 @@ spec:
                   items:
                   items:
                     properties:
                     properties:
                       match:
                       match:
-                        items:
-                          properties:
-                            remoteRefs:
-                              items:
-                                properties:
-                                  remoteKey:
-                                    type: string
-                                required:
-                                  - remoteKey
-                                type: object
-                              type: array
-                            secretKey:
-                              type: string
-                          required:
-                            - remoteRefs
-                            - secretKey
-                          type: object
-                        type: array
+                        properties:
+                          remoteRefs:
+                            items:
+                              properties:
+                                remoteKey:
+                                  type: string
+                              required:
+                                - remoteKey
+                              type: object
+                            type: array
+                          secretKey:
+                            type: string
+                        required:
+                          - remoteRefs
+                          - secretKey
+                        type: object
                     required:
                     required:
                       - match
                       - match
                     type: object
                     type: object
@@ -3249,7 +3250,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 kind: CustomResourceDefinition
 metadata:
 metadata:
   annotations:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.0
+    controller-gen.kubebuilder.io/version: v0.9.2
   creationTimestamp: null
   creationTimestamp: null
   name: secretstores.external-secrets.io
   name: secretstores.external-secrets.io
 spec:
 spec:
@@ -4278,6 +4279,7 @@ spec:
           type: string
           type: string
         - jsonPath: .status.capabilities
         - jsonPath: .status.capabilities
           name: Capabilities
           name: Capabilities
+          type: string
         - jsonPath: .status.conditions[?(@.type=="Ready")].status
         - jsonPath: .status.conditions[?(@.type=="Ready")].status
           name: Ready
           name: Ready
           type: string
           type: string

+ 8 - 8
design/002-secretsink.md → design/002-pushsecret.md

@@ -2,7 +2,7 @@
 ---
 ---
 title: PushSecret
 title: PushSecret
 version: v1alpha1
 version: v1alpha1
-authors: 
+authors:
 creation-date: 2022-01-25
 creation-date: 2022-01-25
 status: draft
 status: draft
 ---
 ---
@@ -26,7 +26,7 @@ Secret Sink allows some inCluster generated secrets to also be available on a gi
 ### Goals
 ### Goals
 - CRD Design for the PushSecret
 - CRD Design for the PushSecret
 - Define the need for a SinkStore
 - Define the need for a SinkStore
-- 
+-
 ### Non-Goals
 ### Non-Goals
 Do not implement full compatibility mechanisms with each provider (we are not Terraform neither Crossplane)
 Do not implement full compatibility mechanisms with each provider (we are not Terraform neither Crossplane)
 
 
@@ -130,17 +130,17 @@ spec:
     secret:
     secret:
       name: foobar
       name: foobar
   data:
   data:
-    match:
-    - secretKey: foobar
+  - match:
+      secretKey: foobar
       remoteRefs:
       remoteRefs:
-      - remoteKey: my/path/foobar 
+      - remoteKey: my/path/foobar
         property: my-property #optional. To allow coming back from a 'dataFrom'
         property: my-property #optional. To allow coming back from a 'dataFrom'
       - remoteKey: secret/my-path-foobar
       - remoteKey: secret/my-path-foobar
         property: another-property
         property: another-property
     rewrite:
     rewrite:
-    - secretKey: game-(.+).(.+)
+      secretKey: game-(.+).(.+)
       remoteRefs:
       remoteRefs:
-      - remoteKey: my/path/($1) 
+      - remoteKey: my/path/($1)
         property: prop-($2)
         property: prop-($2)
       - remoteKey: my-path-($1)-($2) #Applies this way to all other secretStores
       - remoteKey: my-path-($1)-($2) #Applies this way to all other secretStores
 
 
@@ -148,7 +148,7 @@ status:
   refreshTime: "2019-08-12T12:33:02Z"
   refreshTime: "2019-08-12T12:33:02Z"
   conditions:
   conditions:
   - type: Ready
   - type: Ready
-    status: "True" 
+    status: "True"
     reason: "SecretSynced"
     reason: "SecretSynced"
     message: "Secret was synced" #Fully synced
     message: "Secret was synced" #Fully synced
     lastTransitionTime: "2019-08-12T12:33:02Z"
     lastTransitionTime: "2019-08-12T12:33:02Z"

+ 3 - 3
e2e/framework/addon/eso.go

@@ -17,7 +17,7 @@ import (
 	"os"
 	"os"
 
 
 	// nolint
 	// nolint
-	ginkgo "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/ginkgo/v2"
 )
 )
 
 
 type ESO struct {
 type ESO struct {
@@ -155,7 +155,7 @@ func WithCRDs() MutationFunc {
 }
 }
 
 
 func (l *ESO) Install() error {
 func (l *ESO) Install() error {
-	ginkgo.By("Installing eso\n")
+	By("Installing eso\n")
 	err := l.HelmChart.Install()
 	err := l.HelmChart.Install()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -165,7 +165,7 @@ func (l *ESO) Install() error {
 }
 }
 
 
 func (l *ESO) Uninstall() error {
 func (l *ESO) Uninstall() error {
-	ginkgo.By("Uninstalling eso")
+	By("Uninstalling eso")
 	err := l.HelmChart.Uninstall()
 	err := l.HelmChart.Uninstall()
 	if err != nil {
 	if err != nil {
 		return err
 		return err

+ 1 - 1
go.mod

@@ -91,7 +91,7 @@ require (
 	k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
 	k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
 	sigs.k8s.io/controller-runtime v0.11.2
 	sigs.k8s.io/controller-runtime v0.11.2
 	sigs.k8s.io/controller-tools v0.9.2
 	sigs.k8s.io/controller-tools v0.9.2
-	software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78
+	software.sslmate.com/src/go-pkcs12 v0.2.0
 )
 )
 
 
 require github.com/1Password/connect-sdk-go v1.5.0
 require github.com/1Password/connect-sdk-go v1.5.0

+ 8 - 10
pkg/controllers/pushsecret/pushsecret_controller.go

@@ -134,16 +134,14 @@ func (r *Reconciler) SetSecretToProviders(ctx context.Context, stores []v1beta1.
 			}
 			}
 		}()
 		}()
 		for _, ref := range ps.Spec.Data {
 		for _, ref := range ps.Spec.Data {
-			for _, match := range ref.Match {
-				secretValue, ok := secret.Data[match.SecretKey]
-				if !ok {
-					return fmt.Errorf("secret key %v does not exist", match.SecretKey)
-				}
-				for _, rK := range match.RemoteRefs {
-					err := client.SetSecret(ctx, secretValue, rK)
-					if err != nil {
-						return fmt.Errorf(errSetSecretFailed, match.SecretKey, store.GetName(), err)
-					}
+			secretValue, ok := secret.Data[ref.Match.SecretKey]
+			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)
 				}
 				}
 			}
 			}
 		}
 		}

+ 5 - 7
pkg/controllers/pushsecret/pushsecret_controller_test.go

@@ -361,13 +361,11 @@ var _ = Describe("pushsecret", func() {
 				},
 				},
 				Data: []esapi.PushSecretData{
 				Data: []esapi.PushSecretData{
 					{
 					{
-						Match: []esapi.PushSecretMatch{
-							{
-								SecretKey: "foo",
-								RemoteRefs: []esapi.PushSecretRemoteRefs{
-									{
-										RemoteKey: "bar",
-									},
+						Match: esapi.PushSecretMatch{
+							SecretKey: "foo",
+							RemoteRefs: []esapi.PushSecretRemoteRefs{
+								{
+									RemoteKey: "bar",
 								},
 								},
 							},
 							},
 						},
 						},

+ 1 - 1
pkg/provider/aws/secretsmanager/fake/fake.go

@@ -38,7 +38,7 @@ func NewClient() *Client {
 
 
 func (sm *Client) CreateSecretWithContext(aws.Context, *awssm.CreateSecretInput, ...request.Option) (*awssm.CreateSecretOutput, error) {
 func (sm *Client) CreateSecretWithContext(aws.Context, *awssm.CreateSecretInput, ...request.Option) (*awssm.CreateSecretOutput, error) {
 	value := "I'm a key"
 	value := "I'm a key"
-	output := awssm.CreateSecretOutput {
+	output := awssm.CreateSecretOutput{
 		Name: &value,
 		Name: &value,
 	}
 	}
 	return &output, nil
 	return &output, nil

+ 46 - 1
pkg/provider/gcp/secretmanager/fake/fake.go

@@ -31,16 +31,49 @@ type MockSMClient struct {
 	addSecretFn    func(ctx context.Context, req *secretmanagerpb.AddSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)
 	addSecretFn    func(ctx context.Context, req *secretmanagerpb.AddSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error)
 	createSecretFn func(ctx context.Context, req *secretmanagerpb.CreateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error)
 	createSecretFn func(ctx context.Context, req *secretmanagerpb.CreateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error)
 	closeFn        func() error
 	closeFn        func() error
+	GetSecretFn    func(ctx context.Context, req *secretmanagerpb.GetSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error)
+}
+
+type AccessSecretVersionMockReturn struct {
+	Res *secretmanagerpb.AccessSecretVersionResponse
+	Err error
+}
+
+type AddSecretVersionMockReturn struct {
+	SecretVersion *secretmanagerpb.SecretVersion
+	Err           error
+}
+
+type GetSecretMockReturn struct {
+	Secret *secretmanagerpb.Secret
+	Err    error
+}
+
+type CreateSecretMockReturn struct {
+	Secret *secretmanagerpb.Secret
+	Err    error
 }
 }
 
 
 func (mc *MockSMClient) GetSecret(ctx context.Context, req *secretmanagerpb.GetSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error) {
 func (mc *MockSMClient) GetSecret(ctx context.Context, req *secretmanagerpb.GetSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error) {
-	return nil, nil
+	return mc.GetSecretFn(ctx, req)
+}
+
+func (mc *MockSMClient) NewGetSecretFn(mock GetSecretMockReturn) {
+	mc.GetSecretFn = func(ctx context.Context, req *secretmanagerpb.GetSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error) {
+		return mock.Secret, mock.Err
+	}
 }
 }
 
 
 func (mc *MockSMClient) AccessSecretVersion(ctx context.Context, req *secretmanagerpb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error) {
 func (mc *MockSMClient) AccessSecretVersion(ctx context.Context, req *secretmanagerpb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error) {
 	return mc.accessSecretFn(ctx, req)
 	return mc.accessSecretFn(ctx, req)
 }
 }
 
 
+func (mc *MockSMClient) NewAccessSecretVersionFn(mock AccessSecretVersionMockReturn) {
+	mc.accessSecretFn = func(ctx context.Context, req *secretmanagerpb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error) {
+		return mock.Res, mock.Err
+	}
+}
+
 func (mc *MockSMClient) ListSecrets(ctx context.Context, req *secretmanagerpb.ListSecretsRequest, opts ...gax.CallOption) *secretmanager.SecretIterator {
 func (mc *MockSMClient) ListSecrets(ctx context.Context, req *secretmanagerpb.ListSecretsRequest, opts ...gax.CallOption) *secretmanager.SecretIterator {
 	return mc.ListSecretsFn(ctx, req)
 	return mc.ListSecretsFn(ctx, req)
 }
 }
@@ -52,10 +85,22 @@ func (mc *MockSMClient) AddSecretVersion(ctx context.Context, req *secretmanager
 	return mc.addSecretFn(ctx, req)
 	return mc.addSecretFn(ctx, req)
 }
 }
 
 
+func (mc *MockSMClient) NewAddSecretVersionFn(mock AddSecretVersionMockReturn) {
+	mc.addSecretFn = func(ctx context.Context, req *secretmanagerpb.AddSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.SecretVersion, error) {
+		return mock.SecretVersion, mock.Err
+	}
+}
+
 func (mc *MockSMClient) CreateSecret(ctx context.Context, req *secretmanagerpb.CreateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error) {
 func (mc *MockSMClient) CreateSecret(ctx context.Context, req *secretmanagerpb.CreateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error) {
 	return mc.createSecretFn(ctx, req)
 	return mc.createSecretFn(ctx, req)
 }
 }
 
 
+func (mc *MockSMClient) NewCreateSecretFn(mock CreateSecretMockReturn) {
+	mc.createSecretFn = func(ctx context.Context, req *secretmanagerpb.CreateSecretRequest, opts ...gax.CallOption) (*secretmanagerpb.Secret, error) {
+		return mock.Secret, mock.Err
+	}
+}
+
 func (mc *MockSMClient) NilClose() {
 func (mc *MockSMClient) NilClose() {
 	mc.closeFn = func() error {
 	mc.closeFn = func() error {
 		return nil
 		return nil

+ 5 - 5
pkg/provider/gcp/secretmanager/secretsmanager.go

@@ -251,15 +251,13 @@ func (sm *ProviderGCP) SetSecret(ctx context.Context, payload []byte, remoteRef
 
 
 	var gErr *apierror.APIError
 	var gErr *apierror.APIError
 
 
-	if errors.As(err, &gErr) {
-		if err != nil && gErr.GRPCStatus().Code() == codes.NotFound {
+	if err != nil && errors.As(err, &gErr) {
+		if gErr.GRPCStatus().Code() == codes.NotFound {
 			gcpSecret, err = sm.SecretManagerClient.CreateSecret(ctx, createSecretReq)
 			gcpSecret, err = sm.SecretManagerClient.CreateSecret(ctx, createSecretReq)
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}
-		}
-
-		if err != nil {
+		} else {
 			return err
 			return err
 		}
 		}
 	}
 	}
@@ -278,6 +276,8 @@ func (sm *ProviderGCP) SetSecret(ctx context.Context, payload []byte, remoteRef
 		if err != nil && gErr.GRPCStatus().Code() != codes.NotFound {
 		if err != nil && gErr.GRPCStatus().Code() != codes.NotFound {
 			return err
 			return err
 		}
 		}
+	} else if err != nil {
+		return err
 	}
 	}
 
 
 	if gcpVersion != nil && gcpVersion.Payload != nil && string(payload) == string(gcpVersion.Payload.Data) {
 	if gcpVersion != nil && gcpVersion.Payload != nil && string(payload) == string(gcpVersion.Payload.Data) {

+ 182 - 125
pkg/provider/gcp/secretmanager/secretsmanager_test.go

@@ -20,19 +20,18 @@ import (
 	"strings"
 	"strings"
 	"testing"
 	"testing"
 
 
+	"github.com/crossplane/crossplane-runtime/pkg/test"
+	"github.com/google/go-cmp/cmp"
 	"github.com/googleapis/gax-go/v2/apierror"
 	"github.com/googleapis/gax-go/v2/apierror"
-	"github.com/stretchr/testify/assert"
 	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
 	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 	"google.golang.org/grpc/status"
 	"k8s.io/utils/pointer"
 	"k8s.io/utils/pointer"
 
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
-	fakeprr "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1/fakes"
 	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	"github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
 	"github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
 	fakesm "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager/fake"
 	fakesm "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager/fake"
-	"github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager/internal/fakes"
 )
 )
 
 
 type secretManagerTestCase struct {
 type secretManagerTestCase struct {
@@ -188,84 +187,38 @@ func TestSecretManagerGetSecret(t *testing.T) {
 	}
 	}
 }
 }
 
 
-func TestSetSecret(t *testing.T) {
-	client := newClient()
-	pushRemoteRef := newPushRemoteRef()
-	secret := newSecret()
-	p := newProvider(client)
-
-	client.GetSecretReturns(&secret, nil)
-
-	err := p.SetSecret(context.Background(), nil, pushRemoteRef)
-	assert.Equal(t, err, nil)
+type fakeRef struct {
+	key string
 }
 }
 
 
-func TestSetSecretAddSecretVersion(t *testing.T) {
-	client := newClient()
-	pushRemoteRef := newPushRemoteRef()
-	secret := newSecret()
-	p := newProvider(client)
-
-	expectedErr := "rpc error: code = Aborted desc = failed"
-	newStatus := status.Error(codes.Aborted, "failed")
-	err, _ := apierror.FromError(newStatus)
-
-	client.GetSecretReturns(&secret, nil)
-	client.AddSecretVersionReturns(nil, err)
-
-	expect := p.SetSecret(context.TODO(), nil, pushRemoteRef)
-	if assert.Error(t, expect) {
-		assert.Equal(t, expect.Error(), expectedErr)
-	}
+func (f fakeRef) GetRemoteKey() string {
+	return f.key
 }
 }
 
 
-func TestSetSecretAccessSecretVersion(t *testing.T) {
-	client := newClient()
-	pushRemoteRef := newPushRemoteRef()
-	secret := newSecret()
-	p := newProvider(client)
-
-	expectedErr := "rpc error: code = Aborted desc = failed"
-	newStatus := status.Error(codes.Aborted, "failed")
-	err, _ := apierror.FromError(newStatus)
-
-	client.AccessSecretVersionReturns(nil, err)
-	client.GetSecretReturns(nil, err)
-	client.CreateSecretReturns(&secret, nil)
-
-	expect := p.SetSecret(context.Background(), nil, pushRemoteRef)
-	if assert.Error(t, expect) {
-		assert.Equal(t, expect.Error(), expectedErr)
-	}
-}
+func TestSetSecret(t *testing.T) {
+	ref := fakeRef{key: "/baz"}
 
 
-func TestSetSecretGetSecret404(t *testing.T) {
-	client := newClient()
-	pushRemoteRef := newPushRemoteRef()
-	secret := newSecret()
-	p := newProvider(client)
+	notFoundError := status.Error(codes.NotFound, "failed")
+	notFoundError, _ = apierror.FromError(notFoundError)
 
 
-	newStatus := status.Error(codes.NotFound, "failed")
-	err, _ := apierror.FromError(newStatus)
+	canceledError := status.Error(codes.Canceled, "canceled")
+	canceledError, _ = apierror.FromError(canceledError)
 
 
-	client.GetSecretReturns(nil, err)
-	client.CreateSecretReturns(&secret, nil)
-	client.AccessSecretVersionReturns(nil, err)
+	APIerror := fmt.Errorf("API Error")
+	labelError := fmt.Errorf("secret %v is not managed by external secrets", ref.GetRemoteKey())
 
 
-	p.SetSecret(context.Background(), nil, pushRemoteRef)
-	if client.AddSecretVersionCallCount() != 1 {
-		t.Error("expected addSecretVersion to be called")
-	}
-	if client.CreateSecretCallCount() != 1 {
-		t.Error("expected CreateSecret to be called")
-	}
-}
-
-func TestSetSecretWrongLabel(t *testing.T) {
-	client := newClient()
-	pushRemoteRef := newPushRemoteRef()
-	p := newProvider(client)
 	secret := secretmanagerpb.Secret{
 	secret := secretmanagerpb.Secret{
+		Name: "projects/default/secrets/baz",
+		Replication: &secretmanagerpb.Replication{
+			Replication: &secretmanagerpb.Replication_Automatic_{
+				Automatic: &secretmanagerpb.Replication_Automatic{},
+			},
+		},
+		Labels: map[string]string{
+			"managed-by": "external-secrets",
+		},
+	}
+	wrongLabelSecret := secretmanagerpb.Secret{
 		Name: "projects/default/secrets/foo-bar",
 		Name: "projects/default/secrets/foo-bar",
 		Replication: &secretmanagerpb.Replication{
 		Replication: &secretmanagerpb.Replication{
 			Replication: &secretmanagerpb.Replication_Automatic_{
 			Replication: &secretmanagerpb.Replication_Automatic_{
@@ -277,36 +230,170 @@ func TestSetSecretWrongLabel(t *testing.T) {
 		},
 		},
 	}
 	}
 
 
-	pushRemoteRef.GetRemoteKeyReturns("foo-bar")
-	client.GetSecretReturns(&secret, nil)
-
-	expectedErr := "secret foo-bar is not managed by external secrets"
-	err := p.SetSecret(context.Background(), nil, pushRemoteRef)
+	smtc := secretManagerTestCase{
+		mockClient:     &fakesm.MockSMClient{},
+		apiInput:       makeValidAPIInput(),
+		ref:            makeValidRef(),
+		apiOutput:      makeValidAPIOutput(),
+		projectID:      "default",
+		apiErr:         nil,
+		expectError:    "",
+		expectedSecret: "",
+		expectedData:   map[string][]byte{},
+	}
 
 
-	if assert.Error(t, err) {
-		assert.Equal(t, err.Error(), expectedErr)
+	var payload = secretmanagerpb.SecretPayload{
+		Data: []byte("payload"),
 	}
 	}
-}
 
 
-func TestSetSecretAlreadyExists(t *testing.T) {
-	client := newClient()
-	pushRemoteRef := newPushRemoteRef()
-	secret := newSecret()
-	p := newProvider(client)
-	payload := &secretmanagerpb.SecretPayload{Data: []byte("bar")}
+	var payload2 = secretmanagerpb.SecretPayload{
+		Data: []byte("fake-value"),
+	}
 
 
-	client.AccessSecretVersionReturns(&secretmanagerpb.AccessSecretVersionResponse{
+	var res = secretmanagerpb.AccessSecretVersionResponse{
 		Name:    "projects/default/secrets/foo-bar",
 		Name:    "projects/default/secrets/foo-bar",
-		Payload: payload,
-	}, nil)
-	client.GetSecretReturns(&secret, nil)
+		Payload: &payload,
+	}
+
+	var res2 = secretmanagerpb.AccessSecretVersionResponse{
+		Name:    "projects/default/secrets/baz",
+		Payload: &payload2,
+	}
+
+	var secretVersion = secretmanagerpb.SecretVersion{}
+
+	type args struct {
+		mock                          *fakesm.MockSMClient
+		GetSecretMockReturn           fakesm.GetSecretMockReturn
+		AccessSecretVersionMockReturn fakesm.AccessSecretVersionMockReturn
+		AddSecretVersionMockReturn    fakesm.AddSecretVersionMockReturn
+		CreateSecretMockReturn        fakesm.CreateSecretMockReturn
+	}
 
 
-	err := p.SetSecret(context.TODO(), []byte("bar"), pushRemoteRef)
-	if client.AddSecretVersionCallCount() != 0 {
-		t.Error("expected addSecretVersion to not be called")
+	type want struct {
+		err error
+	}
+	tests := map[string]struct {
+		reason string
+		args   args
+		want   want
+	}{
+		"SetSecret": {
+			reason: "SetSecret successfully pushes a secret",
+			args: args{
+				mock:                          smtc.mockClient,
+				GetSecretMockReturn:           fakesm.GetSecretMockReturn{Secret: &secret, Err: nil},
+				AccessSecretVersionMockReturn: fakesm.AccessSecretVersionMockReturn{Res: &res, Err: nil},
+				AddSecretVersionMockReturn:    fakesm.AddSecretVersionMockReturn{SecretVersion: &secretVersion, Err: nil}},
+			want: want{
+				err: nil,
+			},
+		},
+		"AddSecretVersion": {
+			reason: "secret not pushed if AddSecretVersion errors",
+			args: args{
+				mock:                          smtc.mockClient,
+				GetSecretMockReturn:           fakesm.GetSecretMockReturn{Secret: &secret, Err: nil},
+				AccessSecretVersionMockReturn: fakesm.AccessSecretVersionMockReturn{Res: &res, Err: nil},
+				AddSecretVersionMockReturn:    fakesm.AddSecretVersionMockReturn{SecretVersion: nil, Err: APIerror},
+			},
+			want: want{
+				err: APIerror,
+			},
+		},
+		"AccessSecretVersion": {
+			reason: "secret not pushed if AccessSecretVersion errors",
+			args: args{
+				mock:                          smtc.mockClient,
+				GetSecretMockReturn:           fakesm.GetSecretMockReturn{Secret: &secret, Err: nil},
+				AccessSecretVersionMockReturn: fakesm.AccessSecretVersionMockReturn{Res: nil, Err: APIerror},
+			},
+			want: want{
+				err: APIerror,
+			},
+		},
+		"NotManagedByESO": {
+			reason: "secret not pushed if not managed-by external-secrets",
+			args: args{
+				mock:                smtc.mockClient,
+				GetSecretMockReturn: fakesm.GetSecretMockReturn{Secret: &wrongLabelSecret, Err: nil},
+			},
+			want: want{
+				err: labelError,
+			},
+		},
+		"SecretAlreadyExists": {
+			reason: "don't push a secret with the same key and value",
+			args: args{
+				mock:                          smtc.mockClient,
+				AccessSecretVersionMockReturn: fakesm.AccessSecretVersionMockReturn{Res: &res2, Err: nil},
+				GetSecretMockReturn:           fakesm.GetSecretMockReturn{Secret: &secret, Err: nil},
+			},
+			want: want{
+				err: nil,
+			},
+		},
+		"GetSecretNotFound": {
+			reason: "secret is created if one doesn't already exist",
+			args: args{
+				mock:                          smtc.mockClient,
+				GetSecretMockReturn:           fakesm.GetSecretMockReturn{Secret: nil, Err: notFoundError},
+				AccessSecretVersionMockReturn: fakesm.AccessSecretVersionMockReturn{Res: nil, Err: notFoundError},
+				AddSecretVersionMockReturn:    fakesm.AddSecretVersionMockReturn{SecretVersion: &secretVersion, Err: nil},
+				CreateSecretMockReturn:        fakesm.CreateSecretMockReturn{Secret: &secret, Err: nil},
+			},
+			want: want{
+				err: nil,
+			},
+		},
+		"CreateSecretReturnsNotFoundError": {
+			reason: "secret not created if CreateSecret returns not found error",
+			args: args{
+				mock:                   smtc.mockClient,
+				GetSecretMockReturn:    fakesm.GetSecretMockReturn{Secret: nil, Err: notFoundError},
+				CreateSecretMockReturn: fakesm.CreateSecretMockReturn{Secret: &secret, Err: notFoundError},
+			},
+			want: want{
+				err: notFoundError,
+			},
+		},
+		"CreateSecretReturnsError": {
+			reason: "secret not created if CreateSecret returns error",
+			args: args{
+				mock:                smtc.mockClient,
+				GetSecretMockReturn: fakesm.GetSecretMockReturn{Secret: nil, Err: canceledError},
+			},
+			want: want{
+				err: canceledError,
+			},
+		},
+		"AccessSecretVersionReturnsError": {
+			reason: "access secret version for an existing secret returns error",
+			args: args{
+				mock:                          smtc.mockClient,
+				GetSecretMockReturn:           fakesm.GetSecretMockReturn{Secret: &secret, Err: nil},
+				AccessSecretVersionMockReturn: fakesm.AccessSecretVersionMockReturn{Res: nil, Err: canceledError},
+			},
+			want: want{
+				err: canceledError,
+			},
+		},
 	}
 	}
-	if err != nil {
-		t.Errorf("expected nil got error")
+	for name, tc := range tests {
+		t.Run(name, func(t *testing.T) {
+			tc.args.mock.NewGetSecretFn(tc.args.GetSecretMockReturn)
+			tc.args.mock.NewCreateSecretFn(tc.args.CreateSecretMockReturn)
+			tc.args.mock.NewAccessSecretVersionFn(tc.args.AccessSecretVersionMockReturn)
+			tc.args.mock.NewAddSecretVersionFn(tc.args.AddSecretVersionMockReturn)
+
+			p := secretmanager.ProviderGCP{
+				SecretManagerClient: tc.args.mock,
+			}
+			err := p.SetSecret(context.Background(), []byte("fake-value"), ref)
+			if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
+				t.Errorf("\nTesting SetSecret:\nName: %v\nReason: %v\nWant error: %v\nGot error: %v", name, tc.reason, tc.want.err, diff)
+			}
+		})
 	}
 	}
 }
 }
 
 
@@ -423,33 +510,3 @@ func TestValidateStore(t *testing.T) {
 		})
 		})
 	}
 	}
 }
 }
-
-// counterfeiter helper methods.
-func newClient() *fakes.GoogleSecretManagerClient {
-	return new(fakes.GoogleSecretManagerClient)
-}
-
-func newPushRemoteRef() *fakeprr.PushRemoteRef {
-	return new(fakeprr.PushRemoteRef)
-}
-
-func newSecret() secretmanagerpb.Secret {
-	return secretmanagerpb.Secret{
-		Name: "projects/default/secrets/foo-bar",
-		Replication: &secretmanagerpb.Replication{
-			Replication: &secretmanagerpb.Replication_Automatic_{
-				Automatic: &secretmanagerpb.Replication_Automatic{},
-			},
-		},
-		Labels: map[string]string{
-			"managed-by": "external-secrets",
-		},
-	}
-}
-
-func newProvider(client secretmanager.GoogleSecretManagerClient) secretmanager.ProviderGCP {
-	return secretmanager.ProviderGCP{
-		SecretManagerClient: client,
-		ProjectID:           "default",
-	}
-}

+ 8 - 8
pkg/provider/vault/vault.go

@@ -385,6 +385,14 @@ func (v *client) SetSecret(ctx context.Context, value []byte, remoteRef esv1beta
 	if err != nil && !strings.Contains(err.Error(), "secret not found") {
 	if err != nil && !strings.Contains(err.Error(), "secret not found") {
 		return err
 		return err
 	}
 	}
+
+	// Retrieve the secret value to be pushed and convert it to string form.
+	pushSecretValue := string(value)
+
+	if vaultSecretValue == pushSecretValue {
+		return nil
+	}
+
 	// If the secret exists (err == nil), we should check if it is managed by external-secrets
 	// If the secret exists (err == nil), we should check if it is managed by external-secrets
 	if err == nil {
 	if err == nil {
 		metadata, err := v.readSecretMetadata(ctx, remoteRef.GetRemoteKey())
 		metadata, err := v.readSecretMetadata(ctx, remoteRef.GetRemoteKey())
@@ -396,13 +404,6 @@ func (v *client) SetSecret(ctx context.Context, value []byte, remoteRef esv1beta
 			return fmt.Errorf("secret not managed by external-secrets")
 			return fmt.Errorf("secret not managed by external-secrets")
 		}
 		}
 	}
 	}
-
-	// Retrieve the secret value to be pushed and convert it to string form.
-	pushSecretValue := string(value)
-
-	if vaultSecretValue == pushSecretValue {
-		return nil
-	}
 	_, err = v.logical.WriteWithContext(ctx, metaPath, label)
 	_, err = v.logical.WriteWithContext(ctx, metaPath, label)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -749,7 +750,6 @@ func (v *client) readSecret(ctx context.Context, path, version string) (map[stri
 		// Vault KV2 has data embedded within sub-field
 		// Vault KV2 has data embedded within sub-field
 		// reference - https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
 		// reference - https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
 		dataInt, ok := vaultSecret.Data["data"]
 		dataInt, ok := vaultSecret.Data["data"]
-
 		if !ok {
 		if !ok {
 			return nil, errors.New(errDataField)
 			return nil, errors.New(errDataField)
 		}
 		}

+ 94 - 111
pkg/provider/vault/vault_test.go

@@ -24,7 +24,6 @@ import (
 	"github.com/crossplane/crossplane-runtime/pkg/test"
 	"github.com/crossplane/crossplane-runtime/pkg/test"
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp"
 	vault "github.com/hashicorp/vault/api"
 	vault "github.com/hashicorp/vault/api"
-	"gotest.tools/v3/assert"
 	corev1 "k8s.io/api/core/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
 	"k8s.io/utils/pointer"
@@ -38,7 +37,6 @@ import (
 const (
 const (
 	tokenSecretName  = "example-secret-token"
 	tokenSecretName  = "example-secret-token"
 	secretDataString = "some-creds"
 	secretDataString = "some-creds"
-	secretPath       = "secret"
 )
 )
 
 
 var (
 var (
@@ -1410,129 +1408,114 @@ func (f fakeRef) GetRemoteKey() string {
 	return f.key
 	return f.key
 }
 }
 
 
-func TestSetSecretUpdateSecretNotFound(t *testing.T) {
-	path := secretPath
-	secretData := map[string]interface{}{
-		"data": map[string]interface{}{
-			"fake key": "fake value",
-		},
-	}
-	f := fake.Logical{
-		ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, fmt.Errorf("secret not found")),
-	}
-	f.WriteWithContextFn = fake.WriteChangingReadContext(secretData, f)
-	client := client{
-		store: &esv1beta1.VaultProvider{
-			Path: &path,
-		},
-		logical: f,
-	}
-	ref := fakeRef{key: "I'm a key"}
+func TestSetSecret(t *testing.T) {
+	noPermission := errors.New("no permission")
+	secretNotFound := errors.New("secret not found")
 
 
-	err := client.SetSecret(context.Background(), []byte("HI"), ref)
-	assert.Equal(t, err, nil)
-}
-
-func TestSetSecretUpdateSecretNotFoundWithError(t *testing.T) {
-	path := secretPath
-	f := fake.Logical{
-		ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, fmt.Errorf("secret not found")),
-	}
-	f.WriteWithContextFn = fake.NewWriteWithContextFn(nil, fmt.Errorf("no permissions"))
-	client := client{
-		store: &esv1beta1.VaultProvider{
-			Path: &path,
-		},
-		logical: f,
+	type args struct {
+		store    *esv1beta1.VaultProvider
+		vLogical Logical
 	}
 	}
-	ref := fakeRef{key: "I'm a key"}
 
 
-	err := client.SetSecret(context.Background(), []byte("HI"), ref)
-	assert.Equal(t, err.Error(), "no permissions")
-}
-func TestSetSecretEqualsPushSecret(t *testing.T) {
-	path := secretPath
-	f := fake.Logical{
-		ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
-			"key": "fake value",
-		}, nil),
+	type want struct {
+		err error
 	}
 	}
-	f.WriteWithContextFn = fake.NewWriteWithContextFn(nil, nil)
-	client := client{
-		store: &esv1beta1.VaultProvider{
-			Path: &path,
+	tests := map[string]struct {
+		reason string
+		args   args
+		want   want
+	}{
+		"SetSecret": {
+			reason: "secret is successfully set, with no existing vault secret",
+			args: args{
+				store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
+				vLogical: &fake.Logical{
+					ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, secretNotFound),
+					WriteWithContextFn:        fake.NewWriteWithContextFn(nil, nil),
+				},
+			},
+			want: want{
+				err: nil,
+			},
 		},
 		},
-		logical: f,
-	}
-	ref := fakeRef{key: "key"}
-
-	err := client.SetSecret(context.Background(), []byte("fake value"), ref)
 
 
-	assert.Equal(t, err, nil)
-}
-
-func TestSetSecretEqualsPushSecretWithError(t *testing.T) {
-	path := secretPath
-	f := fake.Logical{
-		ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
-			"key": "wrong-key",
-		}, nil),
-	}
-	f.WriteWithContextFn = fake.NewWriteWithContextFn(nil, fmt.Errorf("boom"))
-	client := client{
-		store: &esv1beta1.VaultProvider{
-			Path: &path,
+		"SetSecretWithWriteError": {
+			reason: "secret cannot be pushed if write fails",
+			args: args{
+				store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
+				vLogical: &fake.Logical{
+					ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, secretNotFound),
+					WriteWithContextFn:        fake.NewWriteWithContextFn(nil, noPermission),
+				},
+			},
+			want: want{
+				err: noPermission,
+			},
 		},
 		},
-		logical: f,
-	}
-	ref := fakeRef{key: "key"}
 
 
-	err := client.SetSecret(context.Background(), []byte("fake value"), ref)
-	assert.Equal(t, err.Error(), "boom")
-}
-func TestSetSecretErrorReadingSecret(t *testing.T) {
-	path := secretPath
-	f := fake.Logical{
-		ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, fmt.Errorf("you shall not pass")),
-	}
-	f.WriteWithContextFn = fake.NewWriteWithContextFn(nil, nil)
-	client := client{
-		store: &esv1beta1.VaultProvider{
-			Path: &path,
+		"SetSecretEqualsPushSecret": {
+			reason: "vault secret kv equals secret to push kv",
+			args: args{
+				store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
+				vLogical: &fake.Logical{
+					ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
+						"data": map[string]interface{}{
+							"fake-key": "fake-value",
+						},
+					}, nil),
+				},
+			},
+			want: want{
+				err: nil,
+			},
 		},
 		},
-		logical: f,
-	}
-	ref := fakeRef{key: "key"}
-
-	err := client.SetSecret(context.Background(), []byte("fake value"), ref)
-	assert.ErrorContains(t, err, "you shall not pass")
-}
-
-// Test if secret is managed by eso.
-func TestSetSecretNotManagedByESO(t *testing.T) {
-	path := secretPath
-
-	f := fake.Logical{
-		ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
-			"key": "fake value",
-		}, nil),
-	}
 
 
-	f.WriteWithContextFn = fake.NewWriteWithContextFn(map[string]interface{}{
-		"custom_metadata": map[string]string{
-			"managed-by": "not-external-secrets",
+		"SetSecretErrorReadingSecret": {
+			reason: "error occurs if secret cannot be read",
+			args: args{
+				store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
+				vLogical: &fake.Logical{
+					ReadWithDataWithContextFn: fake.NewReadWithContextFn(nil, noPermission),
+				},
+			},
+			want: want{
+				err: fmt.Errorf(errReadSecret, noPermission),
+			},
 		},
 		},
-	}, nil)
 
 
-	client := client{
-		store: &esv1beta1.VaultProvider{
-			Path: &path,
+		"SetSecretNotManagedByESO": {
+			reason: "a secret not managed by ESO cannot be updated",
+			args: args{
+				store: makeValidSecretStoreWithVersion(esv1beta1.VaultKVStoreV2).Spec.Provider.Vault,
+				vLogical: &fake.Logical{
+					ReadWithDataWithContextFn: fake.NewReadWithContextFn(map[string]interface{}{
+						"data": map[string]interface{}{
+							"fake-key": "fake-value2",
+							"custom_metadata": map[string]interface{}{
+								"managed-by": "not-external-secrets",
+							},
+						},
+					}, nil),
+				},
+			},
+			want: want{
+				err: errors.New("secret not managed by external-secrets"),
+			},
 		},
 		},
-		logical: f,
 	}
 	}
-	ref := fakeRef{key: "key"}
 
 
-	err := client.SetSecret(context.Background(), []byte("fake value"), ref)
+	for name, tc := range tests {
+		t.Run(name, func(t *testing.T) {
+			ref := fakeRef{key: "fake-key"}
+			client := &client{
+				logical: tc.args.vLogical,
+				store:   tc.args.store,
+			}
+			err := client.SetSecret(context.Background(), []byte("fake-value"), ref)
 
 
-	assert.Equal(t, err.Error(), "secret not managed by external-secrets")
+			if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
+				t.Errorf("\nTesting SetSecret:\nName: %v\nReason: %v\nWant error: %v\nGot error: %v", name, tc.reason, tc.want.err, diff)
+			}
+		})
+	}
 }
 }