eso_v2_mutators_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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 addon
  14. import (
  15. "regexp"
  16. "strconv"
  17. "testing"
  18. )
  19. func TestWithV2FakeProvider(t *testing.T) {
  20. t.Setenv("VERSION", "test-version")
  21. eso := NewESO(WithV2FakeProvider())
  22. assertV2ProviderBaseVars(t, eso.HelmChart)
  23. assertVarValue(t, eso.HelmChart, "providers.enabled", "true")
  24. assertProvider(
  25. t,
  26. eso.HelmChart,
  27. "fake",
  28. "fake",
  29. "ghcr.io/external-secrets/provider-fake",
  30. "test-version",
  31. )
  32. assertSequentialProviderIndexes(t, eso.HelmChart)
  33. providers := providerEntries(t, eso.HelmChart)
  34. if len(providers) != 1 {
  35. t.Fatalf("expected exactly one provider entry, got %d", len(providers))
  36. }
  37. if providers[0].Name != "fake" {
  38. t.Fatalf("expected fake to be at index 0 when standalone, got index 0 name %q", providers[0].Name)
  39. }
  40. }
  41. func TestWithV2AWSProvider(t *testing.T) {
  42. t.Setenv("VERSION", "test-version")
  43. eso := NewESO(WithV2AWSProvider())
  44. assertV2ProviderBaseVars(t, eso.HelmChart)
  45. assertVarValue(t, eso.HelmChart, "providers.enabled", "true")
  46. assertProvider(
  47. t,
  48. eso.HelmChart,
  49. "aws",
  50. "aws",
  51. "ghcr.io/external-secrets/provider-aws",
  52. "test-version",
  53. )
  54. assertSequentialProviderIndexes(t, eso.HelmChart)
  55. providers := providerEntries(t, eso.HelmChart)
  56. if len(providers) != 1 {
  57. t.Fatalf("expected exactly one provider entry, got %d", len(providers))
  58. }
  59. if providers[0].Name != "aws" {
  60. t.Fatalf("expected aws to be at index 0 when standalone, got index 0 name %q", providers[0].Name)
  61. }
  62. }
  63. func TestWithV2GCPProvider(t *testing.T) {
  64. t.Setenv("VERSION", "test-version")
  65. eso := NewESO(WithV2GCPProvider())
  66. assertV2ProviderBaseVars(t, eso.HelmChart)
  67. assertVarValue(t, eso.HelmChart, "providers.enabled", "true")
  68. assertProvider(
  69. t,
  70. eso.HelmChart,
  71. "gcp",
  72. "gcp",
  73. "ghcr.io/external-secrets/provider-gcp",
  74. "test-version",
  75. )
  76. assertSequentialProviderIndexes(t, eso.HelmChart)
  77. providers := providerEntries(t, eso.HelmChart)
  78. if len(providers) != 1 {
  79. t.Fatalf("expected exactly one provider entry, got %d", len(providers))
  80. }
  81. if providers[0].Name != "gcp" {
  82. t.Fatalf("expected gcp to be at index 0 when standalone, got index 0 name %q", providers[0].Name)
  83. }
  84. }
  85. func TestWithV2ProvidersComposeIncludesAWS(t *testing.T) {
  86. t.Setenv("VERSION", "test-version")
  87. eso := NewESO(
  88. WithV2Namespace(),
  89. WithV2KubernetesProvider(),
  90. WithV2FakeProvider(),
  91. WithV2AWSProvider(),
  92. WithV2GCPProvider(),
  93. )
  94. if eso.HelmChart.Namespace != v2HelmNamespace {
  95. t.Fatalf("expected namespace %q, got %q", v2HelmNamespace, eso.HelmChart.Namespace)
  96. }
  97. if eso.HelmChart.ReleaseName != v2HelmReleaseName {
  98. t.Fatalf("expected release name %q, got %q", v2HelmReleaseName, eso.HelmChart.ReleaseName)
  99. }
  100. if !containsArg(eso.HelmChart.Args, "--create-namespace") {
  101. t.Fatalf("expected --create-namespace arg, got %v", eso.HelmChart.Args)
  102. }
  103. assertV2ProviderBaseVars(t, eso.HelmChart)
  104. assertVarValue(t, eso.HelmChart, "providers.enabled", "true")
  105. assertProvider(
  106. t,
  107. eso.HelmChart,
  108. "kubernetes",
  109. "kubernetes",
  110. "ghcr.io/external-secrets/provider-kubernetes",
  111. "test-version",
  112. )
  113. assertProvider(
  114. t,
  115. eso.HelmChart,
  116. "fake",
  117. "fake",
  118. "ghcr.io/external-secrets/provider-fake",
  119. "test-version",
  120. )
  121. assertProvider(
  122. t,
  123. eso.HelmChart,
  124. "aws",
  125. "aws",
  126. "ghcr.io/external-secrets/provider-aws",
  127. "test-version",
  128. )
  129. assertProvider(
  130. t,
  131. eso.HelmChart,
  132. "gcp",
  133. "gcp",
  134. "ghcr.io/external-secrets/provider-gcp",
  135. "test-version",
  136. )
  137. assertSequentialProviderIndexes(t, eso.HelmChart)
  138. providers := providerEntries(t, eso.HelmChart)
  139. if providers[0].Name != "kubernetes" {
  140. t.Fatalf("expected kubernetes to remain first provider entry, got %q at index 0", providers[0].Name)
  141. }
  142. if providers[1].Name != "fake" {
  143. t.Fatalf("expected fake to be second provider entry, got %q at index 1", providers[1].Name)
  144. }
  145. if providers[2].Name != "aws" {
  146. t.Fatalf("expected aws to be third provider entry, got %q at index 2", providers[2].Name)
  147. }
  148. if providers[3].Name != "gcp" {
  149. t.Fatalf("expected gcp to be fourth provider entry, got %q at index 3", providers[3].Name)
  150. }
  151. }
  152. func TestWithV2FakeProviderDoesNotDuplicateOnRepeat(t *testing.T) {
  153. t.Setenv("VERSION", "test-version")
  154. eso := NewESO(WithV2FakeProvider(), WithV2FakeProvider())
  155. providers := providerEntries(t, eso.HelmChart)
  156. if len(providers) != 1 {
  157. t.Fatalf("expected one provider entry after applying fake mutator twice, got %d", len(providers))
  158. }
  159. if providers[0].Name != "fake" {
  160. t.Fatalf("expected fake provider at index 0 after repeat application, got %q", providers[0].Name)
  161. }
  162. assertProvider(t, eso.HelmChart, "fake", "fake", "ghcr.io/external-secrets/provider-fake", "test-version")
  163. }
  164. func TestWithV2FakeProviderUpdatesExistingEntryInPlace(t *testing.T) {
  165. t.Setenv("VERSION", "test-version")
  166. eso := NewESO()
  167. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].name", Value: "fake"})
  168. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].type", Value: "fake"})
  169. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].enabled", Value: "false"})
  170. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].replicaCount", Value: "9"})
  171. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].image.repository", Value: "example.invalid/old-fake"})
  172. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].image.tag", Value: "old-tag"})
  173. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.list[3].image.pullPolicy", Value: "Always"})
  174. WithV2FakeProvider()(eso)
  175. providers := providerEntries(t, eso.HelmChart)
  176. if len(providers) != 1 {
  177. t.Fatalf("expected one fake provider entry after in-place update, got %d", len(providers))
  178. }
  179. if providers[3].Name != "fake" {
  180. t.Fatalf("expected fake provider to stay at index 3, got %q", providers[3].Name)
  181. }
  182. assertProvider(t, eso.HelmChart, "fake", "fake", "ghcr.io/external-secrets/provider-fake", "test-version")
  183. }
  184. func TestWithV2FakeProviderEnforcesRequiredFlags(t *testing.T) {
  185. t.Setenv("VERSION", "test-version")
  186. eso := NewESO()
  187. setOrAppendVar(eso.HelmChart, StringTuple{Key: "replicaCount", Value: "7"})
  188. setOrAppendVar(eso.HelmChart, StringTuple{Key: "v2.enabled", Value: "false"})
  189. setOrAppendVar(eso.HelmChart, StringTuple{Key: "crds.createProvider", Value: "false"})
  190. setOrAppendVar(eso.HelmChart, StringTuple{Key: "crds.createClusterProvider", Value: "false"})
  191. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.enabled", Value: "false"})
  192. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providerDefaults.replicaCount", Value: "8"})
  193. WithV2FakeProvider()(eso)
  194. assertVarValue(t, eso.HelmChart, "replicaCount", "7")
  195. assertVarValue(t, eso.HelmChart, "v2.enabled", "true")
  196. assertVarValue(t, eso.HelmChart, "crds.createProvider", "true")
  197. assertVarValue(t, eso.HelmChart, "crds.createClusterProvider", "true")
  198. assertVarValue(t, eso.HelmChart, "providers.enabled", "true")
  199. assertVarValue(t, eso.HelmChart, "providerDefaults.replicaCount", "8")
  200. }
  201. func TestWithV2ProviderServiceAccountOverridesAWSInPlace(t *testing.T) {
  202. t.Setenv("VERSION", "test-version")
  203. eso := NewESO(WithV2AWSProvider())
  204. WithV2ProviderServiceAccount("aws", "irsa-sa")(eso)
  205. assertVarValue(t, eso.HelmChart, "providers.list[0].serviceAccount.create", "false")
  206. assertVarValue(t, eso.HelmChart, "providers.list[0].serviceAccount.name", "irsa-sa")
  207. }
  208. func assertVarValue(t *testing.T, chart *HelmChart, key, wantValue string) {
  209. t.Helper()
  210. for _, variable := range chart.Vars {
  211. if variable.Key == key {
  212. if variable.Value != wantValue {
  213. t.Fatalf("expected %s=%s, got %s", key, wantValue, variable.Value)
  214. }
  215. return
  216. }
  217. }
  218. t.Fatalf("expected %s=%s to be set", key, wantValue)
  219. }
  220. func assertV2ProviderBaseVars(t *testing.T, chart *HelmChart) {
  221. t.Helper()
  222. assertVarValue(t, chart, "replicaCount", "1")
  223. assertVarValue(t, chart, "v2.enabled", "true")
  224. assertVarValue(t, chart, "crds.createProvider", "true")
  225. assertVarValue(t, chart, "crds.createClusterProvider", "true")
  226. assertVarValue(t, chart, "providerDefaults.replicaCount", "1")
  227. }
  228. func assertProvider(t *testing.T, chart *HelmChart, name, providerType, imageRepository, imageTag string) {
  229. t.Helper()
  230. for _, provider := range providerEntries(t, chart) {
  231. if provider.Name != name {
  232. continue
  233. }
  234. if provider.Type != providerType {
  235. t.Fatalf("expected provider %q to have type %q, got %q", name, providerType, provider.Type)
  236. }
  237. if provider.Enabled != "true" {
  238. t.Fatalf("expected provider %q to be enabled, got %q", name, provider.Enabled)
  239. }
  240. if provider.ReplicaCount != "1" {
  241. t.Fatalf("expected provider %q replicaCount 1, got %q", name, provider.ReplicaCount)
  242. }
  243. if provider.ImageRepository != imageRepository {
  244. t.Fatalf("expected provider %q image repository %q, got %q", name, imageRepository, provider.ImageRepository)
  245. }
  246. if provider.ImageTag != imageTag {
  247. t.Fatalf("expected provider %q image tag %q, got %q", name, imageTag, provider.ImageTag)
  248. }
  249. if provider.ImagePullPolicy != "IfNotPresent" {
  250. t.Fatalf("expected provider %q image pull policy IfNotPresent, got %q", name, provider.ImagePullPolicy)
  251. }
  252. return
  253. }
  254. t.Fatalf("expected provider %q to exist", name)
  255. }
  256. func assertSequentialProviderIndexes(t *testing.T, chart *HelmChart) {
  257. t.Helper()
  258. providers := providerEntries(t, chart)
  259. for i := 0; i < len(providers); i++ {
  260. if _, ok := providers[i]; !ok {
  261. t.Fatalf("expected provider index %d to exist, got indexes %v", i, sortedProviderIndexes(providers))
  262. }
  263. }
  264. }
  265. type providerEntry struct {
  266. Name string
  267. Type string
  268. Enabled string
  269. ReplicaCount string
  270. ImageRepository string
  271. ImageTag string
  272. ImagePullPolicy string
  273. }
  274. var providerVarPattern = regexp.MustCompile(`^providers\.list\[(\d+)\]\.(.+)$`)
  275. var allowedProviderFields = map[string]struct{}{
  276. "name": {},
  277. "type": {},
  278. "enabled": {},
  279. "replicaCount": {},
  280. "image.repository": {},
  281. "image.tag": {},
  282. "image.pullPolicy": {},
  283. }
  284. func providerEntries(t *testing.T, chart *HelmChart) map[int]providerEntry {
  285. t.Helper()
  286. providers := make(map[int]providerEntry)
  287. for _, variable := range chart.Vars {
  288. matches := providerVarPattern.FindStringSubmatch(variable.Key)
  289. if matches == nil {
  290. continue
  291. }
  292. index, err := strconv.Atoi(matches[1])
  293. if err != nil {
  294. t.Fatalf("unable to parse provider index from key %q: %v", variable.Key, err)
  295. }
  296. field := matches[2]
  297. if _, ok := allowedProviderFields[field]; !ok {
  298. t.Fatalf("unexpected provider field %q in key %q", field, variable.Key)
  299. }
  300. entry := providers[index]
  301. switch field {
  302. case "name":
  303. entry.Name = variable.Value
  304. case "type":
  305. entry.Type = variable.Value
  306. case "enabled":
  307. entry.Enabled = variable.Value
  308. case "replicaCount":
  309. entry.ReplicaCount = variable.Value
  310. case "image.repository":
  311. entry.ImageRepository = variable.Value
  312. case "image.tag":
  313. entry.ImageTag = variable.Value
  314. case "image.pullPolicy":
  315. entry.ImagePullPolicy = variable.Value
  316. }
  317. providers[index] = entry
  318. }
  319. return providers
  320. }
  321. func sortedProviderIndexes(providers map[int]providerEntry) []int {
  322. indexes := make([]int, 0, len(providers))
  323. for index := range providers {
  324. indexes = append(indexes, index)
  325. }
  326. for i := 0; i < len(indexes); i++ {
  327. for j := i + 1; j < len(indexes); j++ {
  328. if indexes[j] < indexes[i] {
  329. indexes[i], indexes[j] = indexes[j], indexes[i]
  330. }
  331. }
  332. }
  333. return indexes
  334. }