testcase.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. Copyright © The ESO Authors
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. https://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package framework
  14. import (
  15. "time"
  16. //nolint
  17. "github.com/external-secrets/external-secrets-e2e/framework/log"
  18. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  19. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  20. . "github.com/onsi/ginkgo/v2"
  21. . "github.com/onsi/gomega"
  22. v1 "k8s.io/api/core/v1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "sigs.k8s.io/controller-runtime/pkg/client"
  25. )
  26. var TargetSecretName = "target-secret"
  27. // TestCase contains the test infra to run a table driven test.
  28. type TestCase struct {
  29. Framework *Framework
  30. ExternalSecret *esv1.ExternalSecret
  31. PushSecret *esv1alpha1.PushSecret
  32. PushSecretSource *v1.Secret
  33. AdditionalObjects []client.Object
  34. Secrets map[string]SecretEntry
  35. ExpectedSecret *v1.Secret
  36. Prepare func(*TestCase, SecretStoreProvider)
  37. ProviderOverride SecretStoreProvider
  38. AfterSync func(SecretStoreProvider, *v1.Secret)
  39. VerifyPushSecretOutcome func(ps *esv1alpha1.PushSecret, pushClient esv1.SecretsClient)
  40. }
  41. type SecretEntry struct {
  42. Value string
  43. Tags map[string]string
  44. }
  45. // SecretStoreProvider is a interface that must be implemented
  46. // by a provider that runs the e2e test.
  47. type SecretStoreProvider interface {
  48. CreateSecret(key string, val SecretEntry)
  49. DeleteSecret(key string)
  50. }
  51. // TableFuncWithExternalSecret returns the main func that runs a TestCase in a table driven test.
  52. func TableFuncWithExternalSecret(f *Framework, prov SecretStoreProvider) func(...func(*TestCase)) {
  53. return func(tweaks ...func(*TestCase)) {
  54. // make default test case
  55. // and apply customization to it
  56. tc := makeDefaultExternalSecretTestCase(f)
  57. for _, tweak := range tweaks {
  58. tweak(tc)
  59. }
  60. prov = prepareTestCase(tc, prov)
  61. // create secrets & defer delete
  62. var deferRemoveKeys []string
  63. for k, v := range tc.Secrets {
  64. key := k
  65. prov.CreateSecret(key, v)
  66. deferRemoveKeys = append(deferRemoveKeys, key)
  67. }
  68. defer func() {
  69. for _, k := range deferRemoveKeys {
  70. prov.DeleteSecret(k)
  71. }
  72. }()
  73. // create additional objects
  74. generateAdditionalObjects(tc)
  75. // create v1alpha1 external secret, if provided
  76. createProvidedExternalSecret(tc)
  77. // wait for Kind=Secret to have the expected data
  78. executeAfterSync(tc, f, prov)
  79. }
  80. }
  81. func executeAfterSync(tc *TestCase, f *Framework, prov SecretStoreProvider) {
  82. if tc.ExpectedSecret != nil {
  83. secret, err := tc.Framework.WaitForSecretValue(tc.Framework.Namespace.Name, externalSecretTargetName(tc), tc.ExpectedSecret)
  84. if err != nil {
  85. f.printESDebugLogs(tc.ExternalSecret.Name, tc.ExternalSecret.Namespace)
  86. log.Logf("Did not match. Expected: %+v, Got: %+v", tc.ExpectedSecret, secret)
  87. }
  88. Expect(err).ToNot(HaveOccurred())
  89. tc.AfterSync(prov, secret)
  90. } else {
  91. tc.AfterSync(prov, nil)
  92. }
  93. }
  94. func externalSecretTargetName(tc *TestCase) string {
  95. if tc == nil || tc.ExternalSecret == nil {
  96. return TargetSecretName
  97. }
  98. if tc.ExternalSecret.Spec.Target.Name != "" {
  99. return tc.ExternalSecret.Spec.Target.Name
  100. }
  101. if tc.ExternalSecret.Name != "" {
  102. return tc.ExternalSecret.Name
  103. }
  104. return TargetSecretName
  105. }
  106. func generateAdditionalObjects(tc *TestCase) {
  107. if tc.AdditionalObjects != nil {
  108. for _, obj := range tc.AdditionalObjects {
  109. err := tc.Framework.CRClient.Create(GinkgoT().Context(), obj)
  110. Expect(err).ToNot(HaveOccurred())
  111. }
  112. }
  113. }
  114. func createProvidedExternalSecret(tc *TestCase) {
  115. if tc.ExternalSecret == nil {
  116. return
  117. }
  118. err := tc.Framework.CRClient.Create(GinkgoT().Context(), tc.ExternalSecret)
  119. Expect(err).ToNot(HaveOccurred())
  120. }
  121. // TableFuncWithPushSecret returns the main func that runs a TestCase in a table driven test for push secrets.
  122. func TableFuncWithPushSecret(f *Framework, prov SecretStoreProvider, pushClient esv1.SecretsClient) func(...func(*TestCase)) {
  123. return func(tweaks ...func(*TestCase)) {
  124. var err error
  125. // make default test case
  126. // and apply customization to it
  127. tc := makeDefaultPushSecretTestCase(f)
  128. for _, tweak := range tweaks {
  129. tweak(tc)
  130. }
  131. prov = prepareTestCase(tc, prov)
  132. // additional objects
  133. generateAdditionalObjects(tc)
  134. if tc.PushSecretSource != nil {
  135. err := tc.Framework.CRClient.Create(GinkgoT().Context(), tc.PushSecretSource)
  136. Expect(err).ToNot(HaveOccurred())
  137. }
  138. // create v1alpha1 push secret, if provided
  139. if tc.PushSecret != nil {
  140. // create v1beta1 external secret otherwise
  141. err = tc.Framework.CRClient.Create(GinkgoT().Context(), tc.PushSecret)
  142. Expect(err).ToNot(HaveOccurred())
  143. }
  144. // Run verification on the secret that push secret created or not.
  145. tc.VerifyPushSecretOutcome(tc.PushSecret, pushClient)
  146. }
  147. }
  148. func prepareTestCase(tc *TestCase, prov SecretStoreProvider) SecretStoreProvider {
  149. prov = effectiveTestCaseProvider(tc, prov)
  150. if tc.Prepare != nil {
  151. tc.Prepare(tc, prov)
  152. }
  153. return effectiveTestCaseProvider(tc, prov)
  154. }
  155. func effectiveTestCaseProvider(tc *TestCase, prov SecretStoreProvider) SecretStoreProvider {
  156. if tc.ProviderOverride != nil {
  157. return tc.ProviderOverride
  158. }
  159. return prov
  160. }
  161. func makeDefaultExternalSecretTestCase(f *Framework) *TestCase {
  162. return &TestCase{
  163. AfterSync: func(ssp SecretStoreProvider, s *v1.Secret) {},
  164. Framework: f,
  165. ExternalSecret: &esv1.ExternalSecret{
  166. ObjectMeta: metav1.ObjectMeta{
  167. Name: "e2e-es",
  168. Namespace: f.Namespace.Name,
  169. },
  170. Spec: esv1.ExternalSecretSpec{
  171. RefreshInterval: &metav1.Duration{Duration: time.Second * 5},
  172. SecretStoreRef: esv1.SecretStoreRef{
  173. Name: f.Namespace.Name,
  174. Kind: f.DefaultSecretStoreRefKind,
  175. },
  176. Target: esv1.ExternalSecretTarget{
  177. Name: TargetSecretName,
  178. },
  179. },
  180. },
  181. }
  182. }
  183. func makeDefaultPushSecretTestCase(f *Framework) *TestCase {
  184. return &TestCase{
  185. Framework: f,
  186. PushSecret: &esv1alpha1.PushSecret{
  187. ObjectMeta: metav1.ObjectMeta{
  188. Name: "e2e-ps",
  189. Namespace: f.Namespace.Name,
  190. },
  191. Spec: esv1alpha1.PushSecretSpec{
  192. RefreshInterval: &metav1.Duration{Duration: time.Second * 5},
  193. SecretStoreRefs: []esv1alpha1.PushSecretStoreRef{
  194. {
  195. Name: f.Namespace.Name,
  196. Kind: f.DefaultPushSecretStoreRefKind,
  197. APIVersion: f.DefaultPushSecretStoreRefAPIVersion,
  198. },
  199. },
  200. },
  201. },
  202. }
  203. }