github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/initializer/init_test.go (about) 1 /* 2 Copyright 2020 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package initializer 18 19 import ( 20 "bytes" 21 "context" 22 "errors" 23 "fmt" 24 "os" 25 "path/filepath" 26 "runtime" 27 "strings" 28 "testing" 29 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" 31 initconfig "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/config" 32 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema" 33 "github.com/GoogleContainerTools/skaffold/testutil" 34 ) 35 36 func TestDoInit(t *testing.T) { 37 tests := []struct { 38 name string 39 shouldSkip bool 40 dir string 41 config initconfig.Config 42 expectedError string 43 expectedExitCode int 44 }{ 45 //TODO: mocked kompose test 46 { 47 name: "getting-started", 48 dir: "testdata/init/hello", 49 config: initconfig.Config{ 50 Force: true, 51 Opts: config.SkaffoldOptions{ 52 ConfigurationFile: "skaffold.yaml.out", 53 }, 54 }, 55 }, 56 { 57 name: "ignore existing tags", 58 dir: "testdata/init/ignore-tags", 59 config: initconfig.Config{ 60 Force: true, 61 Opts: config.SkaffoldOptions{ 62 ConfigurationFile: "skaffold.yaml.out", 63 }, 64 }, 65 }, 66 { 67 name: "microservices (backwards compatibility)", 68 dir: "testdata/init/microservices", 69 config: initconfig.Config{ 70 Force: true, 71 CliArtifacts: []string{ 72 "leeroy-app/Dockerfile=gcr.io/k8s-skaffold/leeroy-app", 73 "leeroy-web/Dockerfile=gcr.io/k8s-skaffold/leeroy-web", 74 }, 75 Opts: config.SkaffoldOptions{ 76 ConfigurationFile: "skaffold.yaml.out", 77 }, 78 }, 79 }, 80 { 81 name: "microservices", 82 dir: "testdata/init/microservices", 83 config: initconfig.Config{ 84 Force: true, 85 CliArtifacts: []string{ 86 `{"builder":"Docker","payload":{"path":"leeroy-app/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-app"}`, 87 `{"builder":"Docker","payload":{"path":"leeroy-web/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`, 88 }, 89 Opts: config.SkaffoldOptions{ 90 ConfigurationFile: "skaffold.yaml.out", 91 }, 92 }, 93 }, 94 { 95 name: "windows paths use forward slashes", 96 shouldSkip: runtime.GOOS != "windows", 97 dir: `testdata\init\windows`, 98 config: initconfig.Config{ 99 Force: true, 100 CliArtifacts: []string{ 101 `{"builder":"Docker","context":"apps\\web","payload":{"path":"apps\\web\\build\\Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`, 102 }, 103 Opts: config.SkaffoldOptions{ 104 ConfigurationFile: "skaffold.yaml.out", 105 }, 106 }, 107 }, 108 { 109 name: "CLI artifacts + manifest placeholders", 110 dir: "testdata/init/allcli", 111 config: initconfig.Config{ 112 Force: true, 113 CliArtifacts: []string{ 114 `{"builder":"Docker","payload":{"path":"Dockerfile"},"image":"passed-in-artifact"}`, 115 }, 116 CliKubernetesManifests: []string{ 117 "manifest-placeholder1.yaml", 118 "manifest-placeholder2.yaml", 119 }, 120 Opts: config.SkaffoldOptions{ 121 ConfigurationFile: "skaffold.yaml.out", 122 }, 123 }, 124 }, 125 { 126 name: "CLI artifacts but no manifests", 127 dir: "testdata/init/allcli", 128 config: initconfig.Config{ 129 Force: true, 130 CliArtifacts: []string{ 131 `{"builder":"Docker","payload":{"path":"Dockerfile"},"image":"passed-in-artifact"}`, 132 }, 133 Opts: config.SkaffoldOptions{ 134 ConfigurationFile: "skaffold.yaml.out", 135 }, 136 }, 137 expectedError: "one or more valid Kubernetes manifests are required to run skaffold", 138 expectedExitCode: 102, 139 }, 140 { 141 name: "error writing config file", 142 dir: "testdata/init/microservices", 143 config: initconfig.Config{ 144 Force: true, 145 CliArtifacts: []string{ 146 `{"builder":"Docker","payload":{"path":"leeroy-app/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-app"}`, 147 `{"builder":"Docker","payload":{"path":"leeroy-web/Dockerfile"},"image":"gcr.io/k8s-skaffold/leeroy-web"}`, 148 }, 149 Opts: config.SkaffoldOptions{ 150 // erroneous config file as . is a directory 151 ConfigurationFile: ".", 152 }, 153 }, 154 expectedError: "writing config to file: open .: is a directory", 155 expectedExitCode: 1, 156 }, 157 { 158 name: "error no builders", 159 dir: "testdata/init/no-builder", 160 config: initconfig.Config{ 161 Force: true, 162 Opts: config.SkaffoldOptions{ 163 ConfigurationFile: "skaffold.yaml.out", 164 }, 165 }, 166 expectedError: "please provide at least one build config", 167 expectedExitCode: 101, 168 }, 169 { 170 name: "error no manifests", 171 dir: "testdata/init/hello-no-manifest", 172 config: initconfig.Config{ 173 Force: true, 174 Opts: config.SkaffoldOptions{ 175 ConfigurationFile: "skaffold.yaml.out", 176 }, 177 }, 178 expectedError: "one or more valid Kubernetes manifests are required to run skaffold", 179 expectedExitCode: 102, 180 }, 181 { 182 name: "existing config", 183 dir: "testdata/init/hello", 184 config: initconfig.Config{ 185 Force: false, 186 Opts: config.SkaffoldOptions{ 187 ConfigurationFile: "skaffold.yaml", 188 }, 189 }, 190 expectedError: "pre-existing skaffold.yaml found", 191 expectedExitCode: 103, 192 }, 193 { 194 name: "builder/image ambiguity", 195 dir: "testdata/init/microservices", 196 config: initconfig.Config{ 197 Force: true, 198 Opts: config.SkaffoldOptions{ 199 ConfigurationFile: "skaffold.yaml.out", 200 }, 201 }, 202 expectedError: "unable to automatically resolve builder/image pairs", 203 expectedExitCode: 104, 204 }, 205 { 206 name: "kustomize", 207 dir: "testdata/init/getting-started-kustomize", 208 config: initconfig.Config{ 209 Force: true, 210 Opts: config.SkaffoldOptions{ 211 ConfigurationFile: "skaffold.yaml.out", 212 }, 213 }, 214 }, 215 { 216 name: "helm fails", 217 dir: "testdata/init/helm-deployment", 218 config: initconfig.Config{ 219 Opts: config.SkaffoldOptions{ 220 ConfigurationFile: "skaffold.yaml.out", 221 }, 222 }, 223 expectedError: `Projects set up to deploy with helm must be manually configured. 224 225 See https://skaffold.dev/docs/pipeline-stages/deployers/helm/ for a detailed guide on setting your project up with skaffold.`, 226 expectedExitCode: 1, 227 }, 228 } 229 for _, test := range tests { 230 testutil.Run(t, test.name, func(t *testutil.T) { 231 if test.shouldSkip { 232 t.Logf("Skipped test %q", test.name) 233 return 234 } 235 t.Chdir(test.dir) 236 237 err := DoInit(context.TODO(), os.Stdout, test.config) 238 239 if test.expectedError != "" { 240 t.CheckErrorContains(test.expectedError, err) 241 t.CheckDeepEqual(exitCode(err), test.expectedExitCode) 242 } else { 243 t.CheckNoError(err) 244 checkGeneratedConfig(t, ".") 245 } 246 }) 247 } 248 } 249 250 func TestDoInitAnalyze(t *testing.T) { 251 tests := []struct { 252 name string 253 dir string 254 config initconfig.Config 255 expectedOut string 256 }{ 257 { 258 name: "analyze microservices", 259 dir: "testdata/init/microservices", 260 config: initconfig.Config{ 261 Analyze: true, 262 }, 263 expectedOut: strip(`{ 264 "dockerfiles":["leeroy-app/Dockerfile","leeroy-web/Dockerfile"], 265 "images":["gcr.io/k8s-skaffold/leeroy-app","gcr.io/k8s-skaffold/leeroy-web"] 266 }`) + "\n", 267 }, 268 { 269 name: "analyze microservices new format", 270 dir: "testdata/init/microservices", 271 config: initconfig.Config{ 272 Analyze: true, 273 EnableNewInitFormat: true, 274 }, 275 expectedOut: strip(`{ 276 "builders":[ 277 {"name":"Docker","payload":{"path":"leeroy-app/Dockerfile"}}, 278 {"name":"Docker","payload":{"path":"leeroy-web/Dockerfile"}} 279 ], 280 "images":[ 281 {"name":"gcr.io/k8s-skaffold/leeroy-app","foundMatch":false}, 282 {"name":"gcr.io/k8s-skaffold/leeroy-web","foundMatch":false}]}`) + "\n", 283 }, 284 { 285 name: "no error with no manifests in analyze mode with skip-deploy", 286 dir: "testdata/init/hello-no-manifest", 287 288 config: initconfig.Config{ 289 Analyze: true, 290 SkipDeploy: true, 291 Opts: config.SkaffoldOptions{ 292 ConfigurationFile: "skaffold.yaml.out", 293 }, 294 }, 295 296 expectedOut: strip(`{"dockerfiles":["Dockerfile"]}`) + "\n", 297 }, 298 } 299 300 for _, test := range tests { 301 testutil.Run(t, test.name, func(t *testutil.T) { 302 var out bytes.Buffer 303 t.Chdir(test.dir) 304 305 err := DoInit(context.TODO(), &out, test.config) 306 307 t.CheckNoError(err) 308 t.CheckDeepEqual(test.expectedOut, out.String()) 309 }) 310 } 311 } 312 313 func strip(s string) string { 314 cutString := "\n\t\r" 315 stripped := "" 316 for _, r := range s { 317 if strings.ContainsRune(cutString, r) { 318 continue 319 } 320 stripped = fmt.Sprintf("%s%c", stripped, r) 321 } 322 return stripped 323 } 324 325 func checkGeneratedConfig(t *testutil.T, dir string) { 326 expectedOutput, err := schema.ParseConfig(filepath.Join(dir, "skaffold.yaml")) 327 t.CheckNoError(err) 328 329 output, err := schema.ParseConfig(filepath.Join(dir, "skaffold.yaml.out")) 330 t.CheckNoError(err) 331 t.CheckDeepEqual(expectedOutput, output) 332 } 333 334 type ExitCoder interface { 335 ExitCode() int 336 } 337 338 func exitCode(err error) int { 339 var exitErr ExitCoder 340 if ok := errors.As(err, &exitErr); ok { 341 return exitErr.ExitCode() 342 } 343 344 return 1 345 }