Browse Source

Added unit tests for crd controller methods.
Added simple GetAllSecrets logic test
Starting (and failing to) test on controller level

Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>

Gustavo Carvalho 4 years ago
parent
commit
a85e487d1d

+ 4 - 2
go.mod

@@ -85,7 +85,10 @@ require (
 	software.sslmate.com/src/go-pkcs12 v0.0.0-20210415151418-c5206de65a78
 )
 
-require cloud.google.com/go/iam v0.1.1
+require (
+	cloud.google.com/go/iam v0.1.1
+	k8s.io/apiextensions-apiserver v0.23.0
+)
 
 require (
 	cloud.google.com/go/compute v0.1.0 // indirect
@@ -206,7 +209,6 @@ require (
 	gopkg.in/ini.v1 v1.66.2 // indirect
 	gopkg.in/square/go-jose.v2 v2.6.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
-	k8s.io/apiextensions-apiserver v0.23.0 // indirect
 	k8s.io/component-base v0.23.0 // indirect
 	k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c // indirect
 	k8s.io/klog v0.3.0 // indirect

+ 155 - 0
pkg/controllers/crds/common_test.go

@@ -0,0 +1,155 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package crds
+
+// import (
+// 	"context"
+// 	"time"
+
+// 	. "github.com/onsi/ginkgo/v2"
+// 	. "github.com/onsi/gomega"
+// 	corev1 "k8s.io/api/core/v1"
+// 	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+// 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+// 	"k8s.io/apimachinery/pkg/types"
+
+// 	esapi "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+// )
+
+// type testCase struct {
+// 	crd    apiextensions.CustomResourceDefinition
+// 	assert func()
+// }
+
+// var _ = Describe("CRD reconcile", func() {
+// 	var test *testCase
+
+// 	BeforeEach(func() {
+// 		test = makeDefaultTestcase()
+// 	})
+
+// 	AfterEach(func() {
+// 		Expect(k8sClient.Delete(context.Background(), &test.crd)).ToNot(HaveOccurred())
+// 	})
+
+// 	// a invalid provider config should be reflected
+// 	// in the store status condition
+// 	PatchesCRD := func(tc *testCase) {
+// 		tc.assert = func() {
+// 			Eventually(func() bool {
+// 				ss := apiextensions.CustomResourceDefinition{}
+// 				err := k8sClient.Get(context.Background(), types.NamespacedName{
+// 					Name: "secrestores.external-secrets.io",
+// 				}, &ss)
+// 				if err != nil {
+// 					return false
+// 				}
+// 				return ss.Spec.Conversion.Strategy == "Webhook"
+// 			}).
+// 				WithTimeout(time.Second * 10).
+// 				WithPolling(time.Second).
+// 				Should(BeTrue())
+// 		}
+// 	}
+
+// 	// if controllerClass does not match the controller
+// 	// should not touch this store
+// 	ignoreNonTargetCRDs := func(tc *testCase) {
+// 		tc.assert = func() {
+// 			Consistently(func() bool {
+// 				ss := apiextensions.CustomResourceDefinition{}
+// 				err := k8sClient.Get(context.Background(), types.NamespacedName{
+// 					Name: defaultStoreName,
+// 				}, &ss)
+// 				if err != nil {
+// 					return false
+// 				}
+// 				return ss.Spec.Conversion == tc.crd.Spec.Conversion
+// 			}).
+// 				WithTimeout(time.Second * 3).
+// 				WithPolling(time.Millisecond * 500).
+// 				Should(BeTrue())
+// 		}
+// 	}
+
+// 	DescribeTable("Controller Reconcile logic", func(muts ...func(tc *testCase)) {
+// 		for _, mut := range muts {
+// 			mut(test)
+// 		}
+// 		err := k8sClient.Create(context.Background(), test.store.Copy())
+// 		Expect(err).ToNot(HaveOccurred())
+// 		test.assert()
+// 	},
+// 		// namespaced store
+// 		Entry("[namespace] invalid provider with secretStore should set InvalidStore condition", invalidProvider),
+// 		Entry("[namespace] ignore stores with non-matching class", ignoreControllerClass),
+// 		Entry("[namespace] valid provider has status=ready", validProvider),
+
+// 		// cluster store
+// 		Entry("[cluster] invalid provider with secretStore should set InvalidStore condition", invalidProvider, useClusterStore),
+// 		Entry("[cluster] ignore stores with non-matching class", ignoreControllerClass, useClusterStore),
+// 		Entry("[cluster] valid provider has status=ready", validProvider, useClusterStore),
+// 	)
+
+// })
+
+// const (
+// 	defaultStoreName       = "default-store"
+// 	defaultControllerClass = "test-ctrl"
+// )
+
+// func makeDefaultTestcase() *testCase {
+// 	return &testCase{
+// 		assert: func() {
+// 			// this is a noop by default
+// 		},
+// 		crd: &apiextensions.CustomResourceDefinition{
+// 			TypeMeta: metav1.TypeMeta{
+// 				Kind:       esapi.SecretStoreKind,
+// 				APIVersion: esapi.SecretStoreKindAPIVersion,
+// 			},
+// 			ObjectMeta: metav1.ObjectMeta{
+// 				Name:      defaultStoreName,
+// 				Namespace: "default",
+// 			},
+// 			Spec: esapi.SecretStoreSpec{
+// 				Controller: defaultControllerClass,
+// 				// empty provider
+// 				// a testCase mutator must fill in the concrete provider
+// 				Provider: &esapi.SecretStoreProvider{
+// 					Vault: &esapi.VaultProvider{
+// 						Version: esapi.VaultKVStoreV1,
+// 					},
+// 				},
+// 			},
+// 		},
+// 	}
+// }
+
+// func hasEvent(involvedKind, name, reason string) bool {
+// 	el := &corev1.EventList{}
+// 	err := k8sClient.List(context.Background(), el)
+// 	if err != nil {
+// 		return false
+// 	}
+// 	for i := range el.Items {
+// 		ev := el.Items[i]
+// 		if ev.InvolvedObject.Kind == involvedKind && ev.InvolvedObject.Name == name {
+// 			if ev.Reason == reason {
+// 				return true
+// 			}
+// 		}
+// 	}
+// 	return false
+// }

+ 289 - 0
pkg/controllers/crds/crds_controller_test.go

@@ -0,0 +1,289 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package crds
+
+import (
+	"context"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/json"
+	"testing"
+	"time"
+
+	corev1 "k8s.io/api/core/v1"
+	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/types"
+	ctrl "sigs.k8s.io/controller-runtime"
+	client "sigs.k8s.io/controller-runtime/pkg/client/fake"
+)
+
+func newReconciler() Reconciler {
+	return Reconciler{
+		CrdResources: []string{"one", "two", "three"},
+		SvcLabels:    map[string]string{"foo": "bar"},
+		SecretLabels: map[string]string{"foo": "bar"},
+	}
+}
+
+func newService() corev1.Service {
+	return corev1.Service{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "foo",
+			Namespace: "default",
+			Labels:    map[string]string{"foo": "bar"},
+		},
+	}
+}
+func newSecret() corev1.Secret {
+	return corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "foo",
+			Namespace: "default",
+			Labels:    map[string]string{"foo": "bar"},
+		},
+	}
+}
+
+func newCRD() apiextensionsv1.CustomResourceDefinition {
+	return apiextensionsv1.CustomResourceDefinition{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "one",
+		},
+		Spec: apiextensionsv1.CustomResourceDefinitionSpec{
+			Conversion: &apiextensionsv1.CustomResourceConversion{
+				Strategy: "Webhook",
+				Webhook: &apiextensionsv1.WebhookConversion{
+					ConversionReviewVersions: []string{"v1"},
+					ClientConfig: &apiextensionsv1.WebhookClientConfig{
+						CABundle: []byte("test"),
+						Service: &apiextensionsv1.ServiceReference{
+							Name:      "wrong",
+							Namespace: "wrong",
+						},
+					},
+				},
+			},
+		},
+	}
+}
+func TestConvertToWebhookInfo(t *testing.T) {
+	rec := newReconciler()
+	info := rec.ConvertToWebhookInfo()
+	if len(info) != 3 {
+		t.Errorf("Convert to WebhookInfo failed. Total resources:%d", len(info))
+	}
+	for _, v := range info {
+		if v.Type != CRDConversion {
+			t.Errorf("Convert to WebhookInfo failed. wrong type:%v", v.Type)
+		}
+		if v.Name != "one" && v.Name != "two" && v.Name != "three" {
+			t.Errorf("Convert to WebhookInfo failed. wrong name:%v", v.Name)
+		}
+	}
+}
+
+func TestUpdateCRD(t *testing.T) {
+	rec := newReconciler()
+	svc := newService()
+	secret := newSecret()
+	crd := newCRD()
+	c := client.NewClientBuilder().WithObjects(&svc, &secret, &crd).Build()
+	rec.Client = c
+	ctx := context.Background()
+	req := ctrl.Request{
+		NamespacedName: types.NamespacedName{
+			Name: "one",
+		},
+	}
+	err := rec.updateCRD(ctx, req)
+	if err != nil {
+		t.Errorf("Failed updating CRD:%v", err)
+	}
+}
+
+func TestInjectSvcToConversionWebhook(t *testing.T) {
+	svc := newService()
+	crd := newCRD()
+	crdunmarshalled := make(map[string]interface{})
+	crdJSON, err := json.Marshal(crd)
+	if err != nil {
+		t.Fatal("Could not setup test")
+	}
+	err = json.Unmarshal(crdJSON, &crdunmarshalled)
+	if err != nil {
+		t.Fatal("Could not setup test")
+	}
+	u := unstructured.Unstructured{
+		Object: crdunmarshalled,
+	}
+	err = injectSvcToConversionWebhook(&u, &svc)
+	if err != nil {
+		t.Errorf("Failed: error when injecting: %v", err)
+	}
+	val, found, err := unstructured.NestedString(u.Object, "spec", "conversion", "webhook", "clientConfig", "service", "name")
+	if err != nil {
+		t.Error("Error when searching for field")
+	}
+	if !found {
+		t.Error("Field not found, mutation failed")
+	}
+	if val != "foo" {
+		t.Errorf("Wrong service name injected: %v", val)
+	}
+
+	val, found, err = unstructured.NestedString(u.Object, "spec", "conversion", "webhook", "clientConfig", "service", "namespace")
+	if err != nil {
+		t.Error("Error when searching for field")
+	}
+	if !found {
+		t.Error("Field not found, mutation failed")
+	}
+	if val != "default" {
+		t.Errorf("Wrong service namespace injected: %v", val)
+	}
+}
+
+func TestInjectCertToConversionWebhook(t *testing.T) {
+	certPEM := []byte("foobar")
+	crd := newCRD()
+	crdunmarshalled := make(map[string]interface{})
+	crdJson, err := json.Marshal(crd)
+	if err != nil {
+		t.Fatal("Could not setup test")
+	}
+	err = json.Unmarshal(crdJson, &crdunmarshalled)
+	if err != nil {
+		t.Fatal("Could not setup test")
+	}
+	u := unstructured.Unstructured{
+		Object: crdunmarshalled,
+	}
+	err = injectCertToConversionWebhook(&u, certPEM)
+	if err != nil {
+		t.Errorf("Failed: error when injecting: %v", err)
+	}
+	val, found, err := unstructured.NestedString(u.Object, "spec", "conversion", "webhook", "clientConfig", "caBundle")
+	if err != nil {
+		t.Error("Error when searching for field")
+	}
+	if !found {
+		t.Error("Field not found, mutation failed")
+	}
+	if val != "Zm9vYmFy" {
+		t.Errorf("Wrong certificate name injected: %v", val)
+	}
+}
+func TestPopulateSecret(t *testing.T) {
+	secret := newSecret()
+	caArtifacts := KeyPairArtifacts{
+		Cert:    &x509.Certificate{},
+		Key:     &rsa.PrivateKey{},
+		CertPEM: []byte("foobarca"),
+		KeyPEM:  []byte("foobarcakey"),
+	}
+	cert := []byte("foobarcert")
+	key := []byte("foobarkey")
+	populateSecret(cert, key, &caArtifacts, &secret)
+	if string(secret.Data["tls.crt"]) != string(cert) {
+		t.Errorf("secret value for tls.crt is wrong:%v", cert)
+	}
+	if string(secret.Data["tls.key"]) != string(key) {
+		t.Errorf("secret value for tls.key is wrong:%v", cert)
+	}
+	if string(secret.Data["ca.crt"]) != string(caArtifacts.CertPEM) {
+		t.Errorf("secret value for ca.crt is wrong:%v", cert)
+	}
+	if string(secret.Data["ca.key"]) != string(caArtifacts.KeyPEM) {
+		t.Errorf("secret value for ca.key is wrong:%v", cert)
+	}
+}
+
+func TestCreateCACert(t *testing.T) {
+	rec := newReconciler()
+	caArtifacts, err := rec.CreateCACert(time.Now(), time.Now().AddDate(1, 0, 0))
+	if err != nil {
+		t.Errorf("could not create certificates:%v", err)
+	}
+	if !rec.validCACert(caArtifacts.CertPEM, caArtifacts.KeyPEM) {
+		t.Errorf("generated certificates are invalid:%v", caArtifacts)
+	}
+}
+
+func TestCreateCertPEM(t *testing.T) {
+	rec := newReconciler()
+	caArtifacts, err := rec.CreateCACert(time.Now(), time.Now().AddDate(1, 0, 0))
+	if err != nil {
+		t.Fatalf("could not create ca certificates:%v", err)
+	}
+	certPEM, keyPEM, err := rec.CreateCertPEM(caArtifacts, time.Now(), time.Now().AddDate(1, 0, 0))
+	if err != nil {
+		t.Errorf("could not create server certificates: %v", err)
+	}
+	if !rec.validServerCert(caArtifacts.CertPEM, certPEM, keyPEM) {
+		t.Errorf("generated certificates are invalid:%v,%v", certPEM, keyPEM)
+	}
+}
+func TestValidCert(t *testing.T) {
+	rec := newReconciler()
+	rec.dnsName = "foobar"
+	caArtifacts, err := rec.CreateCACert(time.Now(), time.Now().AddDate(1, 0, 0))
+	if err != nil {
+		t.Fatalf("could not create ca certificates:%v", err)
+	}
+	certPEM, keyPEM, err := rec.CreateCertPEM(caArtifacts, time.Now(), time.Now().AddDate(1, 0, 0))
+	if err != nil {
+		t.Errorf("could not create server certificates: %v", err)
+	}
+	ok, err := ValidCert(caArtifacts.CertPEM, certPEM, keyPEM, "foobar", time.Now())
+	if err != nil {
+		t.Errorf("error validating cert: %v", err)
+	}
+	if !ok {
+		t.Errorf("certificate is invalid")
+	}
+}
+
+func TestRefreshCertIfNeeded(t *testing.T) {
+	rec := newReconciler()
+	secret := newSecret()
+	c := client.NewClientBuilder().WithObjects(&secret).Build()
+	rec.Client = c
+	rec.dnsName = "foobar"
+	caArtifacts, err := rec.CreateCACert(time.Now().AddDate(-1, 0, 0), time.Now().AddDate(0, -1, 0))
+	if err != nil {
+		t.Fatalf("could not create ca certificates:%v", err)
+	}
+	certPEM, keyPEM, err := rec.CreateCertPEM(caArtifacts, time.Now(), time.Now().AddDate(1, 0, 0))
+	if err != nil {
+		t.Errorf("could not create server certificates: %v", err)
+	}
+	populateSecret(certPEM, keyPEM, caArtifacts, &secret)
+	ok, err := rec.refreshCertIfNeeded(&secret)
+	if err != nil {
+		t.Errorf("could not verify refresh need: %v", err)
+	}
+	if !ok {
+		t.Error("expected refresh true. got false")
+	}
+	ok, err = rec.refreshCertIfNeeded(&secret)
+	if err != nil {
+		t.Errorf("could not verify refresh need: %v", err)
+	}
+	if !ok {
+		t.Error("expected refresh false. got true")
+	}
+}

+ 101 - 0
pkg/controllers/crds/suite_test.go

@@ -0,0 +1,101 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package crds
+
+import (
+	"context"
+	"path/filepath"
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	"k8s.io/client-go/kubernetes/scheme"
+	"k8s.io/client-go/rest"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/controller"
+	"sigs.k8s.io/controller-runtime/pkg/envtest"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+	esapi "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+)
+
+var cfg *rest.Config
+var k8sClient client.Client
+var testEnv *envtest.Environment
+var cancel context.CancelFunc
+
+func TestAPIs(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Controller Suite")
+}
+
+var _ = BeforeSuite(func() {
+	log := zap.New(zap.WriteTo(GinkgoWriter))
+	logf.SetLogger(log)
+
+	By("bootstrapping test environment")
+	testEnv = &envtest.Environment{
+		CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "deploy", "crds")},
+	}
+
+	var ctx context.Context
+	ctx, cancel = context.WithCancel(context.Background())
+
+	var err error
+	cfg, err = testEnv.Start()
+	Expect(err).ToNot(HaveOccurred())
+	Expect(cfg).ToNot(BeNil())
+
+	err = esapi.AddToScheme(scheme.Scheme)
+	Expect(err).NotTo(HaveOccurred())
+
+	k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
+		Scheme:             scheme.Scheme,
+		MetricsBindAddress: "0", // avoid port collision when testing
+	})
+	Expect(err).ToNot(HaveOccurred())
+
+	k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
+	Expect(err).ToNot(HaveOccurred())
+	Expect(k8sClient).ToNot(BeNil())
+
+	err = (&Reconciler{
+		Client:                 k8sClient,
+		Scheme:                 k8sManager.GetScheme(),
+		Log:                    ctrl.Log.WithName("controllers").WithName("CustomResourceDefinition"),
+		SvcLabels:              map[string]string{"foo": "bar"},
+		SecretLabels:           map[string]string{"foo": "bar"},
+		CrdResources:           []string{"externalsecrets.external-secrets.io", "secretstores.external-secrets.io", "clustersecretstores.external-secrets.io"},
+		CertDir:                "my/cert/dir",
+		CAName:                 "external-secrets",
+		CAOrganization:         "external-secrets",
+		RestartOnSecretRefresh: false,
+	}).SetupWithManager(k8sManager, controller.Options{})
+	Expect(err).ToNot(HaveOccurred())
+
+	go func() {
+		defer GinkgoRecover()
+		Expect(k8sManager.Start(ctx)).ToNot(HaveOccurred())
+	}()
+})
+
+var _ = AfterSuite(func() {
+	By("tearing down the test environment")
+	cancel() // stop manager
+	err := testEnv.Stop()
+	Expect(err).ToNot(HaveOccurred())
+})

+ 25 - 1
pkg/controllers/externalsecret/externalsecret_controller_test.go

@@ -236,7 +236,6 @@ var _ = Describe("ExternalSecret controller", func() {
 			Expect(secret.ObjectMeta.Name).To(Equal(ExternalSecretName))
 		}
 	}
-
 	// labels and annotations from the Kind=ExternalSecret
 	// should be copied over to the Kind=Secret
 	syncLabelsAnnotations := func(tc *testCase) {
@@ -789,6 +788,30 @@ var _ = Describe("ExternalSecret controller", func() {
 		}
 	}
 
+	// with dataFrom.Find the change is on the called method GetAllSecrets
+	// all keys should be put into the secret
+	syncDataFromFind := func(tc *testCase) {
+		tc.externalSecret.Spec.Data = nil
+		tc.externalSecret.Spec.DataFrom = []esv1beta1.ExternalSecretDataFromRemoteRef{
+			{
+				Find: esv1beta1.ExternalSecretFind{
+					Name: esv1beta1.FindName{
+						RegExp: "foobar",
+					},
+				},
+			},
+		}
+		fakeProvider.WithGetAllSecrets(map[string][]byte{
+			"foo": []byte(FooValue),
+			"bar": []byte(BarValue),
+		}, nil)
+		tc.checkSecret = func(es *esv1beta1.ExternalSecret, secret *v1.Secret) {
+			// check values
+			Expect(string(secret.Data["foo"])).To(Equal(FooValue))
+			Expect(string(secret.Data["bar"])).To(Equal(BarValue))
+		}
+	}
+
 	// with dataFrom and using a template
 	// should be put into the secret
 	syncWithDataFromTemplate := func(tc *testCase) {
@@ -1064,6 +1087,7 @@ var _ = Describe("ExternalSecret controller", func() {
 		Entry("should refresh secret map when provider secret changes when using a template", refreshSecretValueMapTemplate),
 		Entry("should not refresh secret value when provider secret changes but refreshInterval is zero", refreshintervalZero),
 		Entry("should fetch secret using dataFrom", syncWithDataFrom),
+		Entry("should fetch secret using dataFrom.find", syncDataFromFind),
 		Entry("should fetch secret using dataFrom and a template", syncWithDataFromTemplate),
 		Entry("should set error condition when provider errors", providerErrCondition),
 		Entry("should set an error condition when store does not exist", storeMissingErrCondition),

+ 1 - 1
pkg/controllers/externalsecret/suite_test.go

@@ -55,7 +55,7 @@ var _ = BeforeSuite(func() {
 
 	By("bootstrapping test environment")
 	testEnv = &envtest.Environment{
-		CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "deploy", "crds")},
+		CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crds", "bases")},
 	}
 
 	var ctx context.Context

+ 8 - 0
pkg/provider/testing/fake/fake.go

@@ -100,6 +100,14 @@ func (v *Client) WithGetSecretMap(secData map[string][]byte, err error) *Client
 	return v
 }
 
+// WithGetAllSecrets wraps the secret data map returned by this fake provider.
+func (v *Client) WithGetAllSecrets(secData map[string][]byte, err error) *Client {
+	v.GetAllSecretsFn = func(context.Context, esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
+		return secData, err
+	}
+	return v
+}
+
 // WithNew wraps the fake provider factory function.
 func (v *Client) WithNew(f func(context.Context, esv1beta1.GenericStore, client.Client,
 	string) (provider.SecretsClient, error)) *Client {