github.com/bitrise-io/bitrise-step-update-gitops-repository@v0.0.0-20240426081835-1466be593380/pkg/gitops/templates_test.go (about) 1 package gitops 2 3 import ( 4 "os" 5 "path" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 // Possible templates to render. 13 const ( 14 templateValuesYAML = `--- 15 api-service: 16 image: 17 name: "{{ .repository }}:{{ .tag }}" 18 ` 19 templateChartYAML = `--- 20 apiVersion: v2 21 name: test 22 description: A test service 23 type: application 24 version: 0.1.0 25 appVersion: {{ .appVersion }} 26 dependencies: 27 - name: api-service 28 version: "0.1.1" 29 repository: "https://bitrise-io.github.io/k8s-recipes/" 30 ` 31 templateBrewFormulae = ` 32 class BitriseDenAgent < Formula 33 desc "CLI for Bitrise DEN agent" 34 homepage "https://github.com/bitrise-io/bitrise-den-agent" 35 url "https://github.com/bitrise-io/bitrise-den-agent.git", 36 tag: "{{ .brew_forumlae_tag }}", 37 revision: "{{ .brew_forumlae_revision }}" 38 license "" 39 end 40 ` 41 ) 42 43 // Possible outputs of rendered templates. 44 const ( 45 myRenderedValuesYAML = `--- 46 api-service: 47 image: 48 name: "myrepo:mytag" 49 ` 50 otherRenderedValuesYAML = `--- 51 api-service: 52 image: 53 name: "foo:bar" 54 ` 55 renderedChartYAML = `--- 56 apiVersion: v2 57 name: test 58 description: A test service 59 type: application 60 version: 0.1.0 61 appVersion: 2.4.5 62 dependencies: 63 - name: api-service 64 version: "0.1.1" 65 repository: "https://bitrise-io.github.io/k8s-recipes/" 66 ` 67 renderedBrewFormulae = ` 68 class BitriseDenAgent < Formula 69 desc "CLI for Bitrise DEN agent" 70 homepage "https://github.com/bitrise-io/bitrise-den-agent" 71 url "https://github.com/bitrise-io/bitrise-den-agent.git", 72 tag: "v1.2.3", 73 revision: "aaabbbcccdddeeefff" 74 license "" 75 end 76 ` 77 ) 78 79 var renderAllFilesCases = map[string]struct { 80 templates map[string]string 81 values map[string]string 82 folder string 83 wantFiles map[string]string 84 wantErr bool 85 }{ 86 "only values.yaml is rendered": { 87 templates: map[string]string{"values.yaml": templateValuesYAML}, 88 values: map[string]string{"repository": "myrepo", "tag": "mytag"}, 89 folder: "folder-with-values-yaml", 90 wantFiles: map[string]string{"values.yaml": myRenderedValuesYAML}, 91 }, 92 "values.yaml is rendered with other input": { 93 templates: map[string]string{"values.yaml": templateValuesYAML}, 94 values: map[string]string{"repository": "foo", "tag": "bar"}, 95 folder: "another-folder-with-values-yaml", 96 wantFiles: map[string]string{"values.yaml": otherRenderedValuesYAML}, 97 }, 98 "only Chart.yaml is rendered": { 99 templates: map[string]string{"Chart.yaml": templateChartYAML}, 100 values: map[string]string{"appVersion": "2.4.5"}, 101 folder: "folder-with-chart-yaml", 102 wantFiles: map[string]string{"Chart.yaml": renderedChartYAML}, 103 }, 104 "both Chart.yaml and values.yaml are rendered": { 105 templates: map[string]string{ 106 "values.yaml": templateValuesYAML, 107 "Chart.yaml": templateChartYAML, 108 }, 109 values: map[string]string{ 110 "repository": "myrepo", 111 "tag": "mytag", 112 "appVersion": "2.4.5", 113 }, 114 folder: "folder-with-multiple-files", 115 wantFiles: map[string]string{ 116 "values.yaml": myRenderedValuesYAML, 117 "Chart.yaml": renderedChartYAML, 118 }, 119 }, 120 "an unused template variable is present (it's ignored)": { 121 templates: map[string]string{"Chart.yaml": templateChartYAML}, 122 values: map[string]string{"appVersion": "2.4.5", "un": "used"}, 123 folder: "folder-with-unused-values", 124 wantFiles: map[string]string{"Chart.yaml": renderedChartYAML}, 125 }, 126 "a template variable is missing (error)": { 127 templates: map[string]string{"Chart.yaml": templateChartYAML}, 128 values: map[string]string{"appVersionTypo": "2.4.5"}, 129 folder: "wont-use-this-folder", 130 wantErr: true, 131 }, 132 "html tags are correctly rendered in brew formulae": { 133 templates: map[string]string{"formulae.rb": templateBrewFormulae}, 134 values: map[string]string{"brew_forumlae_tag": "v1.2.3", "brew_forumlae_revision": "aaabbbcccdddeeefff"}, 135 folder: "another-folder-with-values-yaml", 136 wantFiles: map[string]string{"formulae.rb": renderedBrewFormulae}, 137 }, 138 } 139 140 func TestRenderAllFiles(t *testing.T) { 141 for name, tc := range renderAllFilesCases { 142 t.Run(name, func(t *testing.T) { 143 // Create temporary directory for templates. 144 templatesDir, err := os.MkdirTemp("", "") 145 require.NoError(t, err, "new temp templates dir") 146 defer os.RemoveAll(templatesDir) 147 148 // Create a mock temporary directory for local clone of repository. 149 renderRepo, err := os.MkdirTemp("", "") 150 require.NoError(t, err, "new temp render repo") 151 defer os.RemoveAll(renderRepo) 152 // Create directory inside that for rendered files. 153 renderDir := path.Join(renderRepo, tc.folder) 154 require.NoError(t, os.Mkdir(renderDir, 0700), "new temp render dir") 155 156 // Copy desired templates to the previously created temp directory. 157 for fileName, content := range tc.templates { 158 filePath := path.Join(templatesDir, fileName) 159 err := os.WriteFile(filePath, []byte(content), 0600) 160 require.NoError(t, err, "write template %q", fileName) 161 } 162 163 // Run Templates.renderAllFiles. 164 tr := Templates{ 165 SourceFolder: templatesDir, 166 Values: tc.values, 167 DestinationRepo: &localRepositoryMock{ 168 localPathFunc: func() string { 169 return renderRepo 170 }, 171 }, 172 DestinationFolder: tc.folder, 173 } 174 175 // Assert for error. 176 gotErr := tr.renderAllFiles() 177 if tc.wantErr { 178 require.Error(t, gotErr, "templatesRenderer.renderAllFiles") 179 return 180 } 181 require.NoError(t, gotErr, "templatesRenderer.renderAllFiles") 182 183 // Assert for name of rendered files. 184 var wantFileNames []string 185 for name := range tc.wantFiles { 186 wantFileNames = append(wantFileNames, name) 187 } 188 189 var gotFileNames []string 190 gotFileInfos, err := os.ReadDir(renderDir) 191 require.NoError(t, err, "read files of render dir") 192 for _, v := range gotFileInfos { 193 gotFileNames = append(gotFileNames, v.Name()) 194 } 195 196 require.ElementsMatch(t, wantFileNames, gotFileNames, "file names") 197 198 // Assert for contents of rendered files. 199 for fileName, want := range tc.wantFiles { 200 filePath := path.Join(renderDir, fileName) 201 got, err := os.ReadFile(filePath) 202 require.NoError(t, err, "read contents of %q", filePath) 203 assert.EqualValues(t, want, string(got), "contents of %q", fileName) 204 } 205 }) 206 } 207 }