eso_v2_mutators_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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.createClusterProviderClass", Value: "false"})
  156. setOrAppendVar(eso.HelmChart, StringTuple{Key: "crds.createProviderStore", Value: "false"})
  157. setOrAppendVar(eso.HelmChart, StringTuple{Key: "crds.createClusterProviderStore", Value: "false"})
  158. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providers.enabled", Value: "false"})
  159. setOrAppendVar(eso.HelmChart, StringTuple{Key: "providerDefaults.replicaCount", Value: "8"})
  160. WithV2FakeProvider()(eso)
  161. assertVarValue(t, eso.HelmChart, "replicaCount", "7")
  162. assertVarValue(t, eso.HelmChart, "v2.enabled", "true")
  163. assertVarValue(t, eso.HelmChart, "crds.createClusterProviderClass", "true")
  164. assertVarValue(t, eso.HelmChart, "crds.createProviderStore", "true")
  165. assertVarValue(t, eso.HelmChart, "crds.createClusterProviderStore", "true")
  166. assertVarValue(t, eso.HelmChart, "providers.enabled", "true")
  167. assertVarValue(t, eso.HelmChart, "providerDefaults.replicaCount", "8")
  168. }
  169. func TestWithV2ProviderServiceAccountOverridesAWSInPlace(t *testing.T) {
  170. t.Setenv("VERSION", "test-version")
  171. eso := NewESO(WithV2AWSProvider())
  172. WithV2ProviderServiceAccount("aws", "irsa-sa")(eso)
  173. assertVarValue(t, eso.HelmChart, "providers.list[0].serviceAccount.create", "false")
  174. assertVarValue(t, eso.HelmChart, "providers.list[0].serviceAccount.name", "irsa-sa")
  175. }
  176. func assertVarValue(t *testing.T, chart *HelmChart, key, wantValue string) {
  177. t.Helper()
  178. for _, variable := range chart.Vars {
  179. if variable.Key == key {
  180. if variable.Value != wantValue {
  181. t.Fatalf("expected %s=%s, got %s", key, wantValue, variable.Value)
  182. }
  183. return
  184. }
  185. }
  186. t.Fatalf("expected %s=%s to be set", key, wantValue)
  187. }
  188. func assertV2ProviderBaseVars(t *testing.T, chart *HelmChart) {
  189. t.Helper()
  190. assertVarValue(t, chart, "replicaCount", "1")
  191. assertVarValue(t, chart, "v2.enabled", "true")
  192. assertVarValue(t, chart, "crds.createClusterProviderClass", "true")
  193. assertVarValue(t, chart, "crds.createProviderStore", "true")
  194. assertVarValue(t, chart, "crds.createClusterProviderStore", "true")
  195. assertVarValue(t, chart, "providerDefaults.replicaCount", "1")
  196. }
  197. func assertProvider(t *testing.T, chart *HelmChart, name, providerType, imageRepository, imageTag string) {
  198. t.Helper()
  199. for _, provider := range providerEntries(t, chart) {
  200. if provider.Name != name {
  201. continue
  202. }
  203. if provider.Type != providerType {
  204. t.Fatalf("expected provider %q to have type %q, got %q", name, providerType, provider.Type)
  205. }
  206. if provider.Enabled != "true" {
  207. t.Fatalf("expected provider %q to be enabled, got %q", name, provider.Enabled)
  208. }
  209. if provider.ReplicaCount != "1" {
  210. t.Fatalf("expected provider %q replicaCount 1, got %q", name, provider.ReplicaCount)
  211. }
  212. if provider.ImageRepository != imageRepository {
  213. t.Fatalf("expected provider %q image repository %q, got %q", name, imageRepository, provider.ImageRepository)
  214. }
  215. if provider.ImageTag != imageTag {
  216. t.Fatalf("expected provider %q image tag %q, got %q", name, imageTag, provider.ImageTag)
  217. }
  218. if provider.ImagePullPolicy != "IfNotPresent" {
  219. t.Fatalf("expected provider %q image pull policy IfNotPresent, got %q", name, provider.ImagePullPolicy)
  220. }
  221. return
  222. }
  223. t.Fatalf("expected provider %q to exist", name)
  224. }
  225. func assertSequentialProviderIndexes(t *testing.T, chart *HelmChart) {
  226. t.Helper()
  227. providers := providerEntries(t, chart)
  228. for i := 0; i < len(providers); i++ {
  229. if _, ok := providers[i]; !ok {
  230. t.Fatalf("expected provider index %d to exist, got indexes %v", i, sortedProviderIndexes(providers))
  231. }
  232. }
  233. }
  234. type providerEntry struct {
  235. Name string
  236. Type string
  237. Enabled string
  238. ReplicaCount string
  239. ImageRepository string
  240. ImageTag string
  241. ImagePullPolicy string
  242. }
  243. var providerVarPattern = regexp.MustCompile(`^providers\.list\[(\d+)\]\.(.+)$`)
  244. var allowedProviderFields = map[string]struct{}{
  245. "name": {},
  246. "type": {},
  247. "enabled": {},
  248. "replicaCount": {},
  249. "image.repository": {},
  250. "image.tag": {},
  251. "image.pullPolicy": {},
  252. }
  253. func providerEntries(t *testing.T, chart *HelmChart) map[int]providerEntry {
  254. t.Helper()
  255. providers := make(map[int]providerEntry)
  256. for _, variable := range chart.Vars {
  257. matches := providerVarPattern.FindStringSubmatch(variable.Key)
  258. if matches == nil {
  259. continue
  260. }
  261. index, err := strconv.Atoi(matches[1])
  262. if err != nil {
  263. t.Fatalf("unable to parse provider index from key %q: %v", variable.Key, err)
  264. }
  265. field := matches[2]
  266. if _, ok := allowedProviderFields[field]; !ok {
  267. t.Fatalf("unexpected provider field %q in key %q", field, variable.Key)
  268. }
  269. entry := providers[index]
  270. switch field {
  271. case "name":
  272. entry.Name = variable.Value
  273. case "type":
  274. entry.Type = variable.Value
  275. case "enabled":
  276. entry.Enabled = variable.Value
  277. case "replicaCount":
  278. entry.ReplicaCount = variable.Value
  279. case "image.repository":
  280. entry.ImageRepository = variable.Value
  281. case "image.tag":
  282. entry.ImageTag = variable.Value
  283. case "image.pullPolicy":
  284. entry.ImagePullPolicy = variable.Value
  285. }
  286. providers[index] = entry
  287. }
  288. return providers
  289. }
  290. func sortedProviderIndexes(providers map[int]providerEntry) []int {
  291. indexes := make([]int, 0, len(providers))
  292. for index := range providers {
  293. indexes = append(indexes, index)
  294. }
  295. for i := 0; i < len(indexes); i++ {
  296. for j := i + 1; j < len(indexes); j++ {
  297. if indexes[j] < indexes[i] {
  298. indexes[i], indexes[j] = indexes[j], indexes[i]
  299. }
  300. }
  301. }
  302. return indexes
  303. }