externalsecret_controller_test.go 21 KB

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