externalsecret_controller_test.go 20 KB

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