eso_v2_mutators_test.go 11 KB

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