github.com/openshift/source-to-image@v1.4.1-0.20240516041539-bf52fc02204e/test/integration/dockerfile/dockerfile_test.go (about) 1 //go:build integration 2 // +build integration 3 4 package dockerfile 5 6 import ( 7 "bytes" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "regexp" 12 "strings" 13 "testing" 14 15 "github.com/moby/buildkit/frontend/dockerfile/parser" 16 17 "github.com/openshift/source-to-image/pkg/api" 18 "github.com/openshift/source-to-image/pkg/build" 19 "github.com/openshift/source-to-image/pkg/build/strategies" 20 "github.com/openshift/source-to-image/pkg/scm/git" 21 ) 22 23 func TestDockerfileBuild(t *testing.T) { 24 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 25 if err != nil { 26 t.Errorf("Unable to create temporary directory: %v", err) 27 } 28 defer os.RemoveAll(tempdir) 29 30 config := &api.Config{ 31 BuilderImage: "docker.io/centos/nodejs-8-centos7", 32 AssembleUser: "", 33 ImageWorkDir: "", 34 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 35 ScriptsURL: "", 36 Injections: api.VolumeList{}, 37 Destination: "", 38 39 Environment: api.EnvironmentList{}, 40 Labels: map[string]string{}, 41 42 AsDockerfile: tempdir + string(os.PathSeparator) + "MyDockerfile", 43 } 44 expected := []string{ 45 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 46 "\"io.openshift.s2i.build.commit.date\"", 47 "\"io.openshift.s2i.build.commit.id\"", 48 "\"io.openshift.s2i.build.commit.ref\"", 49 "\"io.openshift.s2i.build.commit.message\"", 50 "\"io.openshift.s2i.build.source-location\"", 51 "\"io.openshift.s2i.build.image\"=\"docker.io/centos/nodejs-8-centos7\"", 52 "\"io.openshift.s2i.build.commit.author\"", 53 "(?m)^COPY upload/src /tmp/src", 54 "(?m)^RUN chown -R 1001:0.* /tmp/src", 55 // Ensure we are using the default image user when running assemble 56 "(?m)^USER 1001\n.+\n.+\nRUN /usr/libexec/s2i/assemble", 57 "(?m)^CMD /usr/libexec/s2i/run", 58 } 59 expectedFiles := []string{ 60 filepath.Join(tempdir, "upload/src/server.js"), 61 filepath.Join(tempdir, "MyDockerfile"), 62 } 63 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 64 } 65 66 func TestDockerfileBuildDefaultDockerfile(t *testing.T) { 67 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 68 if err != nil { 69 t.Errorf("Unable to create temporary directory: %v", err) 70 } 71 defer os.RemoveAll(tempdir) 72 73 config := &api.Config{ 74 BuilderImage: "docker.io/centos/nodejs-8-centos7", 75 AssembleUser: "", 76 ImageWorkDir: "", 77 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 78 ScriptsURL: "", 79 Injections: api.VolumeList{}, 80 Destination: "", 81 82 Environment: api.EnvironmentList{}, 83 Labels: map[string]string{}, 84 85 AsDockerfile: tempdir + string(os.PathSeparator), 86 } 87 expected := []string{ 88 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 89 "\"io.openshift.s2i.build.commit.date\"", 90 "\"io.openshift.s2i.build.commit.id\"", 91 "\"io.openshift.s2i.build.commit.ref\"", 92 "\"io.openshift.s2i.build.commit.message\"", 93 "\"io.openshift.s2i.build.source-location\"", 94 "\"io.openshift.s2i.build.image\"=\"docker.io/centos/nodejs-8-centos7\"", 95 "\"io.openshift.s2i.build.commit.author\"", 96 "(?m)^COPY upload/src /tmp/src", 97 "(?m)^RUN chown -R 1001:0.* /tmp/src", 98 "(?m)^RUN /usr/libexec/s2i/assemble", 99 "(?m)^CMD /usr/libexec/s2i/run", 100 } 101 expectedFiles := []string{ 102 filepath.Join(tempdir, "upload/src/server.js"), 103 filepath.Join(tempdir, "Dockerfile"), 104 } 105 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 106 } 107 108 func TestDockerfileBuildEnv(t *testing.T) { 109 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 110 if err != nil { 111 t.Errorf("Unable to create temporary directory: %v", err) 112 } 113 defer os.RemoveAll(tempdir) 114 115 config := &api.Config{ 116 BuilderImage: "docker.io/centos/nodejs-8-centos7", 117 AssembleUser: "", 118 ImageWorkDir: "", 119 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 120 ScriptsURL: "", 121 Injections: api.VolumeList{}, 122 Destination: "", 123 124 Environment: api.EnvironmentList{ 125 { 126 Name: "key1", 127 Value: "value1", 128 }, 129 { 130 Name: "key2", 131 Value: "value2", 132 }, 133 }, 134 Labels: map[string]string{}, 135 136 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 137 } 138 139 expected := []string{ 140 "key1=\"value1\"", 141 "key2=\"value2\"", 142 } 143 runDockerfileTest(t, config, expected, nil, nil, false) 144 } 145 146 func TestDockerfileBuildLabels(t *testing.T) { 147 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 148 if err != nil { 149 t.Errorf("Unable to create temporary directory: %v", err) 150 } 151 defer os.RemoveAll(tempdir) 152 153 config := &api.Config{ 154 BuilderImage: "docker.io/centos/nodejs-8-centos7", 155 AssembleUser: "", 156 ImageWorkDir: "", 157 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 158 ScriptsURL: "image:///scripts", 159 Injections: api.VolumeList{}, 160 Destination: "/destination", 161 162 Environment: api.EnvironmentList{}, 163 Labels: map[string]string{"label1": "value1", 164 "label2": "value2", 165 "io.openshift.s2i.build.commit.author": "shadowman"}, 166 167 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 168 } 169 expected := []string{ 170 "\"io.openshift.s2i.scripts-url\"=\"image:///scripts\"", 171 "\"io.openshift.s2i.destination\"=\"/destination\"", 172 "\"io.openshift.s2i.build.commit.date\"", 173 "\"io.openshift.s2i.build.commit.id\"", 174 "\"io.openshift.s2i.build.commit.ref\"", 175 "\"io.openshift.s2i.build.commit.message\"", 176 "\"io.openshift.s2i.build.source-location\"", 177 "\"io.openshift.s2i.build.image\"=\"docker.io/centos/nodejs-8-centos7\"", 178 "\"io.openshift.s2i.build.commit.author\"=\"shadowman\"", 179 "\"label1\"=\"value1\"", 180 "\"label2\"=\"value2\"", 181 } 182 runDockerfileTest(t, config, expected, nil, nil, false) 183 } 184 185 func TestDockerfileBuildInjections(t *testing.T) { 186 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 187 if err != nil { 188 t.Errorf("Unable to create temporary directory: %v", err) 189 } 190 defer os.RemoveAll(tempdir) 191 192 injection1 := filepath.Join(tempdir, "injection1") 193 err = os.Mkdir(injection1, 0777) 194 if err != nil { 195 t.Errorf("Unable to create injection dir: %v", err) 196 } 197 198 for i := 0; i < 3; i++ { 199 _, err = ioutil.TempFile(injection1, "injectfile-") 200 if err != nil { 201 t.Errorf("Unable to create injection file: %v", err) 202 } 203 } 204 205 injection2 := filepath.Join(tempdir, "injection2") 206 err = os.Mkdir(injection2, 0777) 207 if err != nil { 208 t.Errorf("Unable to create injection dir: %v", err) 209 } 210 _, err = ioutil.TempFile(injection2, "injectfile-2") 211 if err != nil { 212 t.Errorf("Unable to create injection file: %v", err) 213 } 214 215 config := &api.Config{ 216 BuilderImage: "docker.io/centos/nodejs-8-centos7", 217 AssembleUser: "", 218 ImageWorkDir: "/workdir", 219 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 220 ScriptsURL: "", 221 Injections: api.VolumeList{ 222 { 223 Source: injection1, 224 Destination: "injection1", 225 Keep: false, 226 }, 227 { 228 Source: injection2, 229 Destination: "/destination/injection2", 230 Keep: true, 231 }, 232 }, 233 Destination: "", 234 235 Environment: api.EnvironmentList{}, 236 Labels: map[string]string{}, 237 238 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 239 } 240 241 // strip the C: from windows paths because it's not valid in the middle of a path 242 // like upload/injections/C:/tempdir/injection1 243 trimmedInjection1 := filepath.ToSlash(strings.TrimPrefix(injection1, filepath.VolumeName(injection1))) 244 trimmedInjection2 := filepath.ToSlash(strings.TrimPrefix(injection2, filepath.VolumeName(injection2))) 245 246 expected := []string{ 247 "(?m)^COPY upload/injections" + trimmedInjection1 + " /workdir/injection1", 248 "(?m)^RUN chown -R 1001:0.* /workdir/injection1", 249 "(?m)^COPY upload/injections" + trimmedInjection2 + " /destination/injection2", 250 "(?m)^RUN chown -R 1001:0.* /destination/injection2", 251 "(?m)^RUN rm /workdir/injection1/injectfile-", 252 " rm /workdir/injection1/injectfile-", 253 } 254 notExpected := []string{ 255 "rm -rf /destination/injection2", 256 } 257 expectedFiles := []string{ 258 filepath.Join(tempdir, "upload/src/server.js"), 259 filepath.Join(tempdir, "upload/injections"+trimmedInjection1), 260 filepath.Join(tempdir, "upload/injections"+trimmedInjection2), 261 } 262 runDockerfileTest(t, config, expected, notExpected, expectedFiles, false) 263 } 264 265 func TestDockerfileBuildScriptsURLAssemble(t *testing.T) { 266 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 267 if err != nil { 268 t.Errorf("Unable to create temporary directory: %v", err) 269 } 270 defer os.RemoveAll(tempdir) 271 272 assemble := filepath.Join(tempdir, "assemble") 273 _, err = os.OpenFile(assemble, os.O_RDONLY|os.O_CREATE, 0666) 274 if err != nil { 275 t.Errorf("Unable to create assemble file: %v", err) 276 } 277 278 config := &api.Config{ 279 BuilderImage: "docker.io/centos/nodejs-8-centos7", 280 AssembleUser: "", 281 ImageWorkDir: "", 282 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 283 ScriptsURL: "file://" + filepath.ToSlash(tempdir), 284 Injections: api.VolumeList{}, 285 Destination: "/destination", 286 287 Environment: api.EnvironmentList{}, 288 Labels: map[string]string{}, 289 290 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 291 } 292 expected := []string{ 293 "(?m)^COPY upload/scripts /destination/scripts", 294 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 295 "(?m)^RUN /destination/scripts/assemble", 296 "(?m)^CMD /usr/libexec/s2i/run", 297 } 298 expectedFiles := []string{ 299 filepath.Join(tempdir, "upload/src/server.js"), 300 filepath.Join(tempdir, "upload/scripts/assemble"), 301 } 302 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 303 } 304 305 func TestDockerfileBuildScriptsURLRun(t *testing.T) { 306 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 307 if err != nil { 308 t.Errorf("Unable to create temporary directory: %v", err) 309 } 310 defer os.RemoveAll(tempdir) 311 312 run := filepath.Join(tempdir, "run") 313 _, err = os.OpenFile(run, os.O_RDONLY|os.O_CREATE, 0666) 314 if err != nil { 315 t.Errorf("Unable to create run file: %v", err) 316 } 317 318 config := &api.Config{ 319 BuilderImage: "docker.io/centos/nodejs-8-centos7", 320 AssembleUser: "", 321 ImageWorkDir: "", 322 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 323 ScriptsURL: "file://" + filepath.ToSlash(tempdir), 324 Injections: api.VolumeList{}, 325 Destination: "/destination", 326 327 Environment: api.EnvironmentList{}, 328 Labels: map[string]string{}, 329 330 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 331 } 332 expected := []string{ 333 "(?m)^COPY upload/scripts /destination/scripts", 334 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 335 "(?m)^RUN /usr/libexec/s2i/assemble", 336 "(?m)^CMD /destination/scripts/run", 337 } 338 expectedFiles := []string{ 339 filepath.Join(tempdir, "upload/src/server.js"), 340 filepath.Join(tempdir, "upload/scripts/run"), 341 } 342 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 343 } 344 345 func TestDockerfileBuildScriptsURLNone(t *testing.T) { 346 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 347 if err != nil { 348 t.Errorf("Unable to create temporary directory: %v", err) 349 } 350 defer os.RemoveAll(tempdir) 351 352 config := &api.Config{ 353 BuilderImage: "docker.io/centos/nodejs-8-centos7", 354 AssembleUser: "", 355 ImageWorkDir: "", 356 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 357 ScriptsURL: "file://" + filepath.ToSlash(tempdir), 358 Injections: api.VolumeList{}, 359 Destination: "/destination", 360 361 Environment: api.EnvironmentList{}, 362 Labels: map[string]string{}, 363 364 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 365 } 366 runDockerfileTest(t, config, nil, nil, nil, true) 367 } 368 369 func TestDockerfileBuildSourceScriptsAssemble(t *testing.T) { 370 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 371 if err != nil { 372 t.Errorf("Unable to create temporary directory: %v", err) 373 } 374 defer os.RemoveAll(tempdir) 375 376 sourcecode := filepath.Join(tempdir, "sourcecode") 377 sourcescripts := filepath.Join(sourcecode, ".s2i", "bin") 378 err = os.MkdirAll(sourcescripts, 0777) 379 if err != nil { 380 t.Errorf("Unable to create injection dir: %v", err) 381 } 382 383 assemble := filepath.Join(sourcescripts, "assemble") 384 _, err = os.OpenFile(assemble, os.O_RDONLY|os.O_CREATE, 0666) 385 if err != nil { 386 t.Errorf("Unable to create assemble file: %v", err) 387 } 388 389 config := &api.Config{ 390 BuilderImage: "docker.io/centos/nodejs-8-centos7", 391 AssembleUser: "", 392 ImageWorkDir: "", 393 Source: git.MustParse("file:///" + filepath.ToSlash(sourcecode)), 394 ForceCopy: true, 395 ScriptsURL: "", 396 Injections: api.VolumeList{}, 397 Destination: "/destination", 398 399 Environment: api.EnvironmentList{}, 400 Labels: map[string]string{}, 401 402 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 403 } 404 expected := []string{ 405 "(?m)^COPY upload/scripts /destination/scripts", 406 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 407 "(?m)^RUN /destination/scripts/assemble", 408 "(?m)^CMD /usr/libexec/s2i/run", 409 } 410 expectedFiles := []string{ 411 filepath.Join(tempdir, "upload/scripts/assemble"), 412 } 413 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 414 } 415 416 func TestDockerfileBuildSourceScriptsRun(t *testing.T) { 417 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 418 if err != nil { 419 t.Errorf("Unable to create temporary directory: %v", err) 420 } 421 defer os.RemoveAll(tempdir) 422 423 sourcecode := filepath.Join(tempdir, "sourcecode") 424 sourcescripts := filepath.Join(sourcecode, ".s2i", "bin") 425 err = os.MkdirAll(sourcescripts, 0777) 426 if err != nil { 427 t.Errorf("Unable to create injection dir: %v", err) 428 } 429 430 run := filepath.Join(sourcescripts, "run") 431 _, err = os.OpenFile(run, os.O_RDONLY|os.O_CREATE, 0666) 432 if err != nil { 433 t.Errorf("Unable to create run file: %v", err) 434 } 435 436 config := &api.Config{ 437 BuilderImage: "docker.io/centos/nodejs-8-centos7", 438 AssembleUser: "", 439 ImageWorkDir: "", 440 Source: git.MustParse("file:///" + filepath.ToSlash(sourcecode)), 441 ForceCopy: true, 442 ScriptsURL: "", 443 Injections: api.VolumeList{}, 444 Destination: "/destination", 445 446 Environment: api.EnvironmentList{}, 447 Labels: map[string]string{}, 448 449 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 450 } 451 expected := []string{ 452 "(?m)^COPY upload/scripts /destination/scripts", 453 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 454 "(?m)^RUN /usr/libexec/s2i/assemble", 455 "(?m)^CMD /destination/scripts/run", 456 } 457 expectedFiles := []string{ 458 filepath.Join(tempdir, "upload/scripts/run"), 459 } 460 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 461 } 462 463 // TestDockerfileBuildScriptsURLImage tests the behavior if the ScriptsURL 464 // is set to an image:// URL. In this case we blind trust that the image 465 // contains all of the s2i scripts at the given directory, regardless 466 // of what is contained in the source. 467 func TestDockerfileBuildScriptsURLImage(t *testing.T) { 468 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 469 if err != nil { 470 t.Errorf("Unable to create temporary directory: %v", err) 471 } 472 defer os.RemoveAll(tempdir) 473 474 sourcecode := filepath.Join(tempdir, "sourcecode") 475 sourcescripts := filepath.Join(sourcecode, ".s2i", "bin") 476 err = os.MkdirAll(sourcescripts, 0777) 477 if err != nil { 478 t.Errorf("Unable to create injection dir: %v", err) 479 } 480 481 assemble := filepath.Join(sourcescripts, "assemble") 482 _, err = os.OpenFile(assemble, os.O_RDONLY|os.O_CREATE, 0666) 483 if err != nil { 484 t.Errorf("Unable to create assemble file: %v", err) 485 } 486 487 config := &api.Config{ 488 BuilderImage: "docker.io/centos/nodejs-8-centos7", 489 AssembleUser: "", 490 ImageWorkDir: "", 491 Source: git.MustParse("file:///" + filepath.ToSlash(sourcecode)), 492 ForceCopy: true, 493 ScriptsURL: "image:///usr/custom/s2i", 494 Injections: api.VolumeList{}, 495 Destination: "/destination", 496 497 Environment: api.EnvironmentList{}, 498 Labels: map[string]string{}, 499 500 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 501 } 502 expected := []string{ 503 "(?m)^RUN /usr/custom/s2i/assemble", 504 "(?m)^CMD /usr/custom/s2i/run", 505 } 506 notExpected := []string{ 507 "(?m)^COPY upload/scripts /destination/scripts", 508 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 509 "(?m)^RUN /destination/scripts/assemble", 510 } 511 runDockerfileTest(t, config, expected, notExpected, nil, false) 512 } 513 514 func TestDockerfileBuildImageScriptsURLAssemble(t *testing.T) { 515 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 516 if err != nil { 517 t.Errorf("Unable to create temporary directory: %v", err) 518 } 519 defer os.RemoveAll(tempdir) 520 521 assemble := filepath.Join(tempdir, "assemble") 522 _, err = os.OpenFile(assemble, os.O_RDONLY|os.O_CREATE, 0666) 523 if err != nil { 524 t.Errorf("Unable to create assemble file: %v", err) 525 } 526 527 config := &api.Config{ 528 BuilderImage: "docker.io/centos/nodejs-8-centos7", 529 AssembleUser: "", 530 ImageWorkDir: "", 531 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 532 ImageScriptsURL: "file://" + filepath.ToSlash(tempdir), 533 Injections: api.VolumeList{}, 534 Destination: "/destination", 535 536 Environment: api.EnvironmentList{}, 537 Labels: map[string]string{}, 538 539 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 540 } 541 expected := []string{ 542 "(?m)^COPY upload/scripts /destination/scripts", 543 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 544 "(?m)^RUN /destination/scripts/assemble", 545 "(?m)^CMD /usr/libexec/s2i/run", 546 } 547 expectedFiles := []string{ 548 filepath.Join(tempdir, "upload/src/server.js"), 549 filepath.Join(tempdir, "upload/scripts/assemble"), 550 } 551 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 552 } 553 554 func TestDockerfileBuildImageScriptsURLRun(t *testing.T) { 555 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 556 if err != nil { 557 t.Errorf("Unable to create temporary directory: %v", err) 558 } 559 defer os.RemoveAll(tempdir) 560 561 run := filepath.Join(tempdir, "run") 562 _, err = os.OpenFile(run, os.O_RDONLY|os.O_CREATE, 0666) 563 if err != nil { 564 t.Errorf("Unable to create run file: %v", err) 565 } 566 567 config := &api.Config{ 568 BuilderImage: "docker.io/centos/nodejs-8-centos7", 569 AssembleUser: "", 570 ImageWorkDir: "", 571 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 572 ImageScriptsURL: "file://" + filepath.ToSlash(tempdir), 573 Injections: api.VolumeList{}, 574 Destination: "/destination", 575 576 Environment: api.EnvironmentList{}, 577 Labels: map[string]string{}, 578 579 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 580 } 581 expected := []string{ 582 "(?m)^COPY upload/scripts /destination/scripts", 583 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 584 "(?m)^RUN /usr/libexec/s2i/assemble", 585 "(?m)^CMD /destination/scripts/run", 586 } 587 expectedFiles := []string{ 588 filepath.Join(tempdir, "upload/src/server.js"), 589 filepath.Join(tempdir, "upload/scripts/run"), 590 } 591 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 592 } 593 594 func TestDockerfileBuildImageScriptsURLImage(t *testing.T) { 595 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 596 if err != nil { 597 t.Errorf("Unable to create temporary directory: %v", err) 598 } 599 defer os.RemoveAll(tempdir) 600 601 sourcecode := filepath.Join(tempdir, "sourcecode") 602 sourcescripts := filepath.Join(sourcecode, ".s2i", "bin") 603 err = os.MkdirAll(sourcescripts, 0777) 604 if err != nil { 605 t.Errorf("Unable to create injection dir: %v", err) 606 } 607 608 assemble := filepath.Join(sourcescripts, "assemble") 609 _, err = os.OpenFile(assemble, os.O_RDONLY|os.O_CREATE, 0666) 610 if err != nil { 611 t.Errorf("Unable to create assemble file: %v", err) 612 } 613 614 config := &api.Config{ 615 BuilderImage: "docker.io/centos/nodejs-8-centos7", 616 AssembleUser: "", 617 ImageWorkDir: "", 618 Source: git.MustParse("file:///" + filepath.ToSlash(sourcecode)), 619 ForceCopy: true, 620 ImageScriptsURL: "image:///usr/custom/s2i", 621 Injections: api.VolumeList{}, 622 Destination: "/destination", 623 624 Environment: api.EnvironmentList{}, 625 Labels: map[string]string{}, 626 627 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 628 } 629 expected := []string{ 630 "(?m)^COPY upload/scripts /destination/scripts", 631 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 632 "(?m)^RUN /destination/scripts/assemble", 633 "(?m)^CMD /usr/custom/s2i/run", 634 } 635 expectedFiles := []string{ 636 filepath.Join(tempdir, "upload/scripts/assemble"), 637 } 638 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 639 } 640 641 func TestDockerfileBuildScriptsAndImageURL(t *testing.T) { 642 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 643 if err != nil { 644 t.Errorf("Unable to create temporary directory: %v", err) 645 } 646 defer os.RemoveAll(tempdir) 647 648 assemble := filepath.Join(tempdir, "assemble") 649 _, err = os.OpenFile(assemble, os.O_RDONLY|os.O_CREATE, 0666) 650 if err != nil { 651 t.Errorf("Unable to create assemble file: %v", err) 652 } 653 654 config := &api.Config{ 655 BuilderImage: "docker.io/centos/nodejs-8-centos7", 656 AssembleUser: "", 657 ImageWorkDir: "", 658 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 659 ScriptsURL: "file://" + filepath.ToSlash(tempdir), 660 ImageScriptsURL: "image:///usr/some/dir", 661 Injections: api.VolumeList{}, 662 Destination: "/destination", 663 664 Environment: api.EnvironmentList{}, 665 Labels: map[string]string{}, 666 667 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 668 } 669 expected := []string{ 670 "(?m)^COPY upload/scripts /destination/scripts", 671 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 672 "(?m)^RUN /destination/scripts/assemble", 673 "(?m)^CMD /usr/some/dir/run", 674 } 675 expectedFiles := []string{ 676 filepath.Join(tempdir, "upload/src/server.js"), 677 filepath.Join(tempdir, "upload/scripts/assemble"), 678 } 679 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 680 } 681 682 // TestDockerfileBuildScriptsAndImageURLConflicts tests if both 683 // the ScriptsURL and ImageScriptsURL point to a non-image directory. 684 // In this event, the ScriptsURL value should take precedence. 685 func TestDockerfileBuildScriptsAndImageURLConflicts(t *testing.T) { 686 scriptsTempDir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 687 if err != nil { 688 t.Errorf("Unable to create temporary directory: %v", err) 689 } 690 defer os.RemoveAll(scriptsTempDir) 691 692 imageTempDir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 693 if err != nil { 694 t.Errorf("Unable to create temporary directory: %v", err) 695 } 696 defer os.RemoveAll(imageTempDir) 697 698 outputDir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 699 if err != nil { 700 t.Errorf("Unable to create temporary directory: %v", err) 701 } 702 defer os.RemoveAll(outputDir) 703 704 scriptsAssemble := filepath.Join(scriptsTempDir, "assemble") 705 assembleData := []byte("#!/bin/bash\necho \"Hello World!\"") 706 err = ioutil.WriteFile(scriptsAssemble, assembleData, 0666) 707 if err != nil { 708 t.Errorf("Unable to create image assemble file: %v", err) 709 } 710 711 imageAssemble := filepath.Join(imageTempDir, "assemble") 712 _, err = os.OpenFile(imageAssemble, os.O_RDONLY|os.O_CREATE, 0666) 713 if err != nil { 714 t.Errorf("Unable to create assemble file: %v", err) 715 } 716 717 config := &api.Config{ 718 BuilderImage: "docker.io/centos/nodejs-8-centos7", 719 AssembleUser: "", 720 ImageWorkDir: "", 721 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 722 ScriptsURL: "file://" + filepath.ToSlash(scriptsTempDir), 723 ImageScriptsURL: "file://" + filepath.ToSlash(imageTempDir), 724 Injections: api.VolumeList{}, 725 Destination: "/destination", 726 727 Environment: api.EnvironmentList{}, 728 Labels: map[string]string{}, 729 730 AsDockerfile: filepath.Join(outputDir, "Dockerfile"), 731 } 732 expected := []string{ 733 "(?m)^COPY upload/scripts /destination/scripts", 734 "(?m)^RUN chown -R 1001:0.* /destination/scripts", 735 "(?m)^RUN /destination/scripts/assemble", 736 "(?m)^CMD /usr/libexec/s2i/run", 737 } 738 expectedFiles := []string{ 739 filepath.Join(outputDir, "upload/src/server.js"), 740 filepath.Join(outputDir, "upload/scripts/assemble"), 741 } 742 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 743 dockerfileAssemble, err := ioutil.ReadFile(filepath.Join(outputDir, "upload/scripts/assemble")) 744 if err != nil { 745 t.Errorf("Failed to read uploaded assemble script: %v", err) 746 } 747 if string(dockerfileAssemble) != string(assembleData) { 748 t.Errorf("Expected uploaded assemble script:\n\n%s\n\nto be:\n\n%s", dockerfileAssemble, assembleData) 749 } 750 } 751 752 func TestDockerfileIncrementalBuild(t *testing.T) { 753 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 754 if err != nil { 755 t.Errorf("Unable to create temporary directory: %v", err) 756 } 757 defer os.RemoveAll(tempdir) 758 759 config := &api.Config{ 760 BuilderImage: "docker.io/centos/nodejs-8-centos7", 761 AssembleUser: "", 762 ImageWorkDir: "", 763 Incremental: true, 764 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 765 ScriptsURL: "", 766 Tag: "test:tag", 767 Injections: api.VolumeList{}, 768 Destination: "", 769 770 Environment: api.EnvironmentList{}, 771 Labels: map[string]string{}, 772 773 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 774 } 775 776 expected := []string{ 777 "(?m)^FROM test:tag as cached\n#.+\nUSER 1001", 778 "(?m)^RUN if \\[ -s /usr/libexec/s2i/save-artifacts \\]; then /usr/libexec/s2i/save-artifacts > /tmp/artifacts.tar; else touch /tmp/artifacts.tar; fi", 779 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 780 "(?m)^COPY --from=cached /tmp/artifacts.tar /tmp/artifacts.tar", 781 "(?m)^RUN chown -R 1001:0.* /tmp/artifacts.tar", 782 "if \\[ -s /tmp/artifacts.tar \\]; then mkdir -p /tmp/artifacts; tar -xf /tmp/artifacts.tar -C /tmp/artifacts; fi", 783 "rm /tmp/artifacts.tar", 784 "(?m)^COPY upload/src /tmp/src", 785 "(?m)^RUN chown -R 1001:0.* /tmp/src", 786 "(?m)^RUN /usr/libexec/s2i/assemble", 787 "(?m)^CMD /usr/libexec/s2i/run", 788 } 789 790 runDockerfileTest(t, config, expected, nil, nil, false) 791 } 792 793 func TestDockerfileIncrementalSourceSave(t *testing.T) { 794 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 795 if err != nil { 796 t.Errorf("Unable to create temporary directory: %v", err) 797 } 798 defer os.RemoveAll(tempdir) 799 800 sourcecode := filepath.Join(tempdir, "sourcecode") 801 sourcescripts := filepath.Join(sourcecode, ".s2i", "bin") 802 err = os.MkdirAll(sourcescripts, 0777) 803 if err != nil { 804 t.Errorf("Unable to create injection dir: %v", err) 805 } 806 807 saveArtifacts := filepath.Join(sourcescripts, "save-artifacts") 808 _, err = os.OpenFile(saveArtifacts, os.O_RDONLY|os.O_CREATE, 0666) 809 if err != nil { 810 t.Errorf("Unable to create save-artifacts file: %v", err) 811 } 812 813 config := &api.Config{ 814 BuilderImage: "docker.io/centos/nodejs-8-centos7", 815 AssembleUser: "", 816 ImageWorkDir: "", 817 Incremental: true, 818 Source: git.MustParse("file:///" + filepath.ToSlash(sourcecode)), 819 ScriptsURL: "", 820 Tag: "test:tag", 821 Injections: api.VolumeList{}, 822 Destination: "/destination", 823 824 Environment: api.EnvironmentList{}, 825 Labels: map[string]string{}, 826 827 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 828 } 829 830 expected := []string{ 831 "(?m)^FROM test:tag as cached\n#.+\nUSER root\n", 832 "(?m)^COPY upload/scripts/save-artifacts /destination/scripts/save-artifacts", 833 "(?m)^RUN chown .*1001:0 /destination/scripts/save-artifacts", 834 "(?m)^USER 1001\nRUN if \\[ -s /destination/scripts/save-artifacts \\]; then /destination/scripts/save-artifacts > /tmp/artifacts.tar;", 835 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 836 "mkdir -p /destination/artifacts", 837 "tar -xf /tmp/artifacts.tar -C /destination/artifacts", 838 "(?m)^RUN /usr/libexec/s2i/assemble", 839 "(?m)^CMD /usr/libexec/s2i/run", 840 } 841 expectedFiles := []string{ 842 filepath.Join(tempdir, "upload/scripts/save-artifacts"), 843 } 844 845 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 846 } 847 848 func TestDockerfileIncrementalSaveURL(t *testing.T) { 849 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 850 if err != nil { 851 t.Errorf("Unable to create temporary directory: %v", err) 852 } 853 defer os.RemoveAll(tempdir) 854 855 saveArtifacts := filepath.Join(tempdir, "save-artifacts") 856 _, err = os.OpenFile(saveArtifacts, os.O_RDONLY|os.O_CREATE, 0666) 857 if err != nil { 858 t.Errorf("Unable to create save-artifacts file: %v", err) 859 } 860 861 config := &api.Config{ 862 BuilderImage: "docker.io/centos/nodejs-8-centos7", 863 AssembleUser: "", 864 ImageWorkDir: "", 865 Incremental: true, 866 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 867 ScriptsURL: "file://" + filepath.ToSlash(tempdir), 868 Tag: "test:tag", 869 Injections: api.VolumeList{}, 870 Destination: "/destination", 871 872 Environment: api.EnvironmentList{}, 873 Labels: map[string]string{}, 874 875 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 876 } 877 878 expected := []string{ 879 "(?m)^FROM test:tag as cached\n#.+\nUSER root\n", 880 "(?m)^COPY upload/scripts/save-artifacts /destination/scripts/save-artifacts", 881 "(?m)^RUN chown 1001:0 /destination/scripts/save-artifacts", 882 "(?m)^USER 1001\nRUN if \\[ -s /destination/scripts/save-artifacts \\]; then /destination/scripts/save-artifacts > /tmp/artifacts.tar;", 883 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 884 "mkdir -p /destination/artifacts", 885 "tar -xf /tmp/artifacts.tar -C /destination/artifacts", 886 "(?m)^RUN /usr/libexec/s2i/assemble", 887 "(?m)^CMD /usr/libexec/s2i/run", 888 } 889 expectedFiles := []string{ 890 filepath.Join(tempdir, "upload/scripts/save-artifacts"), 891 } 892 893 runDockerfileTest(t, config, expected, nil, expectedFiles, false) 894 } 895 896 func TestDockerfileIncrementalTag(t *testing.T) { 897 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 898 if err != nil { 899 t.Errorf("Unable to create temporary directory: %v", err) 900 } 901 defer os.RemoveAll(tempdir) 902 903 config := &api.Config{ 904 BuilderImage: "docker.io/centos/nodejs-8-centos7", 905 AssembleUser: "", 906 ImageWorkDir: "", 907 Incremental: true, 908 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 909 Tag: "test:tag", 910 IncrementalFromTag: "incremental:tag", 911 912 Environment: api.EnvironmentList{}, 913 Labels: map[string]string{}, 914 915 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 916 } 917 918 expected := []string{ 919 "(?m)^FROM incremental:tag as cached", 920 "/usr/libexec/s2i/save-artifacts > /tmp/artifacts.tar", 921 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 922 "mkdir -p /tmp/artifacts", 923 "tar -xf /tmp/artifacts.tar -C /tmp/artifacts", 924 "rm /tmp/artifacts.tar", 925 "(?m)^RUN /usr/libexec/s2i/assemble", 926 "(?m)^CMD /usr/libexec/s2i/run", 927 } 928 929 runDockerfileTest(t, config, expected, nil, nil, false) 930 } 931 932 func TestDockerfileIncrementalAssembleUser(t *testing.T) { 933 tempdir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 934 if err != nil { 935 t.Errorf("Unable to create temporary directory: %v", err) 936 } 937 defer os.RemoveAll(tempdir) 938 939 config := &api.Config{ 940 BuilderImage: "docker.io/centos/nodejs-8-centos7", 941 AssembleUser: "2250", 942 ImageWorkDir: "", 943 Incremental: true, 944 Source: git.MustParse("https://github.com/sclorg/nodejs-ex"), 945 Tag: "test:tag", 946 Environment: api.EnvironmentList{}, 947 Labels: map[string]string{}, 948 949 AsDockerfile: filepath.Join(tempdir, "Dockerfile"), 950 } 951 952 expected := []string{ 953 "(?m)^FROM test:tag as cached\n#.+\nUSER 2250", 954 "/usr/libexec/s2i/save-artifacts > /tmp/artifacts.tar", 955 "(?m)^FROM docker.io/centos/nodejs-8-centos7", 956 "(?m)^COPY --from=cached /tmp/artifacts.tar /tmp/artifacts.tar", 957 "(?m)^RUN chown -R 2250:0 .*/tmp/artifacts.tar", 958 "mkdir -p /tmp/artifacts", 959 "tar -xf /tmp/artifacts.tar -C /tmp/artifacts", 960 "rm /tmp/artifacts.tar", 961 "(?m)^RUN /usr/libexec/s2i/assemble", 962 "(?m)^CMD /usr/libexec/s2i/run", 963 } 964 965 runDockerfileTest(t, config, expected, nil, nil, false) 966 } 967 968 func TestDockerfileLocalSource(t *testing.T) { 969 localTempDir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 970 if err != nil { 971 t.Errorf("Unable to create temporary directory: %v", err) 972 } 973 defer os.RemoveAll(localTempDir) 974 975 outputDir, err := ioutil.TempDir("", "s2i-dockerfiletest-dir") 976 if err != nil { 977 t.Errorf("Unable to create temporary directory: %v", err) 978 } 979 defer os.RemoveAll(outputDir) 980 981 config := &api.Config{ 982 BuilderImage: "sti_test/sti-fake", 983 Source: git.MustParse("file:///" + filepath.ToSlash(localTempDir)), 984 AsDockerfile: filepath.Join(outputDir, "Dockerfile"), 985 } 986 987 dirTree := []string{ 988 "foo/bar", 989 "foo/baz/foobar", 990 } 991 for _, dirName := range dirTree { 992 err = os.MkdirAll(filepath.Join(localTempDir, dirName), 0777) 993 if err != nil { 994 t.Errorf("Unable to create dir: %v", err) 995 } 996 } 997 998 fileTree := []string{ 999 "foo/a_file", 1000 "foo/bar/a_file", 1001 "foo/bar/another_file", 1002 "foo/baz/foobar/a_file", 1003 } 1004 for _, fileName := range fileTree { 1005 dummyContent := []byte("Hello World!") 1006 err = ioutil.WriteFile(filepath.Join(localTempDir, fileName), dummyContent, 0666) 1007 if err != nil { 1008 t.Errorf("Unable to create file: %v", err) 1009 } 1010 } 1011 1012 expectedFiles := []string{ 1013 filepath.Join(outputDir, "upload/src/foo/a_file"), 1014 filepath.Join(outputDir, "upload/src/foo/bar"), 1015 filepath.Join(outputDir, "upload/src/foo/bar/a_file"), 1016 filepath.Join(outputDir, "upload/src/foo/bar/another_file"), 1017 filepath.Join(outputDir, "upload/src/foo/baz/foobar"), 1018 filepath.Join(outputDir, "upload/src/foo/baz/foobar/a_file"), 1019 } 1020 1021 runDockerfileTest(t, config, nil, nil, expectedFiles, false) 1022 1023 s2iignore := filepath.Join(localTempDir, ".s2iignore") 1024 s2iignoreDate := []byte("dummy\n#skip_file\nfoo/bar/another_file\nfoo/baz/foobar") 1025 err = ioutil.WriteFile(s2iignore, s2iignoreDate, 0666) 1026 if err != nil { 1027 t.Errorf("Unable to create .s2iignore file: %v", err) 1028 } 1029 1030 expectedFiles = []string{ 1031 filepath.Join(outputDir, "upload/src/foo/a_file"), 1032 filepath.Join(outputDir, "upload/src/foo/bar"), 1033 filepath.Join(outputDir, "upload/src/foo/bar/a_file"), 1034 } 1035 1036 runDockerfileTest(t, config, nil, nil, expectedFiles, false) 1037 } 1038 1039 func runDockerfileTest(t *testing.T, config *api.Config, expected []string, notExpected []string, expectedFiles []string, expectFailure bool) { 1040 1041 b, _, err := strategies.Strategy(nil, config, build.Overrides{}) 1042 if err != nil { 1043 t.Fatalf("Cannot create a new builder.") 1044 } 1045 resp, err := b.Build(config) 1046 if expectFailure { 1047 if err == nil || resp.Success { 1048 t.Errorf("The build succeded when it should have failed. Success: %t, error: %v", resp.Success, err) 1049 } 1050 return 1051 } 1052 if err != nil { 1053 t.Fatalf("An error occurred during the build: %v", err) 1054 } 1055 if !resp.Success { 1056 t.Fatalf("The build failed when it should have succeeded.") 1057 } 1058 1059 filebytes, err := ioutil.ReadFile(config.AsDockerfile) 1060 if err != nil { 1061 t.Fatalf("An error occurred reading the dockerfile: %v", err) 1062 } 1063 dockerfile := string(filebytes) 1064 1065 buf := bytes.NewBuffer(filebytes) 1066 _, err = parser.Parse(buf) 1067 if err != nil { 1068 t.Fatalf("An error occurred parsing the dockerfile: %v\n%s", err, dockerfile) 1069 } 1070 1071 for _, s := range expected { 1072 reg, err := regexp.Compile(s) 1073 if err != nil { 1074 t.Fatalf("failed to compile regex %q: %v", s, err) 1075 } 1076 if !reg.MatchString(dockerfile) { 1077 t.Fatalf("Expected dockerfile to contain %s, it did not: \n%s", s, dockerfile) 1078 } 1079 } 1080 for _, s := range notExpected { 1081 reg, err := regexp.Compile(s) 1082 if err != nil { 1083 t.Fatalf("failed to compile regex %q: %v", s, err) 1084 } 1085 if reg.MatchString(dockerfile) { 1086 t.Fatalf("Expected dockerfile not to contain %s, it did: \n%s", s, dockerfile) 1087 } 1088 } 1089 for _, f := range expectedFiles { 1090 if _, err := os.Stat(f); os.IsNotExist(err) { 1091 t.Fatalf("Did not find expected file %s, ", f) 1092 } 1093 } 1094 }