|
1 | | -/* |
2 | | -Copyright 2025. |
3 | | -
|
4 | | -Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | -you may not use this file except in compliance with the License. |
6 | | -You may obtain a copy of the License at |
7 | | -
|
8 | | - http://www.apache.org/licenses/LICENSE-2.0 |
9 | | -
|
10 | | -Unless required by applicable law or agreed to in writing, software |
11 | | -distributed under the License is distributed on an "AS IS" BASIS, |
12 | | -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | -See the License for the specific language governing permissions and |
14 | | -limitations under the License. |
15 | | -*/ |
16 | | - |
17 | 1 | package e2e |
18 | 2 |
|
19 | 3 | import ( |
| 4 | + "context" |
20 | 5 | "fmt" |
21 | | - "os/exec" |
22 | | - "time" |
23 | | - |
24 | 6 | . "github.com/onsi/ginkgo/v2" |
25 | 7 | . "github.com/onsi/gomega" |
| 8 | + utils "github.com/openshift/external-secrets-operator/test/utils" |
| 9 | + corev1 "k8s.io/api/core/v1" |
| 10 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 11 | + "os" |
| 12 | + "testing" |
| 13 | + "time" |
| 14 | +) |
26 | 15 |
|
27 | | - "github.com/openshift/external-secrets-operator/test/utils" |
| 16 | +const ( |
| 17 | + namespace = "external-secrets-operator" |
| 18 | + secretStoreFile = "testdata/aws_secret_store.yaml" |
| 19 | + externalSecretFile = "testdata/aws_external_secret.yaml" |
28 | 20 | ) |
29 | 21 |
|
30 | | -const namespace = "external-secrets-operator" |
| 22 | +var _ = Describe("External Secrets Operator", Ordered, func() { |
| 23 | + |
| 24 | + var ( |
| 25 | + ctx = context.TODO() |
| 26 | + loader utils.DynamicResourceLoader |
| 27 | + ) |
31 | 28 |
|
32 | | -var _ = Describe("controller", Ordered, func() { |
33 | 29 | BeforeAll(func() { |
34 | | - //TODO: add any pre-reqs for the tests. |
| 30 | + loader = utils.NewDynamicResourceLoader(ctx, &testing.T{}) |
| 31 | + |
| 32 | + // Create ExternalSecret resource |
| 33 | + loader.CreateFromFile(loadFromFile, "testdata/external_secret.yaml", namespace) |
35 | 34 | }) |
36 | 35 |
|
37 | 36 | AfterAll(func() { |
38 | | - //TODO: add any clean up required after the tests. |
| 37 | + loader.DeleteFromFile(loadFromFile, "testdata/external_secret.yaml", namespace) |
39 | 38 | }) |
40 | 39 |
|
41 | 40 | Context("Operator", func() { |
42 | | - It("should run successfully", func() { |
43 | | - var controllerPodName string |
44 | | - |
45 | | - By("validating that the controller-manager pod is running as expected") |
46 | | - verifyControllerUp := func() error { |
47 | | - // Get pod name |
48 | | - |
49 | | - cmd := exec.Command("oc", "get", |
50 | | - "pods", "-l", "control-plane=controller-manager", |
51 | | - "-o", "go-template={{ range .items }}"+ |
52 | | - "{{ if not .metadata.deletionTimestamp }}"+ |
53 | | - "{{ .metadata.name }}"+ |
54 | | - "{{ \"\\n\" }}{{ end }}{{ end }}", |
55 | | - "-n", namespace, |
56 | | - ) |
57 | | - |
58 | | - podOutput, err := utils.Run(cmd) |
| 41 | + It("should have controller pod running", func() { |
| 42 | + verifyControllerPod := func() error { |
| 43 | + pods, err := loader.KubeClient.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{ |
| 44 | + LabelSelector: "control-plane=controller-manager", |
| 45 | + }) |
59 | 46 | ExpectWithOffset(2, err).NotTo(HaveOccurred()) |
60 | | - podNames := utils.GetNonEmptyLines(string(podOutput)) |
61 | | - if len(podNames) != 1 { |
62 | | - return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames)) |
| 47 | + |
| 48 | + var runningPods []corev1.Pod |
| 49 | + for _, pod := range pods.Items { |
| 50 | + if pod.DeletionTimestamp == nil && pod.Status.Phase == corev1.PodRunning { |
| 51 | + runningPods = append(runningPods, pod) |
| 52 | + } |
63 | 53 | } |
64 | | - controllerPodName = podNames[0] |
65 | | - ExpectWithOffset(2, controllerPodName).Should(ContainSubstring("controller-manager")) |
66 | | - |
67 | | - // Validate pod status |
68 | | - cmd = exec.Command("oc", "get", |
69 | | - "pods", controllerPodName, "-o", "jsonpath={.status.phase}", |
70 | | - "-n", namespace, |
71 | | - ) |
72 | | - status, err := utils.Run(cmd) |
73 | | - ExpectWithOffset(2, err).NotTo(HaveOccurred()) |
74 | | - if string(status) != "Running" { |
75 | | - return fmt.Errorf("controller pod in %s status", status) |
| 54 | + |
| 55 | + if len(runningPods) != 1 { |
| 56 | + return fmt.Errorf("expected 1 running controller pod, got %d", len(runningPods)) |
76 | 57 | } |
| 58 | + |
| 59 | + ExpectWithOffset(2, runningPods[0].Name).To(ContainSubstring("controller-manager")) |
| 60 | + fmt.Println(runningPods[0].Name) |
77 | 61 | return nil |
78 | 62 | } |
79 | | - EventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed()) |
| 63 | + |
| 64 | + EventuallyWithOffset(1, verifyControllerPod, time.Minute, time.Second).Should(Succeed()) |
| 65 | + }) |
| 66 | + }) |
| 67 | + |
| 68 | + Context("AWS SecretStore", func() { |
| 69 | + BeforeEach(func() { |
| 70 | + loader.CreateFromFile(loadFromFile, secretStoreFile, namespace) |
| 71 | + loader.CreateFromFile(loadFromFile, externalSecretFile, namespace) |
| 72 | + |
| 73 | + }) |
| 74 | + |
| 75 | + AfterEach(func() { |
| 76 | + // Clean up SecretStore |
| 77 | + loader.DeleteFromFile(loadFromFile, secretStoreFile, namespace) |
| 78 | + // Clean up ExternalStore |
| 79 | + loader.DeleteFromFile(loadFromFile, externalSecretFile, namespace) |
| 80 | + |
| 81 | + }) |
| 82 | + |
| 83 | + It("should synchronize secrets from AWS Secrets Manager", func() { |
| 84 | + By("verifying the synchronization of the secret") |
| 85 | + Eventually(func() error { |
| 86 | + k8sSecret, err := loader.KubeClient.CoreV1().Secrets(namespace).Get(ctx, "aws-secret", metav1.GetOptions{}) |
| 87 | + |
| 88 | + secretsList, err := loader.KubeClient.CoreV1().Secrets("kube-system").List(ctx, metav1.ListOptions{}) |
| 89 | + Expect(err).NotTo(HaveOccurred()) |
| 90 | + |
| 91 | + fmt.Println("Secrets in kube-system:") |
| 92 | + for _, s := range secretsList.Items { |
| 93 | + fmt.Println("-", s.Name) |
| 94 | + } |
| 95 | + if err != nil { |
| 96 | + return fmt.Errorf("failed to get secret: %v", err) |
| 97 | + } |
| 98 | + |
| 99 | + if string(k8sSecret.Data["aws_secret_access_key"]) == "" { |
| 100 | + return fmt.Errorf("secret data is empty") |
| 101 | + } |
| 102 | + |
| 103 | + decodedValue, err := os.ReadFile("testdata/expected_value.yaml") |
| 104 | + if err != nil { |
| 105 | + return fmt.Errorf("failed to read expected secret value: %v", err) |
| 106 | + } |
| 107 | + |
| 108 | + if string(k8sSecret.Data["aws_secret_access_key"]) != string(decodedValue) { |
| 109 | + return fmt.Errorf("secret value does not match expected") |
| 110 | + } |
| 111 | + return nil |
| 112 | + }, time.Minute, time.Second).Should(Succeed()) |
80 | 113 | }) |
81 | 114 | }) |
82 | 115 | }) |
| 116 | + |
| 117 | +func loadFromFile(name string) ([]byte, error) { |
| 118 | + return os.ReadFile(name) |
| 119 | +} |
0 commit comments