externalsecret_controller_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package externalsecret
  13. import (
  14. "context"
  15. "fmt"
  16. "time"
  17. . "github.com/onsi/ginkgo"
  18. . "github.com/onsi/gomega"
  19. v1 "k8s.io/api/core/v1"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. "k8s.io/apimachinery/pkg/types"
  22. "k8s.io/apimachinery/pkg/util/wait"
  23. "sigs.k8s.io/controller-runtime/pkg/client"
  24. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  25. "github.com/external-secrets/external-secrets/pkg/provider"
  26. "github.com/external-secrets/external-secrets/pkg/provider/fake"
  27. "github.com/external-secrets/external-secrets/pkg/provider/schema"
  28. dto "github.com/prometheus/client_model/go"
  29. )
  30. var (
  31. fakeProvider *fake.Client
  32. metric dto.Metric
  33. )
  34. var _ = Describe("ExternalSecret controller", func() {
  35. const (
  36. ExternalSecretName = "test-es"
  37. ExternalSecretStore = "test-store"
  38. ExternalSecretTargetSecretName = "test-secret"
  39. timeout = time.Second * 5
  40. interval = time.Millisecond * 250
  41. )
  42. var ExternalSecretNamespace string
  43. BeforeEach(func() {
  44. var err error
  45. ExternalSecretNamespace, err = CreateNamespace("test-ns", k8sClient)
  46. Expect(err).ToNot(HaveOccurred())
  47. Expect(k8sClient.Create(context.Background(), &esv1alpha1.SecretStore{
  48. ObjectMeta: metav1.ObjectMeta{
  49. Name: ExternalSecretStore,
  50. Namespace: ExternalSecretNamespace,
  51. },
  52. Spec: esv1alpha1.SecretStoreSpec{
  53. Provider: &esv1alpha1.SecretStoreProvider{
  54. AWS: &esv1alpha1.AWSProvider{
  55. Service: esv1alpha1.AWSServiceSecretsManager,
  56. },
  57. },
  58. },
  59. })).To(Succeed())
  60. metric.Reset()
  61. syncCallsTotal.Reset()
  62. syncCallsError.Reset()
  63. })
  64. AfterEach(func() {
  65. Expect(k8sClient.Delete(context.Background(), &v1.Namespace{
  66. ObjectMeta: metav1.ObjectMeta{
  67. Name: ExternalSecretNamespace,
  68. },
  69. }, client.PropagationPolicy(metav1.DeletePropagationBackground)), client.GracePeriodSeconds(0)).To(Succeed())
  70. Expect(k8sClient.Delete(context.Background(), &esv1alpha1.SecretStore{
  71. ObjectMeta: metav1.ObjectMeta{
  72. Name: ExternalSecretStore,
  73. Namespace: ExternalSecretNamespace,
  74. },
  75. }, client.PropagationPolicy(metav1.DeletePropagationBackground)), client.GracePeriodSeconds(0)).To(Succeed())
  76. })
  77. Context("When creating an ExternalSecret", func() {
  78. It("should set the condition eventually", func() {
  79. ctx := context.Background()
  80. es := &esv1alpha1.ExternalSecret{
  81. ObjectMeta: metav1.ObjectMeta{
  82. Name: ExternalSecretName,
  83. Namespace: ExternalSecretNamespace,
  84. },
  85. Spec: esv1alpha1.ExternalSecretSpec{
  86. SecretStoreRef: esv1alpha1.SecretStoreRef{
  87. Name: ExternalSecretStore,
  88. },
  89. Target: esv1alpha1.ExternalSecretTarget{
  90. Name: ExternalSecretTargetSecretName,
  91. },
  92. },
  93. }
  94. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  95. esLookupKey := types.NamespacedName{Name: ExternalSecretName, Namespace: ExternalSecretNamespace}
  96. createdES := &esv1alpha1.ExternalSecret{}
  97. Eventually(func() bool {
  98. err := k8sClient.Get(ctx, esLookupKey, createdES)
  99. if err != nil {
  100. return false
  101. }
  102. cond := GetExternalSecretCondition(createdES.Status, esv1alpha1.ExternalSecretReady)
  103. if cond == nil || cond.Status != v1.ConditionTrue {
  104. return false
  105. }
  106. return true
  107. }, timeout, interval).Should(BeTrue())
  108. })
  109. It("should increment the syncCallsTotal metric", func() {
  110. ctx := context.Background()
  111. es := &esv1alpha1.ExternalSecret{
  112. ObjectMeta: metav1.ObjectMeta{
  113. Name: ExternalSecretName,
  114. Namespace: ExternalSecretNamespace,
  115. },
  116. Spec: esv1alpha1.ExternalSecretSpec{
  117. SecretStoreRef: esv1alpha1.SecretStoreRef{
  118. Name: ExternalSecretStore,
  119. },
  120. Target: esv1alpha1.ExternalSecretTarget{
  121. Name: ExternalSecretTargetSecretName,
  122. },
  123. },
  124. }
  125. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  126. // When creating a new ExternalSecret, the Reconcile loop executes twice
  127. // due the call to `controllerutil.SetControllerReference`
  128. expectedValue := 2.0
  129. Eventually(func() float64 {
  130. Expect(syncCallsTotal.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
  131. return metric.GetCounter().GetValue()
  132. }, timeout, interval).Should(Equal(expectedValue))
  133. })
  134. })
  135. Context("When updating an ExternalSecret", func() {
  136. It("should increment the syncCallsTotal metric", func() {
  137. ctx := context.Background()
  138. es := &esv1alpha1.ExternalSecret{
  139. ObjectMeta: metav1.ObjectMeta{
  140. Name: ExternalSecretName,
  141. Namespace: ExternalSecretNamespace,
  142. },
  143. Spec: esv1alpha1.ExternalSecretSpec{
  144. SecretStoreRef: esv1alpha1.SecretStoreRef{
  145. Name: ExternalSecretStore,
  146. },
  147. Target: esv1alpha1.ExternalSecretTarget{
  148. Name: ExternalSecretTargetSecretName,
  149. },
  150. },
  151. }
  152. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  153. Eventually(func() float64 {
  154. Expect(syncCallsTotal.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
  155. return metric.GetCounter().GetValue()
  156. }, timeout, interval).Should(Equal(2.0))
  157. createdES := &esv1alpha1.ExternalSecret{}
  158. Eventually(func() error {
  159. esLookupKey := types.NamespacedName{Name: ExternalSecretName, Namespace: ExternalSecretNamespace}
  160. err := k8sClient.Get(ctx, esLookupKey, createdES)
  161. if err != nil {
  162. return err
  163. }
  164. createdES.Spec.RefreshInterval = &metav1.Duration{Duration: 10 * time.Second}
  165. err = k8sClient.Update(ctx, createdES)
  166. if err != nil {
  167. return err
  168. }
  169. return nil
  170. }, timeout, interval).Should(Succeed())
  171. // 2 from the Create() + 1 from Update()
  172. expectedValue := 3.0
  173. Eventually(func() float64 {
  174. Expect(syncCallsTotal.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
  175. return metric.GetCounter().GetValue()
  176. }, timeout, interval).Should(Equal(expectedValue))
  177. })
  178. })
  179. Context("When syncing ExternalSecret value", func() {
  180. It("should set the secret value and sync labels/annotations", func() {
  181. ctx := context.Background()
  182. const targetProp = "targetProperty"
  183. const secretVal = "someValue"
  184. es := &esv1alpha1.ExternalSecret{
  185. ObjectMeta: metav1.ObjectMeta{
  186. Name: ExternalSecretName,
  187. Namespace: ExternalSecretNamespace,
  188. Labels: map[string]string{
  189. "fooobar": "bazz",
  190. "bazzing": "booze",
  191. },
  192. Annotations: map[string]string{
  193. "hihihih": "hehehe",
  194. "harharhra": "yallayalla",
  195. },
  196. },
  197. Spec: esv1alpha1.ExternalSecretSpec{
  198. SecretStoreRef: esv1alpha1.SecretStoreRef{
  199. Name: ExternalSecretStore,
  200. },
  201. Target: esv1alpha1.ExternalSecretTarget{
  202. Name: ExternalSecretTargetSecretName,
  203. },
  204. Data: []esv1alpha1.ExternalSecretData{
  205. {
  206. SecretKey: targetProp,
  207. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  208. Key: "barz",
  209. Property: "bang",
  210. },
  211. },
  212. },
  213. },
  214. }
  215. fakeProvider.WithGetSecret([]byte(secretVal), nil)
  216. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  217. secretLookupKey := types.NamespacedName{
  218. Name: ExternalSecretTargetSecretName,
  219. Namespace: ExternalSecretNamespace}
  220. syncedSecret := &v1.Secret{}
  221. Eventually(func() bool {
  222. err := k8sClient.Get(ctx, secretLookupKey, syncedSecret)
  223. if err != nil {
  224. return false
  225. }
  226. v := syncedSecret.Data[targetProp]
  227. return string(v) == secretVal
  228. }, timeout, interval).Should(BeTrue())
  229. Expect(syncedSecret.ObjectMeta.Labels).To(BeEquivalentTo(es.ObjectMeta.Labels))
  230. Expect(syncedSecret.ObjectMeta.Annotations).To(BeEquivalentTo(es.ObjectMeta.Annotations))
  231. })
  232. It("should refresh secret value", func() {
  233. ctx := context.Background()
  234. const targetProp = "targetProperty"
  235. const secretVal = "someValue"
  236. es := &esv1alpha1.ExternalSecret{
  237. ObjectMeta: metav1.ObjectMeta{
  238. Name: ExternalSecretName,
  239. Namespace: ExternalSecretNamespace,
  240. },
  241. Spec: esv1alpha1.ExternalSecretSpec{
  242. RefreshInterval: &metav1.Duration{Duration: time.Second},
  243. SecretStoreRef: esv1alpha1.SecretStoreRef{
  244. Name: ExternalSecretStore,
  245. },
  246. Target: esv1alpha1.ExternalSecretTarget{
  247. Name: ExternalSecretTargetSecretName,
  248. },
  249. Data: []esv1alpha1.ExternalSecretData{
  250. {
  251. SecretKey: targetProp,
  252. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  253. Key: "barz",
  254. },
  255. },
  256. },
  257. },
  258. }
  259. fakeProvider.WithGetSecret([]byte(secretVal), nil)
  260. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  261. secretLookupKey := types.NamespacedName{
  262. Name: ExternalSecretTargetSecretName,
  263. Namespace: ExternalSecretNamespace}
  264. syncedSecret := &v1.Secret{}
  265. Eventually(func() bool {
  266. err := k8sClient.Get(ctx, secretLookupKey, syncedSecret)
  267. if err != nil {
  268. return false
  269. }
  270. v := syncedSecret.Data[targetProp]
  271. return string(v) == secretVal
  272. }, timeout, interval).Should(BeTrue())
  273. newValue := "NEW VALUE"
  274. fakeProvider.WithGetSecret([]byte(newValue), nil)
  275. Eventually(func() bool {
  276. err := k8sClient.Get(ctx, secretLookupKey, syncedSecret)
  277. if err != nil {
  278. return false
  279. }
  280. v := syncedSecret.Data[targetProp]
  281. return string(v) == newValue
  282. }, timeout, interval).Should(BeTrue())
  283. })
  284. It("should fetch secrets using dataFrom", func() {
  285. ctx := context.Background()
  286. const secretVal = "someValue"
  287. es := &esv1alpha1.ExternalSecret{
  288. ObjectMeta: metav1.ObjectMeta{
  289. Name: ExternalSecretName,
  290. Namespace: ExternalSecretNamespace,
  291. },
  292. Spec: esv1alpha1.ExternalSecretSpec{
  293. SecretStoreRef: esv1alpha1.SecretStoreRef{
  294. Name: ExternalSecretStore,
  295. },
  296. Target: esv1alpha1.ExternalSecretTarget{
  297. Name: ExternalSecretTargetSecretName,
  298. },
  299. DataFrom: []esv1alpha1.ExternalSecretDataRemoteRef{
  300. {
  301. Key: "barz",
  302. },
  303. },
  304. },
  305. }
  306. fakeProvider.WithGetSecretMap(map[string][]byte{
  307. "foo": []byte("bar"),
  308. "baz": []byte("bang"),
  309. }, nil)
  310. fakeProvider.WithGetSecret([]byte(secretVal), nil)
  311. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  312. secretLookupKey := types.NamespacedName{
  313. Name: ExternalSecretTargetSecretName,
  314. Namespace: ExternalSecretNamespace}
  315. syncedSecret := &v1.Secret{}
  316. Eventually(func() bool {
  317. err := k8sClient.Get(ctx, secretLookupKey, syncedSecret)
  318. if err != nil {
  319. return false
  320. }
  321. x := syncedSecret.Data["foo"]
  322. y := syncedSecret.Data["baz"]
  323. return string(x) == "bar" && string(y) == "bang"
  324. }, timeout, interval).Should(BeTrue())
  325. })
  326. It("should set an error condition when provider errors", func() {
  327. ctx := context.Background()
  328. const targetProp = "targetProperty"
  329. es := &esv1alpha1.ExternalSecret{
  330. ObjectMeta: metav1.ObjectMeta{
  331. Name: ExternalSecretName,
  332. Namespace: ExternalSecretNamespace,
  333. },
  334. Spec: esv1alpha1.ExternalSecretSpec{
  335. SecretStoreRef: esv1alpha1.SecretStoreRef{
  336. Name: ExternalSecretStore,
  337. },
  338. Target: esv1alpha1.ExternalSecretTarget{
  339. Name: ExternalSecretTargetSecretName,
  340. },
  341. Data: []esv1alpha1.ExternalSecretData{
  342. {
  343. SecretKey: targetProp,
  344. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  345. Key: "barz",
  346. Property: "bang",
  347. },
  348. },
  349. },
  350. },
  351. }
  352. fakeProvider.WithGetSecret(nil, fmt.Errorf("artificial testing error"))
  353. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  354. esLookupKey := types.NamespacedName{
  355. Name: ExternalSecretName,
  356. Namespace: ExternalSecretNamespace}
  357. createdES := &esv1alpha1.ExternalSecret{}
  358. Eventually(func() bool {
  359. err := k8sClient.Get(ctx, esLookupKey, createdES)
  360. if err != nil {
  361. return false
  362. }
  363. // condition must be false
  364. cond := GetExternalSecretCondition(createdES.Status, esv1alpha1.ExternalSecretReady)
  365. if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1alpha1.ConditionReasonSecretSyncedError {
  366. return false
  367. }
  368. return true
  369. }, timeout, interval).Should(BeTrue())
  370. Eventually(func() float64 {
  371. Expect(syncCallsError.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
  372. return metric.GetCounter().GetValue()
  373. }, timeout, interval).Should(Equal(1.0))
  374. })
  375. It("should set an error condition when store does not exist", func() {
  376. ctx := context.Background()
  377. const targetProp = "targetProperty"
  378. es := &esv1alpha1.ExternalSecret{
  379. ObjectMeta: metav1.ObjectMeta{
  380. Name: ExternalSecretName,
  381. Namespace: ExternalSecretNamespace,
  382. },
  383. Spec: esv1alpha1.ExternalSecretSpec{
  384. SecretStoreRef: esv1alpha1.SecretStoreRef{
  385. Name: "storeshouldnotexist",
  386. },
  387. Target: esv1alpha1.ExternalSecretTarget{
  388. Name: ExternalSecretTargetSecretName,
  389. },
  390. Data: []esv1alpha1.ExternalSecretData{
  391. {
  392. SecretKey: targetProp,
  393. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  394. Key: "barz",
  395. Property: "bang",
  396. },
  397. },
  398. },
  399. },
  400. }
  401. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  402. esLookupKey := types.NamespacedName{
  403. Name: ExternalSecretName,
  404. Namespace: ExternalSecretNamespace}
  405. createdES := &esv1alpha1.ExternalSecret{}
  406. Eventually(func() bool {
  407. err := k8sClient.Get(ctx, esLookupKey, createdES)
  408. if err != nil {
  409. return false
  410. }
  411. // condition must be false
  412. cond := GetExternalSecretCondition(createdES.Status, esv1alpha1.ExternalSecretReady)
  413. if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1alpha1.ConditionReasonSecretSyncedError {
  414. return false
  415. }
  416. return true
  417. }, timeout, interval).Should(BeTrue())
  418. Eventually(func() float64 {
  419. Expect(syncCallsError.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
  420. return metric.GetCounter().GetValue()
  421. }, timeout, interval).Should(Equal(1.0))
  422. })
  423. It("should set an error condition when store provider constructor fails", func() {
  424. ctx := context.Background()
  425. const targetProp = "targetProperty"
  426. es := &esv1alpha1.ExternalSecret{
  427. ObjectMeta: metav1.ObjectMeta{
  428. Name: ExternalSecretName,
  429. Namespace: ExternalSecretNamespace,
  430. },
  431. Spec: esv1alpha1.ExternalSecretSpec{
  432. SecretStoreRef: esv1alpha1.SecretStoreRef{
  433. Name: ExternalSecretStore,
  434. },
  435. Target: esv1alpha1.ExternalSecretTarget{
  436. Name: ExternalSecretTargetSecretName,
  437. },
  438. Data: []esv1alpha1.ExternalSecretData{
  439. {
  440. SecretKey: targetProp,
  441. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  442. Key: "barz",
  443. Property: "bang",
  444. },
  445. },
  446. },
  447. },
  448. }
  449. fakeProvider.WithNew(func(context.Context, esv1alpha1.GenericStore, client.Client,
  450. string) (provider.SecretsClient, error) {
  451. return nil, fmt.Errorf("artificial constructor error")
  452. })
  453. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  454. esLookupKey := types.NamespacedName{
  455. Name: ExternalSecretName,
  456. Namespace: ExternalSecretNamespace}
  457. createdES := &esv1alpha1.ExternalSecret{}
  458. Eventually(func() bool {
  459. err := k8sClient.Get(ctx, esLookupKey, createdES)
  460. if err != nil {
  461. return false
  462. }
  463. // condition must be false
  464. cond := GetExternalSecretCondition(createdES.Status, esv1alpha1.ExternalSecretReady)
  465. if cond == nil || cond.Status != v1.ConditionFalse || cond.Reason != esv1alpha1.ConditionReasonSecretSyncedError {
  466. return false
  467. }
  468. return true
  469. }, timeout, interval).Should(BeTrue())
  470. Eventually(func() float64 {
  471. Expect(syncCallsError.WithLabelValues(ExternalSecretName, ExternalSecretNamespace).Write(&metric)).To(Succeed())
  472. return metric.GetCounter().GetValue()
  473. }, timeout, interval).Should(Equal(1.0))
  474. })
  475. It("should not process stores with mismatching controller field", func() {
  476. ctx := context.Background()
  477. storeName := "example-ts-foo"
  478. Expect(k8sClient.Create(context.Background(), &esv1alpha1.SecretStore{
  479. ObjectMeta: metav1.ObjectMeta{
  480. Name: storeName,
  481. Namespace: ExternalSecretNamespace,
  482. },
  483. Spec: esv1alpha1.SecretStoreSpec{
  484. Controller: "some-other-controller",
  485. Provider: &esv1alpha1.SecretStoreProvider{
  486. AWS: &esv1alpha1.AWSProvider{
  487. Service: esv1alpha1.AWSServiceSecretsManager,
  488. },
  489. },
  490. },
  491. })).To(Succeed())
  492. defer func() {
  493. Expect(k8sClient.Delete(context.Background(), &esv1alpha1.SecretStore{
  494. ObjectMeta: metav1.ObjectMeta{
  495. Name: storeName,
  496. Namespace: ExternalSecretNamespace,
  497. },
  498. })).To(Succeed())
  499. }()
  500. es := &esv1alpha1.ExternalSecret{
  501. ObjectMeta: metav1.ObjectMeta{
  502. Name: ExternalSecretName,
  503. Namespace: ExternalSecretNamespace,
  504. },
  505. Spec: esv1alpha1.ExternalSecretSpec{
  506. SecretStoreRef: esv1alpha1.SecretStoreRef{
  507. Name: storeName,
  508. },
  509. Target: esv1alpha1.ExternalSecretTarget{
  510. Name: ExternalSecretTargetSecretName,
  511. },
  512. Data: []esv1alpha1.ExternalSecretData{
  513. {
  514. SecretKey: "doesnothing",
  515. RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
  516. Key: "barz",
  517. Property: "bang",
  518. },
  519. },
  520. },
  521. },
  522. }
  523. Expect(k8sClient.Create(ctx, es)).Should(Succeed())
  524. secretLookupKey := types.NamespacedName{
  525. Name: ExternalSecretName,
  526. Namespace: ExternalSecretNamespace,
  527. }
  528. // COND
  529. createdES := &esv1alpha1.ExternalSecret{}
  530. Consistently(func() bool {
  531. err := k8sClient.Get(ctx, secretLookupKey, createdES)
  532. if err != nil {
  533. return false
  534. }
  535. cond := GetExternalSecretCondition(createdES.Status, esv1alpha1.ExternalSecretReady)
  536. return cond == nil
  537. }, timeout, interval).Should(BeTrue())
  538. })
  539. })
  540. })
  541. // CreateNamespace creates a new namespace in the cluster.
  542. func CreateNamespace(baseName string, c client.Client) (string, error) {
  543. genName := fmt.Sprintf("ctrl-test-%v", baseName)
  544. ns := &v1.Namespace{
  545. ObjectMeta: metav1.ObjectMeta{
  546. GenerateName: genName,
  547. },
  548. }
  549. var err error
  550. err = wait.Poll(time.Second, 10*time.Second, func() (bool, error) {
  551. err = c.Create(context.Background(), ns)
  552. if err != nil {
  553. return false, nil
  554. }
  555. return true, nil
  556. })
  557. if err != nil {
  558. return "", err
  559. }
  560. return ns.Name, nil
  561. }
  562. func init() {
  563. fakeProvider = fake.New()
  564. schema.ForceRegister(fakeProvider, &esv1alpha1.SecretStoreProvider{
  565. AWS: &esv1alpha1.AWSProvider{
  566. Service: esv1alpha1.AWSServiceSecretsManager,
  567. },
  568. })
  569. }