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

test: expand kubernetes v2 provider coverage

Signed-off-by: Moritz Johner <beller.moritz@googlemail.com>
Moritz Johner 2 месяцев назад
Родитель
Сommit
0b18b5caa2

+ 52 - 0
e2e/suites/provider/cases/kubernetes/provider_v2.go

@@ -80,4 +80,56 @@ var _ = Describe("[kubernetes] v2 namespaced provider", Label("kubernetes", "v2"
 		_, err := f.WaitForSecretValue(f.Namespace.Name, "provider-v2-target", expected)
 		Expect(err).NotTo(HaveOccurred())
 	})
+
+	It("syncs ExternalSecret dataFrom.find through a namespaced Provider", func() {
+		secretOne := "provider-v2-find-one"
+		secretTwo := "provider-v2-find-two"
+		secretThree := "provider-v2-ignore"
+
+		prov.CreateSecret(secretOne, framework.SecretEntry{
+			Value: `{"value":"provider-v2-one"}`,
+		})
+		prov.CreateSecret(secretTwo, framework.SecretEntry{
+			Value: `{"value":"provider-v2-two"}`,
+		})
+		prov.CreateSecret(secretThree, framework.SecretEntry{
+			Value: `{"value":"provider-v2-ignore"}`,
+		})
+
+		externalSecret := &esv1.ExternalSecret{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "provider-v2-find-es",
+				Namespace: f.Namespace.Name,
+			},
+			Spec: esv1.ExternalSecretSpec{
+				RefreshInterval: &metav1.Duration{Duration: defaultV2RefreshInterval},
+				SecretStoreRef: esv1.SecretStoreRef{
+					Name: f.Namespace.Name,
+					Kind: esv1.ProviderKindStr,
+				},
+				Target: esv1.ExternalSecretTarget{
+					Name: "provider-v2-find-target",
+				},
+				DataFrom: []esv1.ExternalSecretDataFromRemoteRef{{
+					Find: &esv1.ExternalSecretFind{
+						Name: &esv1.FindName{
+							RegExp: "provider-v2-find-(one|two)",
+						},
+					},
+				}},
+			},
+		}
+		Expect(f.CRClient.Create(context.Background(), externalSecret)).To(Succeed())
+
+		expected := &corev1.Secret{
+			Type: corev1.SecretTypeOpaque,
+			Data: map[string][]byte{
+				secretOne: []byte(`{"value":"provider-v2-one"}`),
+				secretTwo: []byte(`{"value":"provider-v2-two"}`),
+			},
+		}
+
+		_, err := f.WaitForSecretValue(f.Namespace.Name, "provider-v2-find-target", expected)
+		Expect(err).NotTo(HaveOccurred())
+	})
 })

+ 249 - 2
pkg/controllers/pushsecret/pushsecret_controller_v2_test.go

@@ -30,14 +30,14 @@ import (
 	"time"
 
 	"github.com/go-logr/logr"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	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/runtime"
 	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials"
 	fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
 
 	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
@@ -541,6 +541,253 @@ func TestDeleteSecretFromProvidersV2UsesProviderNamespaceAuthScope(t *testing.T)
 	}
 }
 
+func TestDeleteSecretFromProvidersV2DeletesOnlyRemovedEntriesForManifestScope(t *testing.T) {
+	previous := clientmanager.V2ProvidersEnabled()
+	clientmanager.SetV2ProvidersEnabled(true)
+	t.Cleanup(func() {
+		clientmanager.SetV2ProvidersEnabled(previous)
+	})
+
+	scheme := newPushSecretTestScheme(t)
+	server, address, tlsSecret := newPushSecretProviderServer(t)
+
+	clusterProvider := &esv1.ClusterProvider{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "cluster-provider",
+		},
+		Spec: esv1.ClusterProviderSpec{
+			Config: esv1.ProviderConfig{
+				Address: address,
+				ProviderRef: esv1.ProviderReference{
+					APIVersion: "provider.external-secrets.io/v2alpha1",
+					Kind:       "Kubernetes",
+					Name:       "backend",
+				},
+			},
+			AuthenticationScope: esv1.AuthenticationScopeManifestNamespace,
+			Conditions: []esv1.ClusterSecretStoreCondition{{
+				Namespaces: []string{"tenant-a"},
+			}},
+		},
+	}
+
+	kubeClient := fakeclient.NewClientBuilder().
+		WithScheme(scheme).
+		WithObjects(
+			clusterProvider,
+			&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{
+				Name: "tenant-a",
+				Labels: map[string]string{
+					"kubernetes.io/metadata.name": "tenant-a",
+				},
+			}},
+			&corev1.Secret{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "external-secrets-provider-tls",
+					Namespace: "tenant-a",
+				},
+				Data: tlsSecret,
+			},
+		).
+		Build()
+
+	r := &Reconciler{Client: kubeClient, Log: logr.Discard()}
+	ps := &esapi.PushSecret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "pushsecret",
+			Namespace: "tenant-a",
+		},
+		Status: esapi.PushSecretStatus{
+			SyncedPushSecrets: esapi.SyncedPushSecretsMap{
+				"ClusterProvider/cluster-provider": {
+					"remote/keep/property": {
+						Match: esapi.PushSecretMatch{
+							SecretKey: "keep",
+							RemoteRef: esapi.PushSecretRemoteRef{
+								RemoteKey: "remote/keep",
+								Property:  "property",
+							},
+						},
+					},
+					"remote/delete/property": {
+						Match: esapi.PushSecretMatch{
+							SecretKey: "delete",
+							RemoteRef: esapi.PushSecretRemoteRef{
+								RemoteKey: "remote/delete",
+								Property:  "property",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+
+	newMap := esapi.SyncedPushSecretsMap{
+		"ClusterProvider/cluster-provider": {
+			"remote/keep/property": ps.Status.SyncedPushSecrets["ClusterProvider/cluster-provider"]["remote/keep/property"],
+		},
+	}
+
+	result, err := r.DeleteSecretFromProvidersV2(context.Background(), ps, newMap, map[esapi.PushSecretStoreRef]interface{}{
+		{Name: "cluster-provider", Kind: esv1.ClusterProviderKindStr}: clusterProvider,
+	})
+	if err != nil {
+		t.Fatalf("DeleteSecretFromProvidersV2() error = %v", err)
+	}
+
+	if server.deleteRequest == nil {
+		t.Fatal("expected delete request to be recorded")
+	}
+	if server.deleteRequest.SourceNamespace != "tenant-a" {
+		t.Fatalf("unexpected source namespace: %q", server.deleteRequest.SourceNamespace)
+	}
+	if server.deleteRequest.RemoteRef == nil || server.deleteRequest.RemoteRef.RemoteKey != "remote/delete" || server.deleteRequest.RemoteRef.Property != "property" {
+		t.Fatalf("unexpected delete ref: %#v", server.deleteRequest.RemoteRef)
+	}
+
+	storeState, ok := result["ClusterProvider/cluster-provider"]
+	if !ok {
+		t.Fatalf("expected synced state for cluster provider, got %#v", result)
+	}
+	if len(storeState) != 1 {
+		t.Fatalf("expected one remaining synced entry, got %#v", storeState)
+	}
+	if _, ok := storeState["remote/keep/property"]; !ok {
+		t.Fatalf("expected keep entry to remain, got %#v", storeState)
+	}
+	if _, ok := storeState["remote/delete/property"]; ok {
+		t.Fatalf("expected delete entry to be removed, got %#v", storeState)
+	}
+}
+
+func TestDeleteSecretFromProvidersV2DeletesOnlyRemovedEntriesForProviderNamespaceScope(t *testing.T) {
+	previous := clientmanager.V2ProvidersEnabled()
+	clientmanager.SetV2ProvidersEnabled(true)
+	t.Cleanup(func() {
+		clientmanager.SetV2ProvidersEnabled(previous)
+	})
+
+	scheme := newPushSecretTestScheme(t)
+	server, address, tlsSecret := newPushSecretProviderServer(t)
+
+	const manifestNamespace = "tenant-a"
+	const providerNamespace = "provider-config-ns"
+
+	clusterProvider := &esv1.ClusterProvider{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "cluster-provider",
+		},
+		Spec: esv1.ClusterProviderSpec{
+			Config: esv1.ProviderConfig{
+				Address: address,
+				ProviderRef: esv1.ProviderReference{
+					APIVersion: "provider.external-secrets.io/v2alpha1",
+					Kind:       "Kubernetes",
+					Name:       "backend",
+					Namespace:  providerNamespace,
+				},
+			},
+			AuthenticationScope: esv1.AuthenticationScopeProviderNamespace,
+			Conditions: []esv1.ClusterSecretStoreCondition{{
+				Namespaces: []string{manifestNamespace},
+			}},
+		},
+	}
+
+	kubeClient := fakeclient.NewClientBuilder().
+		WithScheme(scheme).
+		WithObjects(
+			clusterProvider,
+			&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{
+				Name: manifestNamespace,
+				Labels: map[string]string{
+					"kubernetes.io/metadata.name": manifestNamespace,
+				},
+			}},
+			&corev1.Secret{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "external-secrets-provider-tls",
+					Namespace: providerNamespace,
+				},
+				Data: tlsSecret,
+			},
+		).
+		Build()
+
+	r := &Reconciler{Client: kubeClient, Log: logr.Discard()}
+	ps := &esapi.PushSecret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "pushsecret",
+			Namespace: manifestNamespace,
+		},
+		Status: esapi.PushSecretStatus{
+			SyncedPushSecrets: esapi.SyncedPushSecretsMap{
+				"ClusterProvider/cluster-provider": {
+					"remote/keep/property": {
+						Match: esapi.PushSecretMatch{
+							SecretKey: "keep",
+							RemoteRef: esapi.PushSecretRemoteRef{
+								RemoteKey: "remote/keep",
+								Property:  "property",
+							},
+						},
+					},
+					"remote/delete/property": {
+						Match: esapi.PushSecretMatch{
+							SecretKey: "delete",
+							RemoteRef: esapi.PushSecretRemoteRef{
+								RemoteKey: "remote/delete",
+								Property:  "property",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+
+	newMap := esapi.SyncedPushSecretsMap{
+		"ClusterProvider/cluster-provider": {
+			"remote/keep/property": ps.Status.SyncedPushSecrets["ClusterProvider/cluster-provider"]["remote/keep/property"],
+		},
+	}
+
+	result, err := r.DeleteSecretFromProvidersV2(context.Background(), ps, newMap, map[esapi.PushSecretStoreRef]interface{}{
+		{Name: "cluster-provider", Kind: esv1.ClusterProviderKindStr}: clusterProvider,
+	})
+	if err != nil {
+		t.Fatalf("DeleteSecretFromProvidersV2() error = %v", err)
+	}
+
+	if server.deleteRequest == nil {
+		t.Fatal("expected delete request to be recorded")
+	}
+	if server.deleteRequest.SourceNamespace != providerNamespace {
+		t.Fatalf("unexpected source namespace: %q", server.deleteRequest.SourceNamespace)
+	}
+	if server.deleteRequest.ProviderRef == nil || server.deleteRequest.ProviderRef.Namespace != providerNamespace {
+		t.Fatalf("unexpected provider ref: %#v", server.deleteRequest.ProviderRef)
+	}
+	if server.deleteRequest.RemoteRef == nil || server.deleteRequest.RemoteRef.RemoteKey != "remote/delete" || server.deleteRequest.RemoteRef.Property != "property" {
+		t.Fatalf("unexpected delete ref: %#v", server.deleteRequest.RemoteRef)
+	}
+
+	storeState, ok := result["ClusterProvider/cluster-provider"]
+	if !ok {
+		t.Fatalf("expected synced state for cluster provider, got %#v", result)
+	}
+	if len(storeState) != 1 {
+		t.Fatalf("expected one remaining synced entry, got %#v", storeState)
+	}
+	if _, ok := storeState["remote/keep/property"]; !ok {
+		t.Fatalf("expected keep entry to remain, got %#v", storeState)
+	}
+	if _, ok := storeState["remote/delete/property"]; ok {
+		t.Fatalf("expected delete entry to be removed, got %#v", storeState)
+	}
+}
+
 func newPushSecretTestScheme(t *testing.T) *runtime.Scheme {
 	t.Helper()