GitOps for k8s
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

helmrelease_test.go 35KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. package resource
  2. import (
  3. "fmt"
  4. "github.com/stretchr/testify/assert"
  5. "testing"
  6. "github.com/fluxcd/flux/resource"
  7. )
  8. func TestSortedContainers(t *testing.T) {
  9. unordered, expected := map[string]imageAndSetter{
  10. "ZZZ": {},
  11. "AAA": {},
  12. "FFF": {},
  13. ReleaseContainerName: {},
  14. }, []string{ReleaseContainerName, "AAA", "FFF", "ZZZ"}
  15. actual := sorted_containers(unordered)
  16. assert.Equal(t, expected, actual)
  17. }
  18. func TestParseImageOnlyFormat(t *testing.T) {
  19. expectedImage := "bitnami/ghost:1.21.5-r0"
  20. doc := `---
  21. apiVersion: helm.fluxcd.io/v1
  22. kind: HelmRelease
  23. metadata:
  24. name: ghost
  25. namespace: ghost
  26. labels:
  27. chart: ghost
  28. spec:
  29. chart:
  30. git: git@github.com:fluxcd/flux-get-started
  31. ref: master
  32. path: charts/ghost
  33. values:
  34. first: post
  35. image: ` + expectedImage + `
  36. persistence:
  37. enabled: false
  38. `
  39. resources, err := ParseMultidoc([]byte(doc), "test")
  40. if err != nil {
  41. t.Fatal(err)
  42. }
  43. res, ok := resources["ghost:helmrelease/ghost"]
  44. if !ok {
  45. t.Fatalf("expected resource not found; instead got %#v", resources)
  46. }
  47. hr, ok := res.(resource.Workload)
  48. if !ok {
  49. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  50. }
  51. containers := hr.Containers()
  52. if len(containers) != 1 {
  53. t.Errorf("expected 1 container; got %#v", containers)
  54. }
  55. image := containers[0].Image.String()
  56. if image != expectedImage {
  57. t.Errorf("expected container image %q, got %q", expectedImage, image)
  58. }
  59. }
  60. func TestParseImageTagFormat(t *testing.T) {
  61. expectedImageName := "bitnami/ghost"
  62. expectedImageTag := "1.21.5-r0"
  63. expectedImage := expectedImageName + ":" + expectedImageTag
  64. doc := `---
  65. apiVersion: helm.fluxcd.io/v1
  66. kind: HelmRelease
  67. metadata:
  68. name: ghost
  69. namespace: ghost
  70. labels:
  71. chart: ghost
  72. spec:
  73. chart:
  74. git: git@github.com:fluxcd/flux-get-started
  75. ref: master
  76. path: charts/ghostb
  77. values:
  78. first: post
  79. image: ` + expectedImageName + `
  80. tag: ` + expectedImageTag + `
  81. persistence:
  82. enabled: false
  83. `
  84. resources, err := ParseMultidoc([]byte(doc), "test")
  85. if err != nil {
  86. t.Fatal(err)
  87. }
  88. res, ok := resources["ghost:helmrelease/ghost"]
  89. if !ok {
  90. t.Fatalf("expected resource not found; instead got %#v", resources)
  91. }
  92. hr, ok := res.(resource.Workload)
  93. if !ok {
  94. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  95. }
  96. containers := hr.Containers()
  97. if len(containers) != 1 {
  98. t.Errorf("expected 1 container; got %#v", containers)
  99. }
  100. image := containers[0].Image.String()
  101. if image != expectedImage {
  102. t.Errorf("expected container image %q, got %q", expectedImage, image)
  103. }
  104. }
  105. func TestParseRegistryImageTagFormat(t *testing.T) {
  106. expectedRegistry := "registry.com"
  107. expectedImageName := "bitnami/ghost"
  108. expectedImageTag := "1.21.5-r0"
  109. expectedImage := expectedRegistry + "/" + expectedImageName + ":" + expectedImageTag
  110. doc := `---
  111. apiVersion: helm.fluxcd.io/v1
  112. kind: HelmRelease
  113. metadata:
  114. name: ghost
  115. namespace: ghost
  116. labels:
  117. chart: ghost
  118. spec:
  119. chart:
  120. git: git@github.com:fluxcd/flux-get-started
  121. ref: master
  122. path: charts/ghost
  123. spec:
  124. chartGitPath: mariadb
  125. values:
  126. first: post
  127. registry: ` + expectedRegistry + `
  128. image: ` + expectedImageName + `
  129. tag: ` + expectedImageTag + `
  130. persistence:
  131. enabled: false
  132. `
  133. resources, err := ParseMultidoc([]byte(doc), "test")
  134. if err != nil {
  135. t.Fatal(err)
  136. }
  137. res, ok := resources["ghost:helmrelease/ghost"]
  138. if !ok {
  139. t.Fatalf("expected resource not found; instead got %#v", resources)
  140. }
  141. hr, ok := res.(resource.Workload)
  142. if !ok {
  143. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  144. }
  145. containers := hr.Containers()
  146. if len(containers) != 1 {
  147. t.Errorf("expected 1 container; got %#v", containers)
  148. }
  149. image := containers[0].Image.String()
  150. if image != expectedImage {
  151. t.Errorf("expected container image %q, got %q", expectedImage, image)
  152. }
  153. }
  154. func TestParseRegistryImageFormat(t *testing.T) {
  155. expectedRegistry := "registry.com"
  156. expectedImageName := "bitnami/ghost:1.21.5-r0"
  157. expectedImage := expectedRegistry + "/" + expectedImageName
  158. doc := `---
  159. apiVersion: helm.fluxcd.io/v1
  160. kind: HelmRelease
  161. metadata:
  162. name: ghost
  163. namespace: ghost
  164. labels:
  165. chart: ghost
  166. spec:
  167. chart:
  168. git: git@github.com:fluxcd/flux-get-started
  169. ref: master
  170. path: charts/ghost
  171. spec:
  172. chartGitPath: mariadb
  173. values:
  174. first: post
  175. registry: ` + expectedRegistry + `
  176. image: ` + expectedImageName + `
  177. persistence:
  178. enabled: false
  179. `
  180. resources, err := ParseMultidoc([]byte(doc), "test")
  181. if err != nil {
  182. t.Fatal(err)
  183. }
  184. res, ok := resources["ghost:helmrelease/ghost"]
  185. if !ok {
  186. t.Fatalf("expected resource not found; instead got %#v", resources)
  187. }
  188. hr, ok := res.(resource.Workload)
  189. if !ok {
  190. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  191. }
  192. containers := hr.Containers()
  193. if len(containers) != 1 {
  194. t.Errorf("expected 1 container; got %#v", containers)
  195. }
  196. image := containers[0].Image.String()
  197. if image != expectedImage {
  198. t.Errorf("expected container image %q, got %q", expectedImage, image)
  199. }
  200. }
  201. func TestParseNamedImageFormat(t *testing.T) {
  202. expectedContainer := "db"
  203. expectedImage := "bitnami/ghost:1.21.5-r0"
  204. doc := `---
  205. apiVersion: helm.fluxcd.io/v1
  206. kind: HelmRelease
  207. metadata:
  208. name: ghost
  209. namespace: ghost
  210. labels:
  211. chart: ghost
  212. spec:
  213. chart:
  214. git: git@github.com:fluxcd/flux-get-started
  215. ref: master
  216. path: charts/ghost
  217. spec:
  218. chartGitPath: mariadb
  219. values:
  220. ` + expectedContainer + `:
  221. first: post
  222. image: ` + expectedImage + `
  223. persistence:
  224. enabled: false
  225. `
  226. resources, err := ParseMultidoc([]byte(doc), "test")
  227. if err != nil {
  228. t.Fatal(err)
  229. }
  230. res, ok := resources["ghost:helmrelease/ghost"]
  231. if !ok {
  232. t.Fatalf("expected resource not found; instead got %#v", resources)
  233. }
  234. hr, ok := res.(resource.Workload)
  235. if !ok {
  236. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  237. }
  238. containers := hr.Containers()
  239. if len(containers) != 1 {
  240. t.Fatalf("expected 1 container; got %#v", containers)
  241. }
  242. image := containers[0].Image.String()
  243. if image != expectedImage {
  244. t.Errorf("expected container image %q, got %q", expectedImage, image)
  245. }
  246. if containers[0].Name != expectedContainer {
  247. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  248. }
  249. newImage := containers[0].Image.WithNewTag("some-other-tag")
  250. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  251. t.Error(err)
  252. }
  253. containers = hr.Containers()
  254. if len(containers) != 1 {
  255. t.Fatalf("expected 1 container; got %#v", containers)
  256. }
  257. image = containers[0].Image.String()
  258. if image != newImage.String() {
  259. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  260. }
  261. if containers[0].Name != expectedContainer {
  262. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  263. }
  264. }
  265. func TestParseNamedImageTagFormat(t *testing.T) {
  266. expectedContainer := "db"
  267. expectedImageName := "bitnami/ghost"
  268. expectedImageTag := "1.21.5-r0"
  269. expectedImage := expectedImageName + ":" + expectedImageTag
  270. doc := `---
  271. apiVersion: helm.fluxcd.io/v1
  272. kind: HelmRelease
  273. metadata:
  274. name: ghost
  275. namespace: ghost
  276. labels:
  277. chart: ghost
  278. spec:
  279. chart:
  280. git: git@github.com:fluxcd/flux-get-started
  281. ref: master
  282. path: charts/ghost
  283. spec:
  284. chartGitPath: mariadb
  285. values:
  286. other:
  287. not: "containing image"
  288. ` + expectedContainer + `:
  289. first: post
  290. image: ` + expectedImageName + `
  291. tag: ` + expectedImageTag + `
  292. persistence:
  293. enabled: false
  294. `
  295. resources, err := ParseMultidoc([]byte(doc), "test")
  296. if err != nil {
  297. t.Fatal(err)
  298. }
  299. res, ok := resources["ghost:helmrelease/ghost"]
  300. if !ok {
  301. t.Fatalf("expected resource not found; instead got %#v", resources)
  302. }
  303. hr, ok := res.(resource.Workload)
  304. if !ok {
  305. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  306. }
  307. containers := hr.Containers()
  308. if len(containers) != 1 {
  309. t.Fatalf("expected 1 container; got %#v", containers)
  310. }
  311. image := containers[0].Image.String()
  312. if image != expectedImage {
  313. t.Errorf("expected container image %q, got %q", expectedImage, image)
  314. }
  315. if containers[0].Name != expectedContainer {
  316. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  317. }
  318. newImage := containers[0].Image.WithNewTag("some-other-tag")
  319. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  320. t.Error(err)
  321. }
  322. containers = hr.Containers()
  323. if len(containers) != 1 {
  324. t.Fatalf("expected 1 container; got %#v", containers)
  325. }
  326. image = containers[0].Image.String()
  327. if image != newImage.String() {
  328. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  329. }
  330. if containers[0].Name != expectedContainer {
  331. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  332. }
  333. }
  334. func TestParseNamedRegistryImageTagFormat(t *testing.T) {
  335. expectedContainer := "db"
  336. expectedRegistry := "registry.com"
  337. expectedImageName := "bitnami/ghost"
  338. expectedImageTag := "1.21.5-r0"
  339. expectedImage := expectedRegistry + "/" + expectedImageName + ":" + expectedImageTag
  340. doc := `---
  341. apiVersion: helm.fluxcd.io/v1
  342. kind: HelmRelease
  343. metadata:
  344. name: ghost
  345. namespace: ghost
  346. labels:
  347. chart: ghost
  348. spec:
  349. chart:
  350. git: git@github.com:fluxcd/flux-get-started
  351. ref: master
  352. path: charts/ghost
  353. spec:
  354. chartGitPath: mariadb
  355. values:
  356. other:
  357. not: "containing image"
  358. ` + expectedContainer + `:
  359. first: post
  360. registry: ` + expectedRegistry + `
  361. image: ` + expectedImageName + `
  362. tag: ` + expectedImageTag + `
  363. persistence:
  364. enabled: false
  365. `
  366. resources, err := ParseMultidoc([]byte(doc), "test")
  367. if err != nil {
  368. t.Fatal(err)
  369. }
  370. res, ok := resources["ghost:helmrelease/ghost"]
  371. if !ok {
  372. t.Fatalf("expected resource not found; instead got %#v", resources)
  373. }
  374. hr, ok := res.(resource.Workload)
  375. if !ok {
  376. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  377. }
  378. containers := hr.Containers()
  379. if len(containers) != 1 {
  380. t.Fatalf("expected 1 container; got %#v", containers)
  381. }
  382. image := containers[0].Image.String()
  383. if image != expectedImage {
  384. t.Errorf("expected container image %q, got %q", expectedImage, image)
  385. }
  386. if containers[0].Name != expectedContainer {
  387. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  388. }
  389. newImage := containers[0].Image.WithNewTag("some-other-tag")
  390. newImage.Domain = "someotherregistry.com"
  391. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  392. t.Error(err)
  393. }
  394. containers = hr.Containers()
  395. if len(containers) != 1 {
  396. t.Fatalf("expected 1 container; got %#v", containers)
  397. }
  398. image = containers[0].Image.String()
  399. if image != newImage.String() {
  400. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  401. }
  402. if containers[0].Name != expectedContainer {
  403. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  404. }
  405. }
  406. func TestParseNamedRegistryImageFormat(t *testing.T) {
  407. expectedContainer := "db"
  408. expectedRegistry := "registry.com"
  409. expectedImageName := "bitnami/ghost:1.21.5-r0"
  410. expectedImage := expectedRegistry + "/" + expectedImageName
  411. doc := `---
  412. apiVersion: helm.fluxcd.io/v1
  413. kind: HelmRelease
  414. metadata:
  415. name: ghost
  416. namespace: ghost
  417. labels:
  418. chart: ghost
  419. spec:
  420. chart:
  421. git: git@github.com:fluxcd/flux-get-started
  422. ref: master
  423. path: charts/ghost
  424. values:
  425. other:
  426. not: "containing image"
  427. ` + expectedContainer + `:
  428. first: post
  429. registry: ` + expectedRegistry + `
  430. image: ` + expectedImageName + `
  431. persistence:
  432. enabled: false
  433. `
  434. resources, err := ParseMultidoc([]byte(doc), "test")
  435. if err != nil {
  436. t.Fatal(err)
  437. }
  438. res, ok := resources["ghost:helmrelease/ghost"]
  439. if !ok {
  440. t.Fatalf("expected resource not found; instead got %#v", resources)
  441. }
  442. hr, ok := res.(resource.Workload)
  443. if !ok {
  444. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  445. }
  446. containers := hr.Containers()
  447. if len(containers) != 1 {
  448. t.Fatalf("expected 1 container; got %#v", containers)
  449. }
  450. image := containers[0].Image.String()
  451. if image != expectedImage {
  452. t.Errorf("expected container image %q, got %q", expectedImage, image)
  453. }
  454. if containers[0].Name != expectedContainer {
  455. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  456. }
  457. newImage := containers[0].Image.WithNewTag("some-other-tag")
  458. newImage.Domain = "someotherregistry.com"
  459. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  460. t.Error(err)
  461. }
  462. containers = hr.Containers()
  463. if len(containers) != 1 {
  464. t.Fatalf("expected 1 container; got %#v", containers)
  465. }
  466. image = containers[0].Image.String()
  467. if image != newImage.String() {
  468. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  469. }
  470. if containers[0].Name != expectedContainer {
  471. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  472. }
  473. }
  474. func TestParseImageObjectFormat(t *testing.T) {
  475. expectedImageName := "bitnami/ghost"
  476. expectedImageTag := "1.21.5-r0"
  477. expectedImage := expectedImageName + ":" + expectedImageTag
  478. doc := `---
  479. apiVersion: helm.fluxcd.io/v1
  480. kind: HelmRelease
  481. metadata:
  482. name: ghost
  483. namespace: ghost
  484. labels:
  485. chart: ghost
  486. spec:
  487. chart:
  488. git: git@github.com:fluxcd/flux-get-started
  489. ref: master
  490. path: charts/ghost
  491. values:
  492. first: post
  493. image:
  494. repository: ` + expectedImageName + `
  495. tag: ` + expectedImageTag + `
  496. persistence:
  497. enabled: false
  498. `
  499. resources, err := ParseMultidoc([]byte(doc), "test")
  500. if err != nil {
  501. t.Fatal(err)
  502. }
  503. res, ok := resources["ghost:helmrelease/ghost"]
  504. if !ok {
  505. t.Fatalf("expected resource not found; instead got %#v", resources)
  506. }
  507. hr, ok := res.(resource.Workload)
  508. if !ok {
  509. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  510. }
  511. containers := hr.Containers()
  512. if len(containers) != 1 {
  513. t.Errorf("expected 1 container; got %#v", containers)
  514. }
  515. image := containers[0].Image.String()
  516. if image != expectedImage {
  517. t.Errorf("expected container image %q, got %q", expectedImage, image)
  518. }
  519. }
  520. func TestParseNamedImageObjectFormat(t *testing.T) {
  521. expectedContainer := "db"
  522. expectedImageName := "bitnami/ghost"
  523. expectedImageTag := "1.21.5-r0"
  524. expectedImage := expectedImageName + ":" + expectedImageTag
  525. doc := `---
  526. apiVersion: helm.fluxcd.io/v1
  527. kind: HelmRelease
  528. metadata:
  529. name: ghost
  530. namespace: ghost
  531. labels:
  532. chart: ghost
  533. spec:
  534. chart:
  535. git: git@github.com:fluxcd/flux-get-started
  536. ref: master
  537. path: charts/ghost
  538. values:
  539. other:
  540. not: "containing image"
  541. ` + expectedContainer + `:
  542. first: post
  543. image:
  544. repository: ` + expectedImageName + `
  545. tag: ` + expectedImageTag + `
  546. persistence:
  547. enabled: false
  548. `
  549. resources, err := ParseMultidoc([]byte(doc), "test")
  550. if err != nil {
  551. t.Fatal(err)
  552. }
  553. res, ok := resources["ghost:helmrelease/ghost"]
  554. if !ok {
  555. t.Fatalf("expected resource not found; instead got %#v", resources)
  556. }
  557. hr, ok := res.(resource.Workload)
  558. if !ok {
  559. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  560. }
  561. containers := hr.Containers()
  562. if len(containers) != 1 {
  563. t.Fatalf("expected 1 container; got %#v", containers)
  564. }
  565. image := containers[0].Image.String()
  566. if image != expectedImage {
  567. t.Errorf("expected container image %q, got %q", expectedImage, image)
  568. }
  569. if containers[0].Name != expectedContainer {
  570. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  571. }
  572. newImage := containers[0].Image.WithNewTag("some-other-tag")
  573. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  574. t.Error(err)
  575. }
  576. containers = hr.Containers()
  577. if len(containers) != 1 {
  578. t.Fatalf("expected 1 container; got %#v", containers)
  579. }
  580. image = containers[0].Image.String()
  581. if image != newImage.String() {
  582. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  583. }
  584. if containers[0].Name != expectedContainer {
  585. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  586. }
  587. }
  588. func TestParseNamedImageObjectFormatWithRegistry(t *testing.T) {
  589. expectedContainer := "db"
  590. expectedRegistry := "registry.com"
  591. expectedImageName := "bitnami/ghost"
  592. expectedImageTag := "1.21.5-r0"
  593. expectedImage := expectedRegistry + "/" + expectedImageName + ":" + expectedImageTag
  594. doc := `---
  595. apiVersion: helm.fluxcd.io/v1
  596. kind: HelmRelease
  597. metadata:
  598. name: ghost
  599. namespace: ghost
  600. labels:
  601. chart: ghost
  602. spec:
  603. chart:
  604. git: git@github.com:fluxcd/flux-get-started
  605. ref: master
  606. path: charts/ghost
  607. values:
  608. other:
  609. not: "containing image"
  610. ` + expectedContainer + `:
  611. first: post
  612. image:
  613. registry: ` + expectedRegistry + `
  614. repository: ` + expectedImageName + `
  615. tag: ` + expectedImageTag + `
  616. persistence:
  617. enabled: false
  618. `
  619. resources, err := ParseMultidoc([]byte(doc), "test")
  620. if err != nil {
  621. t.Fatal(err)
  622. }
  623. res, ok := resources["ghost:helmrelease/ghost"]
  624. if !ok {
  625. t.Fatalf("expected resource not found; instead got %#v", resources)
  626. }
  627. hr, ok := res.(resource.Workload)
  628. if !ok {
  629. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  630. }
  631. containers := hr.Containers()
  632. if len(containers) != 1 {
  633. t.Fatalf("expected 1 container; got %#v", containers)
  634. }
  635. image := containers[0].Image.String()
  636. if image != expectedImage {
  637. t.Errorf("expected container image %q, got %q", expectedImage, image)
  638. }
  639. if containers[0].Name != expectedContainer {
  640. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  641. }
  642. newImage := containers[0].Image.WithNewTag("some-other-tag")
  643. newImage.Domain = "someotherregistry.com"
  644. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  645. t.Error(err)
  646. }
  647. containers = hr.Containers()
  648. if len(containers) != 1 {
  649. t.Fatalf("expected 1 container; got %#v", containers)
  650. }
  651. image = containers[0].Image.String()
  652. if image != newImage.String() {
  653. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  654. }
  655. if containers[0].Name != expectedContainer {
  656. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  657. }
  658. }
  659. func TestParseNamedImageObjectFormatWithRegistryWitoutTag(t *testing.T) {
  660. expectedContainer := "db"
  661. expectedRegistry := "registry.com"
  662. expectedImageName := "bitnami/ghost:1.21.5-r0"
  663. expectedImage := expectedRegistry + "/" + expectedImageName
  664. doc := `---
  665. apiVersion: helm.fluxcd.io/v1
  666. kind: HelmRelease
  667. metadata:
  668. name: ghost
  669. namespace: ghost
  670. labels:
  671. chart: ghost
  672. spec:
  673. chart:
  674. git: git@github.com:fluxcd/flux-get-started
  675. ref: master
  676. path: charts/ghost
  677. values:
  678. other:
  679. not: "containing image"
  680. ` + expectedContainer + `:
  681. first: post
  682. image:
  683. registry: ` + expectedRegistry + `
  684. repository: ` + expectedImageName + `
  685. persistence:
  686. enabled: false
  687. `
  688. resources, err := ParseMultidoc([]byte(doc), "test")
  689. if err != nil {
  690. t.Fatal(err)
  691. }
  692. res, ok := resources["ghost:helmrelease/ghost"]
  693. if !ok {
  694. t.Fatalf("expected resource not found; instead got %#v", resources)
  695. }
  696. hr, ok := res.(resource.Workload)
  697. if !ok {
  698. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  699. }
  700. containers := hr.Containers()
  701. if len(containers) != 1 {
  702. t.Fatalf("expected 1 container; got %#v", containers)
  703. }
  704. image := containers[0].Image.String()
  705. if image != expectedImage {
  706. t.Errorf("expected container image %q, got %q", expectedImage, image)
  707. }
  708. if containers[0].Name != expectedContainer {
  709. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  710. }
  711. newImage := containers[0].Image.WithNewTag("some-other-tag")
  712. newImage.Domain = "someotherregistry.com"
  713. if err := hr.SetContainerImage(expectedContainer, newImage); err != nil {
  714. t.Error(err)
  715. }
  716. containers = hr.Containers()
  717. if len(containers) != 1 {
  718. t.Fatalf("expected 1 container; got %#v", containers)
  719. }
  720. image = containers[0].Image.String()
  721. if image != newImage.String() {
  722. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  723. }
  724. if containers[0].Name != expectedContainer {
  725. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  726. }
  727. }
  728. func TestParseMappedImageOnly(t *testing.T) {
  729. expectedContainer := "mariadb"
  730. expectedImage := "bitnami/mariadb:10.1.30-r1"
  731. doc := `---
  732. apiVersion: helm.integrations.flux.weave.works/v1alpha2
  733. kind: FluxHelmRelease
  734. metadata:
  735. name: mariadb
  736. namespace: maria
  737. annotations:
  738. ` + ImageRepositoryPrefix + expectedContainer + `: customRepository
  739. labels:
  740. chart: mariadb
  741. spec:
  742. chartGitPath: mariadb
  743. values:
  744. first: post
  745. customRepository: ` + expectedImage + `
  746. persistence:
  747. enabled: false
  748. `
  749. resources, err := ParseMultidoc([]byte(doc), "test")
  750. if err != nil {
  751. t.Fatal(err)
  752. }
  753. res, ok := resources["maria:fluxhelmrelease/mariadb"]
  754. if !ok {
  755. t.Fatalf("expected resource not found; instead got %#v", resources)
  756. }
  757. fhr, ok := res.(resource.Workload)
  758. if !ok {
  759. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  760. }
  761. containers := fhr.Containers()
  762. if len(containers) != 1 {
  763. t.Fatalf("expected 1 container; got %#v", containers)
  764. }
  765. container := containers[0].Name
  766. if container != expectedContainer {
  767. t.Errorf("expected container container %q, got %q", expectedContainer, container)
  768. }
  769. image := containers[0].Image.String()
  770. if image != expectedImage {
  771. t.Errorf("expected container image %q, got %q", expectedImage, image)
  772. }
  773. newImage := containers[0].Image.WithNewTag("some-other-tag")
  774. if err := fhr.SetContainerImage(expectedContainer, newImage); err != nil {
  775. t.Error(err)
  776. }
  777. containers = fhr.Containers()
  778. if len(containers) != 1 {
  779. t.Fatalf("expected 1 container; got %#v", containers)
  780. }
  781. image = containers[0].Image.String()
  782. if image != newImage.String() {
  783. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  784. }
  785. if containers[0].Name != expectedContainer {
  786. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  787. }
  788. }
  789. func TestParseMappedImageTag(t *testing.T) {
  790. expectedContainer := "mariadb"
  791. expectedImageName := "bitnami/mariadb"
  792. expectedImageTag := "10.1.30-r1"
  793. expectedImage := expectedImageName + ":" + expectedImageTag
  794. doc := `---
  795. apiVersion: helm.integrations.flux.weave.works/v1alpha2
  796. kind: FluxHelmRelease
  797. metadata:
  798. name: mariadb
  799. namespace: maria
  800. annotations:
  801. ` + ImageRepositoryPrefix + expectedContainer + `: customRepository
  802. ` + ImageTagPrefix + expectedContainer + `: customTag
  803. labels:
  804. chart: mariadb
  805. spec:
  806. chartGitPath: mariadb
  807. values:
  808. first: post
  809. customRepository: ` + expectedImageName + `
  810. customTag: ` + expectedImageTag + `
  811. persistence:
  812. enabled: false
  813. `
  814. resources, err := ParseMultidoc([]byte(doc), "test")
  815. if err != nil {
  816. t.Fatal(err)
  817. }
  818. res, ok := resources["maria:fluxhelmrelease/mariadb"]
  819. if !ok {
  820. t.Fatalf("expected resource not found; instead got %#v", resources)
  821. }
  822. fhr, ok := res.(resource.Workload)
  823. if !ok {
  824. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  825. }
  826. containers := fhr.Containers()
  827. if len(containers) != 1 {
  828. t.Fatalf("expected 1 container; got %#v", containers)
  829. }
  830. container := containers[0].Name
  831. if container != expectedContainer {
  832. t.Errorf("expected container container %q, got %q", expectedContainer, container)
  833. }
  834. image := containers[0].Image.String()
  835. if image != expectedImage {
  836. t.Errorf("expected container image %q, got %q", expectedImage, image)
  837. }
  838. newImage := containers[0].Image.WithNewTag("some-other-tag")
  839. if err := fhr.SetContainerImage(expectedContainer, newImage); err != nil {
  840. t.Error(err)
  841. }
  842. containers = fhr.Containers()
  843. if len(containers) != 1 {
  844. t.Fatalf("expected 1 container; got %#v", containers)
  845. }
  846. image = containers[0].Image.String()
  847. if image != newImage.String() {
  848. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  849. }
  850. if containers[0].Name != expectedContainer {
  851. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  852. }
  853. }
  854. func TestParseMappedRegistryImage(t *testing.T) {
  855. expectedContainer := "mariadb"
  856. expectedRegistry := "docker.io"
  857. expectedImageName := "bitnami/mariadb:10.1.30-r1"
  858. expectedImage := expectedRegistry + "/" + expectedImageName
  859. doc := `---
  860. apiVersion: helm.integrations.flux.weave.works/v1alpha2
  861. kind: FluxHelmRelease
  862. metadata:
  863. name: mariadb
  864. namespace: maria
  865. annotations:
  866. ` + ImageRegistryPrefix + expectedContainer + `: customRegistry
  867. ` + ImageRepositoryPrefix + expectedContainer + `: customImage
  868. labels:
  869. chart: mariadb
  870. spec:
  871. chartGitPath: mariadb
  872. values:
  873. first: post
  874. customRegistry: ` + expectedRegistry + `
  875. customImage: ` + expectedImageName + `
  876. persistence:
  877. enabled: false
  878. `
  879. resources, err := ParseMultidoc([]byte(doc), "test")
  880. if err != nil {
  881. t.Fatal(err)
  882. }
  883. res, ok := resources["maria:fluxhelmrelease/mariadb"]
  884. if !ok {
  885. t.Fatalf("expected resource not found; instead got %#v", resources)
  886. }
  887. fhr, ok := res.(resource.Workload)
  888. if !ok {
  889. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  890. }
  891. containers := fhr.Containers()
  892. if len(containers) != 1 {
  893. t.Fatalf("expected 1 container; got %#v", containers)
  894. }
  895. container := containers[0].Name
  896. if container != expectedContainer {
  897. t.Errorf("expected container container %q, got %q", expectedContainer, container)
  898. }
  899. image := containers[0].Image.String()
  900. if image != expectedImage {
  901. t.Errorf("expected container image %q, got %q", expectedImage, image)
  902. }
  903. newImage := containers[0].Image.WithNewTag("some-other-tag")
  904. if err := fhr.SetContainerImage(expectedContainer, newImage); err != nil {
  905. t.Error(err)
  906. }
  907. containers = fhr.Containers()
  908. if len(containers) != 1 {
  909. t.Fatalf("expected 1 container; got %#v", containers)
  910. }
  911. image = containers[0].Image.String()
  912. if image != newImage.String() {
  913. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  914. }
  915. if containers[0].Name != expectedContainer {
  916. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  917. }
  918. }
  919. func TestParseMappedRegistryImageTag(t *testing.T) {
  920. expectedContainer := "mariadb"
  921. expectedRegistry := "index.docker.io"
  922. expectedImageName := "bitnami/mariadb"
  923. expectedImageTag := "10.1.30-r1"
  924. expectedImage := expectedRegistry + "/" + expectedImageName + ":" + expectedImageTag
  925. doc := `---
  926. apiVersion: helm.integrations.flux.weave.works/v1alpha2
  927. kind: FluxHelmRelease
  928. metadata:
  929. name: mariadb
  930. namespace: maria
  931. annotations:
  932. ` + ImageRegistryPrefix + expectedContainer + `: customRegistry
  933. ` + ImageRepositoryPrefix + expectedContainer + `: customRepository
  934. ` + ImageTagPrefix + expectedContainer + `: customTag
  935. labels:
  936. chart: mariadb
  937. spec:
  938. chartGitPath: mariadb
  939. values:
  940. first: post
  941. customRegistry: ` + expectedRegistry + `
  942. customRepository: ` + expectedImageName + `
  943. customTag: ` + expectedImageTag + `
  944. persistence:
  945. enabled: false
  946. `
  947. resources, err := ParseMultidoc([]byte(doc), "test")
  948. if err != nil {
  949. t.Fatal(err)
  950. }
  951. res, ok := resources["maria:fluxhelmrelease/mariadb"]
  952. if !ok {
  953. t.Fatalf("expected resource not found; instead got %#v", resources)
  954. }
  955. fhr, ok := res.(resource.Workload)
  956. if !ok {
  957. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  958. }
  959. containers := fhr.Containers()
  960. if len(containers) != 1 {
  961. t.Fatalf("expected 1 container; got %#v", containers)
  962. }
  963. container := containers[0].Name
  964. if container != expectedContainer {
  965. t.Errorf("expected container container %q, got %q", expectedContainer, container)
  966. }
  967. image := containers[0].Image.String()
  968. if image != expectedImage {
  969. t.Errorf("expected container image %q, got %q", expectedImage, image)
  970. }
  971. newImage := containers[0].Image.WithNewTag("some-other-tag")
  972. if err := fhr.SetContainerImage(expectedContainer, newImage); err != nil {
  973. t.Error(err)
  974. }
  975. containers = fhr.Containers()
  976. if len(containers) != 1 {
  977. t.Fatalf("expected 1 container; got %#v", containers)
  978. }
  979. image = containers[0].Image.String()
  980. if image != newImage.String() {
  981. t.Errorf("expected container image %q, got %q", newImage.String(), image)
  982. }
  983. if containers[0].Name != expectedContainer {
  984. t.Errorf("expected container name %q, got %q", expectedContainer, containers[0].Name)
  985. }
  986. }
  987. func TestParseMappedTagOnly(t *testing.T) {
  988. container := "mariadb"
  989. imageTag := "10.1.30-r1"
  990. doc := `---
  991. apiVersion: helm.integrations.flux.weave.works/v1alpha2
  992. kind: FluxHelmRelease
  993. metadata:
  994. name: mariadb
  995. namespace: maria
  996. annotations:
  997. ` + ImageTagPrefix + container + `: customTag
  998. labels:
  999. chart: mariadb
  1000. spec:
  1001. chartGitPath: mariadb
  1002. values:
  1003. first: post
  1004. customTag: ` + imageTag + `
  1005. persistence:
  1006. enabled: false
  1007. `
  1008. resources, err := ParseMultidoc([]byte(doc), "test")
  1009. if err != nil {
  1010. t.Fatal(err)
  1011. }
  1012. res, ok := resources["maria:fluxhelmrelease/mariadb"]
  1013. if !ok {
  1014. t.Fatalf("expected resource not found; instead got %#v", resources)
  1015. }
  1016. fhr, ok := res.(resource.Workload)
  1017. if !ok {
  1018. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  1019. }
  1020. containers := fhr.Containers()
  1021. if len(containers) != 0 {
  1022. t.Errorf("expected 0 container; got %#v", containers)
  1023. }
  1024. }
  1025. func TestParseMappedImageFormats(t *testing.T) {
  1026. expected := []struct {
  1027. name, registry, image, tag string
  1028. }{
  1029. {"AAA", "", "repo/imageOne", "tagOne"},
  1030. {"CCC", "", "repo/imageTwo", "tagTwo"},
  1031. {"NNN", "", "repo/imageThree", "tagThree"},
  1032. {"ZZZ", "registry.com", "repo/imageFour", "tagFour"},
  1033. }
  1034. doc := `---
  1035. apiVersion: helm.integrations.flux.weave.works/v1alpha2
  1036. kind: FluxHelmRelease
  1037. metadata:
  1038. name: test
  1039. namespace: test
  1040. annotations:
  1041. # Top level mapping
  1042. ` + ImageRepositoryPrefix + expected[0].name + `: customRepository
  1043. ` + ImageTagPrefix + expected[0].name + `: customTag
  1044. # Sub level mapping
  1045. ` + ImageRepositoryPrefix + expected[1].name + `: ` + expected[1].name + `.customRepository
  1046. ` + ImageTagPrefix + expected[1].name + `: ` + expected[1].name + `.customTag
  1047. # Sub level mapping 2
  1048. ` + ImageRepositoryPrefix + expected[2].name + `: ` + expected[2].name + `.image.customRepository
  1049. # Sub level mapping 3
  1050. ` + ImageRegistryPrefix + expected[3].name + `: ` + expected[3].name + `.nested.deep.customRegistry
  1051. ` + ImageRepositoryPrefix + expected[3].name + `: ` + expected[3].name + `.nested.deep.customRepository
  1052. ` + ImageTagPrefix + expected[3].name + `: ` + expected[3].name + `.nested.deep.customTag
  1053. spec:
  1054. chartGitPath: test
  1055. values:
  1056. # Top level image
  1057. customRepository: ` + expected[0].image + `
  1058. customTag: ` + expected[0].tag + `
  1059. # Sub level image
  1060. ` + expected[1].name + `:
  1061. customRepository: ` + expected[1].image + `
  1062. customTag: ` + expected[1].tag + `
  1063. # Sub level image 2
  1064. ` + expected[2].name + `:
  1065. image:
  1066. customRepository: ` + expected[2].image + `:` + expected[2].tag + `
  1067. # Sub level image 3
  1068. ` + expected[3].name + `:
  1069. nested:
  1070. deep:
  1071. customRegistry: ` + expected[3].registry + `
  1072. customRepository: ` + expected[3].image + `
  1073. customTag: ` + expected[3].tag + `
  1074. `
  1075. resources, err := ParseMultidoc([]byte(doc), "test")
  1076. if err != nil {
  1077. t.Fatal(err)
  1078. }
  1079. res, ok := resources["test:fluxhelmrelease/test"]
  1080. if !ok {
  1081. t.Fatalf("expected resource not found; instead got %#v", resources)
  1082. }
  1083. fhr, ok := res.(resource.Workload)
  1084. if !ok {
  1085. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  1086. }
  1087. containers := fhr.Containers()
  1088. if len(containers) != len(expected) {
  1089. t.Fatalf("expected %d containers, got %d, %#v", len(expected), len(containers), containers)
  1090. }
  1091. for i, c0 := range expected {
  1092. c1 := containers[i]
  1093. if c1.Name != c0.name {
  1094. t.Errorf("names do not match %q != %q", c0, c1)
  1095. }
  1096. var c0image string
  1097. if c0.registry != "" {
  1098. c0image = c0.registry + "/"
  1099. }
  1100. c0image += fmt.Sprintf("%s:%s", c0.image, c0.tag)
  1101. if c1.Image.String() != c0image {
  1102. t.Errorf("images do not match %q != %q", c0image, c1.Image.String())
  1103. }
  1104. }
  1105. }
  1106. func TestParseAllFormatsInOne(t *testing.T) {
  1107. type container struct {
  1108. name, registry, image, tag string
  1109. }
  1110. // *NB* the containers will be calculated based on the order
  1111. // 1. the entry for 'image' if present
  1112. // 2. the order of the keys in `values`.
  1113. //
  1114. // To avoid having to mess around later, I have cooked the order
  1115. // of these so they can be compared directly to the return value.
  1116. expected := []container{
  1117. {ReleaseContainerName, "", "repo/imageOne", "tagOne"},
  1118. {"AAA", "", "repo/imageTwo", "tagTwo"},
  1119. {"DDD", "", "repo/imageThree", "tagThree"},
  1120. {"HHH", "registry.com", "repo/imageFour", "tagFour"},
  1121. {"NNN", "registry.com", "repo/imageFive", "tagFive"},
  1122. {"XXX", "registry.com", "repo/imageSix", "tagSix"},
  1123. {"ZZZ", "", "repo/imageSeven", "tagSeven"},
  1124. }
  1125. doc := `---
  1126. apiVersion: helm.fluxcd.io/v1
  1127. kind: HelmRelease
  1128. metadata:
  1129. name: test
  1130. namespace: test
  1131. annotations:
  1132. ` + ImageRepositoryPrefix + expected[6].name + `: ` + expected[6].name + `.customRepository
  1133. ` + ImageTagPrefix + expected[6].name + `: ` + expected[6].name + `.customTag
  1134. spec:
  1135. chart:
  1136. git: git@github.com:fluxcd/flux-get-started
  1137. ref: master
  1138. path: charts/ghost
  1139. values:
  1140. # top-level image
  1141. image: ` + expected[0].image + ":" + expected[0].tag + `
  1142. # under .container, as image and tag entries
  1143. ` + expected[1].name + `:
  1144. image: ` + expected[1].image + `
  1145. tag: ` + expected[1].tag + `
  1146. # under .container.image, as repository and tag entries
  1147. ` + expected[2].name + `:
  1148. image:
  1149. repository: ` + expected[2].image + `
  1150. tag: ` + expected[2].tag + `
  1151. persistence:
  1152. enabled: false
  1153. # under .container, with a separate registry entry
  1154. ` + expected[3].name + `:
  1155. registry: ` + expected[3].registry + `
  1156. image: ` + expected[3].image + `
  1157. tag: ` + expected[3].tag + `
  1158. # under .container.image with a separate registry entry,
  1159. # but without a tag
  1160. ` + expected[4].name + `:
  1161. image:
  1162. registry: ` + expected[4].registry + `
  1163. repository: ` + expected[4].image + ":" + expected[4].tag + `
  1164. # under .container.image with a separate registry entry
  1165. ` + expected[5].name + `:
  1166. image:
  1167. registry: ` + expected[5].registry + `
  1168. repository: ` + expected[5].image + `
  1169. tag: ` + expected[5].tag + `
  1170. # mapped by user annotations
  1171. ` + expected[6].name + `:
  1172. customRepository: ` + expected[6].image + `
  1173. customTag: ` + expected[6].tag + `
  1174. `
  1175. resources, err := ParseMultidoc([]byte(doc), "test")
  1176. if err != nil {
  1177. t.Fatal(err)
  1178. }
  1179. res, ok := resources["test:helmrelease/test"]
  1180. if !ok {
  1181. t.Fatalf("expected resource not found; instead got %#v", resources)
  1182. }
  1183. hr, ok := res.(resource.Workload)
  1184. if !ok {
  1185. t.Fatalf("expected resource to be a Workload, instead got %#v", res)
  1186. }
  1187. containers := hr.Containers()
  1188. if len(containers) != len(expected) {
  1189. t.Fatalf("expected %d containers, got %d", len(expected), len(containers))
  1190. }
  1191. for i, c0 := range expected {
  1192. c1 := containers[i]
  1193. if c1.Name != c0.name {
  1194. t.Errorf("names do not match %q != %q", c0, c1)
  1195. }
  1196. var c0image string
  1197. if c0.registry != "" {
  1198. c0image = c0.registry + "/"
  1199. }
  1200. c0image += fmt.Sprintf("%s:%s", c0.image, c0.tag)
  1201. if c1.Image.String() != c0image {
  1202. t.Errorf("images do not match %q != %q", c0image, c1.Image.String())
  1203. }
  1204. }
  1205. }