github.com/GoogleContainerTools/skaffold/v2@v2.13.2/integration/render_test.go (about) 1 /* 2 Copyright 2019 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 integration 18 19 import ( 20 "bytes" 21 "context" 22 "fmt" 23 "os" 24 "path" 25 "path/filepath" 26 "regexp" 27 "testing" 28 29 "gopkg.in/yaml.v2" 30 31 "github.com/GoogleContainerTools/skaffold/v2/integration/skaffold" 32 "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/graph" 33 "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/render" 34 "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/render/renderer/kubectl" 35 "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/schema/latest" 36 "github.com/GoogleContainerTools/skaffold/v2/testutil" 37 ) 38 39 func TestKubectlRenderOutput(t *testing.T) { 40 ns, _ := SetupNamespace(t) 41 test := struct { 42 description string 43 builds []graph.Artifact 44 input string 45 expectedOut string 46 }{ 47 description: "write rendered manifest to provided filepath", 48 builds: []graph.Artifact{ 49 { 50 ImageName: "us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold", 51 Tag: "us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold:test", 52 }, 53 }, 54 input: `apiVersion: v1 55 kind: Pod 56 spec: 57 containers: 58 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold 59 name: skaffold 60 `, 61 expectedOut: fmt.Sprintf(`apiVersion: v1 62 kind: Pod 63 metadata: 64 namespace: %s 65 spec: 66 containers: 67 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold:test 68 name: skaffold`, ns.Name)} 69 70 testutil.Run(t, test.description, func(t *testutil.T) { 71 MarkIntegrationTest(t.T, CanRunWithoutGcp) 72 tmpDir := t.NewTempDir() 73 tmpDir.Write("deployment.yaml", test.input).Chdir() 74 75 rc := latest.RenderConfig{ 76 Generate: latest.Generate{ 77 RawK8s: []string{"deployment.yaml"}}, 78 } 79 mockCfg := render.MockConfig{WorkingDir: tmpDir.Root()} 80 r, err := kubectl.New(mockCfg, rc, map[string]string{}, "default", ns.Name, nil, true) 81 t.RequireNoError(err) 82 var b bytes.Buffer 83 l, err := r.Render(context.Background(), &b, test.builds, false) 84 85 t.CheckNoError(err) 86 87 t.CheckDeepEqual(test.expectedOut, l.String(), testutil.YamlObj(t.T)) 88 }) 89 } 90 91 func TestKubectlRender(t *testing.T) { 92 ns, _ := SetupNamespace(t) 93 tests := []struct { 94 description string 95 builds []graph.Artifact 96 input string 97 expectedOut string 98 }{ 99 { 100 description: "normal render", 101 builds: []graph.Artifact{ 102 { 103 ImageName: "us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold", 104 Tag: "us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold:test", 105 }, 106 }, 107 input: `apiVersion: v1 108 kind: Pod 109 metadata: 110 name: my-pod-123 111 spec: 112 containers: 113 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold 114 name: skaffold 115 `, 116 expectedOut: fmt.Sprintf(`apiVersion: v1 117 kind: Pod 118 metadata: 119 name: my-pod-123 120 namespace: %s 121 spec: 122 containers: 123 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold:test 124 name: skaffold`, ns.Name), 125 }, 126 { 127 description: "two artifacts", 128 builds: []graph.Artifact{ 129 { 130 ImageName: "gcr.io/project/image1", 131 Tag: "gcr.io/project/image1:tag1", 132 }, 133 { 134 ImageName: "gcr.io/project/image2", 135 Tag: "gcr.io/project/image2:tag2", 136 }, 137 }, 138 input: `apiVersion: v1 139 kind: Pod 140 metadata: 141 name: my-pod-123 142 spec: 143 containers: 144 - image: gcr.io/project/image1 145 name: image1 146 - image: gcr.io/project/image2 147 name: image2 148 `, 149 expectedOut: fmt.Sprintf(`apiVersion: v1 150 kind: Pod 151 metadata: 152 name: my-pod-123 153 namespace: %s 154 spec: 155 containers: 156 - image: gcr.io/project/image1:tag1 157 name: image1 158 - image: gcr.io/project/image2:tag2 159 name: image2`, ns.Name), 160 }, 161 { 162 description: "two artifacts, combined manifests", 163 builds: []graph.Artifact{ 164 { 165 ImageName: "gcr.io/project/image1", 166 Tag: "gcr.io/project/image1:tag1", 167 }, 168 { 169 ImageName: "gcr.io/project/image2", 170 Tag: "gcr.io/project/image2:tag2", 171 }, 172 }, 173 input: `apiVersion: v1 174 kind: Pod 175 metadata: 176 name: my-pod-123 177 spec: 178 containers: 179 - image: gcr.io/project/image1 180 name: image1 181 --- 182 apiVersion: v1 183 kind: Pod 184 metadata: 185 name: my-pod-456 186 spec: 187 containers: 188 - image: gcr.io/project/image2 189 name: image2 190 `, 191 expectedOut: fmt.Sprintf(`apiVersion: v1 192 kind: Pod 193 metadata: 194 name: my-pod-123 195 namespace: %s 196 spec: 197 containers: 198 - image: gcr.io/project/image1:tag1 199 name: image1 200 --- 201 apiVersion: v1 202 kind: Pod 203 metadata: 204 name: my-pod-456 205 namespace: %s 206 spec: 207 containers: 208 - image: gcr.io/project/image2:tag2 209 name: image2`, ns.Name, ns.Name), 210 }, 211 } 212 for _, test := range tests { 213 testutil.Run(t, test.description, func(t *testutil.T) { 214 MarkIntegrationTest(t.T, CanRunWithoutGcp) 215 tmpDir := t.NewTempDir() 216 tmpDir.Write("deployment.yaml", test.input). 217 Chdir() 218 rc := latest.RenderConfig{ 219 Generate: latest.Generate{ 220 RawK8s: []string{"deployment.yaml"}}, 221 } 222 mockCfg := render.MockConfig{WorkingDir: tmpDir.Root()} 223 r, err := kubectl.New(mockCfg, rc, map[string]string{}, "default", ns.Name, nil, true) 224 t.RequireNoError(err) 225 var b bytes.Buffer 226 l, err := r.Render(context.Background(), &b, test.builds, false) 227 228 t.CheckNoError(err) 229 t.CheckDeepEqual(test.expectedOut, l.String(), testutil.YamlObj(t.T)) 230 }) 231 } 232 } 233 234 func TestHelmRender(t *testing.T) { 235 tests := []struct { 236 description string 237 dir string 238 args []string 239 builds []graph.Artifact 240 helmReleases []latest.HelmRelease 241 expectedOut string 242 withoutBuildJSON bool 243 }{ 244 { 245 description: "Bare bones render", 246 dir: "testdata/gke_loadbalancer-render", 247 expectedOut: `apiVersion: v1 248 kind: Service 249 metadata: 250 labels: 251 app: gke-loadbalancer 252 skaffold.dev/run-id: phony-run-id 253 name: gke-loadbalancer 254 spec: 255 ports: 256 - name: http 257 port: 80 258 protocol: TCP 259 targetPort: 3000 260 selector: 261 app: gke-loadbalancer 262 type: LoadBalancer 263 --- 264 apiVersion: apps/v1 265 kind: Deployment 266 metadata: 267 labels: 268 app: gke-loadbalancer 269 skaffold.dev/run-id: phony-run-id 270 name: gke-loadbalancer 271 spec: 272 replicas: 1 273 selector: 274 matchLabels: 275 app: gke-loadbalancer 276 template: 277 metadata: 278 labels: 279 app: gke-loadbalancer 280 skaffold.dev/run-id: phony-run-id 281 spec: 282 containers: 283 - image: gke-loadbalancer:test 284 name: gke-container 285 ports: 286 - containerPort: 3000 287 `, 288 }, 289 { 290 description: "A more complex template", 291 dir: "testdata/helm-render", 292 args: []string{"--profile=helm-render"}, 293 expectedOut: `apiVersion: v1 294 kind: Service 295 metadata: 296 labels: 297 app: skaffold-helm 298 chart: skaffold-helm-0.1.0 299 heritage: Helm 300 release: skaffold-helm 301 skaffold.dev/run-id: phony-run-id 302 name: skaffold-helm-skaffold-helm 303 spec: 304 ports: 305 - name: nginx 306 port: 80 307 protocol: TCP 308 targetPort: 80 309 selector: 310 app: skaffold-helm 311 release: skaffold-helm 312 type: ClusterIP 313 --- 314 apiVersion: apps/v1 315 kind: Deployment 316 metadata: 317 labels: 318 app: skaffold-helm 319 chart: skaffold-helm-0.1.0 320 heritage: Helm 321 release: skaffold-helm 322 skaffold.dev/run-id: phony-run-id 323 name: skaffold-helm 324 spec: 325 replicas: 1 326 selector: 327 matchLabels: 328 app: skaffold-helm 329 release: skaffold-helm 330 template: 331 metadata: 332 labels: 333 app: skaffold-helm 334 release: skaffold-helm 335 skaffold.dev/run-id: phony-run-id 336 spec: 337 containers: 338 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold-helm:sha256-nonsenselettersandnumbers 339 imagePullPolicy: always 340 name: skaffold-helm 341 ports: 342 - containerPort: 80 343 resources: {} 344 --- 345 apiVersion: networking.k8s.io/v1 346 kind: Ingress 347 metadata: 348 annotations: null 349 labels: 350 app: skaffold-helm 351 chart: skaffold-helm-0.1.0 352 heritage: Helm 353 release: skaffold-helm 354 name: skaffold-helm-skaffold-helm 355 spec: 356 rules: 357 - http: 358 paths: 359 - backend: 360 service: 361 name: skaffold-helm-skaffold-helm 362 port: 363 number: 80 364 path: / 365 pathType: ImplementationSpecific 366 `, 367 }, { 368 description: "Template with Release.namespace set from skaffold.yaml file deploy.helm.releases.namespace", 369 dir: "testdata/helm-deploy-namespace", 370 withoutBuildJSON: true, 371 expectedOut: `apiVersion: apps/v1 372 kind: Deployment 373 metadata: 374 labels: 375 app: skaffold-helm 376 skaffold.dev/run-id: phony-run-id 377 name: skaffold-helm 378 namespace: helm-namespace 379 spec: 380 replicas: 2 381 selector: 382 matchLabels: 383 app: skaffold-helm 384 template: 385 metadata: 386 labels: 387 app: skaffold-helm 388 skaffold.dev/run-id: phony-run-id 389 spec: 390 containers: 391 - image: skaffold-helm:latest 392 name: skaffold-helm 393 `, 394 }, { 395 description: "Template with Release.namespace set from skaffold.yaml file manifests.helm.releases.namespace", 396 dir: "testdata/helm-manifests-namespace", 397 withoutBuildJSON: true, 398 expectedOut: `apiVersion: apps/v1 399 kind: Deployment 400 metadata: 401 labels: 402 app: skaffold-helm 403 skaffold.dev/run-id: phony-run-id 404 name: skaffold-helm 405 namespace: helm-namespace 406 spec: 407 replicas: 2 408 selector: 409 matchLabels: 410 app: skaffold-helm 411 template: 412 metadata: 413 labels: 414 app: skaffold-helm 415 skaffold.dev/run-id: phony-run-id 416 spec: 417 containers: 418 - image: skaffold-helm:latest 419 name: skaffold-helm 420 `, 421 }, { 422 description: "Template with Release.namespace set from skaffold.yaml file manifests.helm.releases.namespace and deploy.helm.releases.namespace", 423 dir: "testdata/helm-manifests-and-deploy-namespace", 424 withoutBuildJSON: true, 425 expectedOut: `apiVersion: apps/v1 426 kind: Deployment 427 metadata: 428 labels: 429 app: skaffold-helm 430 skaffold.dev/run-id: phony-run-id 431 name: skaffold-helm 432 namespace: helm-namespace-1 433 spec: 434 replicas: 2 435 selector: 436 matchLabels: 437 app: skaffold-helm 438 template: 439 metadata: 440 labels: 441 app: skaffold-helm 442 skaffold.dev/run-id: phony-run-id 443 spec: 444 containers: 445 - image: skaffold-helm:latest 446 name: skaffold-helm 447 `, 448 }, { 449 description: "Template with Release.namespace set from skaffold.yaml file deploy.helm.releases.namespace - v1 skaffold schema", 450 dir: "testdata/helm-deploy-namespace-v1-schema", 451 withoutBuildJSON: true, 452 expectedOut: `apiVersion: apps/v1 453 kind: Deployment 454 metadata: 455 labels: 456 app: skaffold-helm 457 skaffold.dev/run-id: phony-run-id 458 name: skaffold-helm 459 namespace: helm-namespace 460 spec: 461 replicas: 2 462 selector: 463 matchLabels: 464 app: skaffold-helm 465 template: 466 metadata: 467 labels: 468 app: skaffold-helm 469 skaffold.dev/run-id: phony-run-id 470 spec: 471 containers: 472 - image: skaffold-helm:latest 473 name: skaffold-helm 474 `, 475 }, 476 { 477 description: "Template replicaCount with --set flag", 478 dir: "testdata/helm-render-simple", 479 args: []string{"--set", "replicaCount=3"}, 480 withoutBuildJSON: true, 481 expectedOut: `apiVersion: apps/v1 482 kind: Deployment 483 metadata: 484 labels: 485 app: skaffold-helm 486 skaffold.dev/run-id: phony-run-id 487 name: skaffold-helm 488 namespace: helm-namespace 489 spec: 490 replicas: 3 491 selector: 492 matchLabels: 493 app: skaffold-helm 494 template: 495 metadata: 496 labels: 497 app: skaffold-helm 498 skaffold.dev/run-id: phony-run-id 499 spec: 500 containers: 501 - image: skaffold-helm:latest 502 name: skaffold-helm 503 `, 504 }, 505 { 506 description: "With Helm global flags", 507 dir: "testdata/helm-render", 508 args: []string{"-p", "helm-render-with-global-flags"}, 509 withoutBuildJSON: true, 510 expectedOut: `apiVersion: v1 511 kind: Service 512 metadata: 513 labels: 514 app: skaffold-helm 515 chart: skaffold-helm-0.1.0 516 heritage: Helm 517 release: skaffold-helm 518 skaffold.dev/run-id: phony-run-id 519 name: skaffold-helm-skaffold-helm 520 spec: 521 ports: 522 - name: nginx 523 port: 80 524 protocol: TCP 525 targetPort: 80 526 selector: 527 app: skaffold-helm 528 release: skaffold-helm 529 type: ClusterIP 530 --- 531 apiVersion: apps/v1 532 kind: Deployment 533 metadata: 534 labels: 535 app: skaffold-helm 536 chart: skaffold-helm-0.1.0 537 heritage: Helm 538 release: skaffold-helm 539 skaffold.dev/run-id: phony-run-id 540 name: skaffold-helm 541 spec: 542 replicas: 1 543 selector: 544 matchLabels: 545 app: skaffold-helm 546 release: skaffold-helm 547 template: 548 metadata: 549 labels: 550 app: skaffold-helm 551 release: skaffold-helm 552 skaffold.dev/run-id: phony-run-id 553 spec: 554 containers: 555 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold-helm:latest 556 imagePullPolicy: always 557 name: skaffold-helm 558 ports: 559 - containerPort: 80 560 resources: {} 561 --- 562 apiVersion: networking.k8s.io/v1 563 kind: Ingress 564 metadata: 565 annotations: null 566 labels: 567 app: skaffold-helm 568 chart: skaffold-helm-0.1.0 569 heritage: Helm 570 release: skaffold-helm 571 name: skaffold-helm-skaffold-helm 572 spec: 573 rules: 574 - http: 575 paths: 576 - backend: 577 service: 578 name: skaffold-helm-skaffold-helm 579 port: 580 number: 80 581 path: / 582 pathType: ImplementationSpecific 583 `, 584 }, 585 } 586 for _, test := range tests { 587 t.Run(test.description, func(t *testing.T) { 588 MarkIntegrationTest(t, CanRunWithoutGcp) 589 590 args := []string{"--default-repo=", "--label=skaffold.dev/run-id=phony-run-id"} 591 if !test.withoutBuildJSON { 592 args = append(args, "--build-artifacts=builds.out.json") 593 } 594 args = append(args, test.args...) 595 596 out := skaffold.Render(args...).InDir(test.dir).RunOrFailOutput(t) 597 598 testutil.CheckDeepEqual(t, test.expectedOut, string(out), testutil.YamlObj(t)) 599 }) 600 } 601 } 602 603 func TestRenderWithBuilds(t *testing.T) { 604 tests := []struct { 605 description string 606 config string 607 buildOutputFilePath string 608 images string 609 offline bool 610 input map[string]string // file path => content 611 expectedOut string 612 namespaceFlag string 613 }{ 614 { 615 description: "kubectl render from build output, online, no labels", 616 config: ` 617 apiVersion: skaffold/v2alpha1 618 kind: Config 619 620 # Irrelevant for rendering from previous build output 621 build: 622 artifacts: [] 623 624 deploy: 625 kubectl: 626 manifests: 627 - deployment.yaml 628 `, 629 buildOutputFilePath: "testdata/render/build-output.json", 630 offline: false, 631 input: map[string]string{"deployment.yaml": ` 632 apiVersion: v1 633 kind: Pod 634 metadata: 635 name: my-pod-123 636 spec: 637 containers: 638 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 639 name: a 640 - image: gcr.io/my/project-b 641 name: b 642 `}, 643 expectedOut: `apiVersion: v1 644 kind: Pod 645 metadata: 646 name: my-pod-123 647 spec: 648 containers: 649 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 650 name: a 651 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 652 name: b 653 `, 654 }, 655 { 656 description: "kubectl render from build output, offline, no labels", 657 config: ` 658 apiVersion: skaffold/v2alpha1 659 kind: Config 660 661 # Irrelevant for rendering from previous build output 662 build: 663 artifacts: [] 664 665 deploy: 666 kubectl: 667 manifests: 668 - deployment.yaml 669 `, 670 buildOutputFilePath: "testdata/render/build-output.json", 671 offline: true, 672 input: map[string]string{"deployment.yaml": ` 673 apiVersion: v1 674 kind: Pod 675 metadata: 676 name: my-pod-123 677 spec: 678 containers: 679 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 680 name: a 681 - image: gcr.io/my/project-b 682 name: b 683 `}, 684 // No `metadata.namespace` in offline mode 685 expectedOut: `apiVersion: v1 686 kind: Pod 687 metadata: 688 name: my-pod-123 689 spec: 690 containers: 691 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 692 name: a 693 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 694 name: b 695 `, 696 }, 697 698 { 699 description: "kubectl render from build output, offline, with labels", 700 config: ` 701 apiVersion: skaffold/v2alpha1 702 kind: Config 703 704 # Irrelevant for rendering from previous build output 705 build: 706 artifacts: [] 707 708 deploy: 709 kubectl: 710 manifests: 711 - deployment.yaml 712 `, 713 buildOutputFilePath: "testdata/render/build-output.json", 714 offline: true, 715 input: map[string]string{"deployment.yaml": ` 716 apiVersion: v1 717 kind: Pod 718 metadata: 719 name: my-pod-123 720 spec: 721 containers: 722 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 723 name: a 724 - image: gcr.io/my/project-b 725 name: b 726 `}, 727 // No `metadata.namespace` in offline mode 728 expectedOut: `apiVersion: v1 729 kind: Pod 730 metadata: 731 name: my-pod-123 732 spec: 733 containers: 734 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 735 name: a 736 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 737 name: b 738 `, 739 }, 740 741 { 742 description: "kustomize render from build output, offline, no labels", 743 config: ` 744 apiVersion: skaffold/v2alpha1 745 kind: Config 746 747 # Irrelevant for rendering from previous build output 748 build: 749 artifacts: [] 750 751 deploy: 752 kustomize: {} # defaults to current working directory 753 `, 754 buildOutputFilePath: "testdata/render/build-output.json", 755 offline: true, 756 input: map[string]string{"deployment.yaml": ` 757 apiVersion: v1 758 kind: Pod 759 metadata: 760 name: my-pod-123 761 spec: 762 containers: 763 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 764 name: a 765 - image: gcr.io/my/project-b 766 name: b 767 `, 768 "kustomization.yaml": ` 769 commonLabels: 770 this-is-from: kustomization.yaml 771 772 resources: 773 - deployment.yaml 774 `}, 775 // No `metadata.namespace` in offline mode 776 expectedOut: `apiVersion: v1 777 kind: Pod 778 metadata: 779 labels: 780 this-is-from: kustomization.yaml 781 name: my-pod-123 782 spec: 783 containers: 784 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 785 name: a 786 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 787 name: b 788 `, 789 }, 790 791 { 792 description: "kustomize render from build output, offline, with labels", 793 config: ` 794 apiVersion: skaffold/v2alpha1 795 kind: Config 796 797 # Irrelevant for rendering from previous build output 798 build: 799 artifacts: [] 800 801 deploy: 802 kustomize: {} # defaults to current working directory 803 `, 804 buildOutputFilePath: "testdata/render/build-output.json", 805 offline: true, 806 input: map[string]string{"deployment.yaml": ` 807 apiVersion: v1 808 kind: Pod 809 metadata: 810 name: my-pod-123 811 spec: 812 containers: 813 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 814 name: a 815 - image: gcr.io/my/project-b 816 name: b 817 `, 818 "kustomization.yaml": ` 819 commonLabels: 820 this-is-from: kustomization.yaml 821 822 resources: 823 - deployment.yaml 824 `}, 825 // No `metadata.namespace` in offline mode 826 expectedOut: `apiVersion: v1 827 kind: Pod 828 metadata: 829 labels: 830 this-is-from: kustomization.yaml 831 name: my-pod-123 832 spec: 833 containers: 834 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 835 name: a 836 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 837 name: b 838 `, 839 }, 840 { 841 description: "kustomize render from build output, offline=false", 842 config: ` 843 apiVersion: skaffold/v4beta2 844 kind: Config 845 846 # Irrelevant for rendering from previous build output 847 build: 848 artifacts: [] 849 850 manifests: 851 kustomize: 852 paths: 853 - . 854 `, 855 buildOutputFilePath: "testdata/render/build-output.json", 856 offline: false, 857 input: map[string]string{"pod.yaml": ` 858 apiVersion: v1 859 kind: Pod 860 metadata: 861 name: my-pod-123 862 spec: 863 containers: 864 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 865 name: a 866 - image: gcr.io/my/project-b 867 name: b 868 `, 869 "kustomization.yaml": ` 870 commonLabels: 871 this-is-from: kustomization.yaml 872 873 resources: 874 - pod.yaml 875 `}, 876 // No `metadata.namespace` should be injected 877 expectedOut: `apiVersion: v1 878 kind: Pod 879 metadata: 880 labels: 881 this-is-from: kustomization.yaml 882 name: my-pod-123 883 spec: 884 containers: 885 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 886 name: a 887 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 888 name: b 889 `, 890 }, 891 { 892 description: "kustomize + rawYaml render from build output, offline=false", 893 config: ` 894 apiVersion: skaffold/v4beta2 895 kind: Config 896 897 # Irrelevant for rendering from previous build output 898 build: 899 artifacts: [] 900 901 manifests: 902 rawYaml: 903 - pod2.yaml 904 kustomize: 905 paths: 906 - . 907 `, 908 buildOutputFilePath: "testdata/render/build-output.json", 909 offline: false, 910 input: map[string]string{"pod1.yaml": ` 911 apiVersion: v1 912 kind: Pod 913 metadata: 914 name: my-pod-1 915 spec: 916 containers: 917 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 918 name: a 919 - image: gcr.io/my/project-b 920 name: b 921 `, 922 "pod2.yaml": ` 923 apiVersion: v1 924 kind: Pod 925 metadata: 926 name: my-pod-2 927 spec: 928 containers: 929 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 930 name: a 931 - image: gcr.io/my/project-b 932 name: b 933 `, 934 "kustomization.yaml": ` 935 commonLabels: 936 this-is-from: kustomization.yaml 937 938 resources: 939 - pod1.yaml 940 `}, 941 // No `metadata.namespace` should be injected in the manifest rendererd by kustomize 942 expectedOut: `apiVersion: v1 943 kind: Pod 944 metadata: 945 name: my-pod-2 946 spec: 947 containers: 948 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 949 name: a 950 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 951 name: b 952 --- 953 apiVersion: v1 954 kind: Pod 955 metadata: 956 labels: 957 this-is-from: kustomization.yaml 958 name: my-pod-1 959 spec: 960 containers: 961 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 962 name: a 963 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 964 name: b 965 `, 966 }, 967 { 968 description: "kustomize + rawYaml render from build output, offline=false, with namespace flag", 969 namespaceFlag: "mynamespace", 970 config: ` 971 apiVersion: skaffold/v4beta2 972 kind: Config 973 974 # Irrelevant for rendering from previous build output 975 build: 976 artifacts: [] 977 978 manifests: 979 rawYaml: 980 - pod2.yaml 981 kustomize: 982 paths: 983 - . 984 `, 985 buildOutputFilePath: "testdata/render/build-output.json", 986 offline: false, 987 input: map[string]string{"pod1.yaml": ` 988 apiVersion: v1 989 kind: Pod 990 metadata: 991 name: my-pod-1 992 spec: 993 containers: 994 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 995 name: a 996 - image: gcr.io/my/project-b 997 name: b 998 `, 999 "pod2.yaml": ` 1000 apiVersion: v1 1001 kind: Pod 1002 metadata: 1003 name: my-pod-2 1004 spec: 1005 containers: 1006 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 1007 name: a 1008 - image: gcr.io/my/project-b 1009 name: b 1010 `, 1011 "kustomization.yaml": ` 1012 commonLabels: 1013 this-is-from: kustomization.yaml 1014 1015 resources: 1016 - pod1.yaml 1017 `}, 1018 // No `metadata.namespace` should be injected in the manifest rendererd by kustomize 1019 expectedOut: `apiVersion: v1 1020 kind: Pod 1021 metadata: 1022 name: my-pod-2 1023 namespace: mynamespace 1024 spec: 1025 containers: 1026 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 1027 name: a 1028 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 1029 name: b 1030 --- 1031 apiVersion: v1 1032 kind: Pod 1033 metadata: 1034 namespace: mynamespace 1035 labels: 1036 this-is-from: kustomization.yaml 1037 name: my-pod-1 1038 spec: 1039 containers: 1040 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 1041 name: a 1042 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 1043 name: b 1044 `, 1045 }, 1046 { 1047 description: "kubectl render with images", 1048 config: ` 1049 apiVersion: skaffold/v2alpha1 1050 kind: Config 1051 1052 # Irrelevant for rendering from previous build output 1053 build: 1054 artifacts: [] 1055 1056 deploy: 1057 kubectl: 1058 manifests: 1059 - deployment.yaml 1060 `, 1061 images: "12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf,gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc", 1062 offline: false, 1063 input: map[string]string{"deployment.yaml": ` 1064 apiVersion: v1 1065 kind: Pod 1066 metadata: 1067 name: my-pod-123 1068 spec: 1069 containers: 1070 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a 1071 name: a 1072 - image: gcr.io/my/project-b 1073 name: b 1074 `}, 1075 expectedOut: `apiVersion: v1 1076 kind: Pod 1077 metadata: 1078 name: my-pod-123 1079 spec: 1080 containers: 1081 - image: 12345.dkr.ecr.eu-central-1.amazonaws.com/my/project-a:4da6a56988057d23f68a4e988f4905dd930ea438-dirty@sha256:d8a33c260c50385ea54077bc7032dba0a860dc8870464f6795fd0aa548d117bf 1082 name: a 1083 - image: gcr.io/my/project-b:764841f8bac17e625724adcbf0d28013f22d058f-dirty@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc 1084 name: b 1085 `, 1086 }, 1087 } 1088 1089 testDir, err := os.Getwd() 1090 if err != nil { 1091 t.Fatal(err) 1092 } 1093 1094 for _, test := range tests { 1095 testutil.Run(t, test.description, func(t *testutil.T) { 1096 MarkIntegrationTest(t.T, CanRunWithoutGcp) 1097 tmpDir := t.NewTempDir() 1098 tmpDir.Write("skaffold.yaml", test.config) 1099 1100 for filePath, content := range test.input { 1101 tmpDir.Write(filePath, content) 1102 } 1103 1104 tmpDir.Chdir() 1105 1106 // `--default-repo=` is used to cancel the default repo that is set by default. 1107 args := []string{"--default-repo=", "--digest-source=local", "--output", "rendered.yaml"} 1108 if test.buildOutputFilePath != "" { 1109 args = append(args, "--build-artifacts="+path.Join(testDir, test.buildOutputFilePath)) 1110 } else { 1111 args = append(args, "--images="+test.images) 1112 } 1113 1114 if test.namespaceFlag != "" { 1115 args = append(args, "--namespace", test.namespaceFlag) 1116 } 1117 1118 if test.offline { 1119 env := []string{"KUBECONFIG=not-supposed-to-be-used-in-offline-mode"} 1120 args = append(args, "--offline=true") 1121 skaffold.Render(args...).WithEnv(env).RunOrFail(t.T) 1122 } else { 1123 skaffold.Render(args...).RunOrFail(t.T) 1124 } 1125 1126 fileContent, err := os.ReadFile("rendered.yaml") 1127 t.RequireNoError(err) 1128 1129 // Tests are written in a way that actual output is valid YAML 1130 parsed := make(map[string]interface{}) 1131 err = yaml.UnmarshalStrict(fileContent, parsed) 1132 t.CheckNoError(err) 1133 1134 fileContentReplaced := regexp.MustCompile("(?m)(skaffold.dev/run-id|skaffold.dev/docker-api-version): .+$").ReplaceAll(fileContent, []byte("$1: SOMEDYNAMICVALUE")) 1135 1136 t.RequireNoError(err) 1137 t.CheckDeepEqual(test.expectedOut, string(fileContentReplaced), testutil.YamlObj(t.T)) 1138 }) 1139 } 1140 } 1141 1142 func TestRenderHydrationDirCreation(t *testing.T) { 1143 MarkIntegrationTest(t, CanRunWithoutGcp) 1144 const hydrationDir = "hydration-dir" 1145 1146 tests := []struct { 1147 description string 1148 shouldCreateHydrationDir bool 1149 config string 1150 manifest string 1151 }{ 1152 { 1153 description: "project with kpt renderer should create hydration dir", 1154 shouldCreateHydrationDir: true, 1155 config: ` 1156 apiVersion: skaffold/v4beta1 1157 kind: Config 1158 1159 build: 1160 artifacts: [] 1161 manifests: 1162 kpt: [] 1163 `, 1164 manifest: ` 1165 apiVersion: v1 1166 kind: Pod 1167 metadata: 1168 name: getting-started 1169 spec: 1170 containers: 1171 - name: getting-started 1172 image: skaffold-example`, 1173 }, 1174 { 1175 description: "project with kpt deployer should create hydration dir", 1176 shouldCreateHydrationDir: true, 1177 config: ` 1178 apiVersion: skaffold/v4beta1 1179 kind: Config 1180 1181 build: 1182 artifacts: [] 1183 manifests: 1184 kpt: [] 1185 deploy: 1186 kpt: {} 1187 `, 1188 manifest: ` 1189 apiVersion: v1 1190 kind: Pod 1191 metadata: 1192 name: getting-started 1193 spec: 1194 containers: 1195 - name: getting-started 1196 image: skaffold-example`, 1197 }, 1198 { 1199 description: "project with rawYaml and transform should not create hydration dir (uses kpt renderer)", 1200 shouldCreateHydrationDir: false, 1201 config: ` 1202 apiVersion: skaffold/v4beta1 1203 kind: Config 1204 1205 build: 1206 artifacts: [] 1207 manifests: 1208 rawYaml: 1209 - k8s/k8s-pod.yaml 1210 transform: 1211 - name: set-annotations 1212 configMap: 1213 - "author:fake-author" 1214 `, 1215 manifest: ` 1216 apiVersion: v1 1217 kind: Pod 1218 metadata: 1219 name: getting-started 1220 spec: 1221 containers: 1222 - name: getting-started 1223 image: skaffold-example`, 1224 }, 1225 { 1226 description: "project without kpt should not create hydration dir", 1227 shouldCreateHydrationDir: false, 1228 config: ` 1229 apiVersion: skaffold/v4beta1 1230 kind: Config 1231 1232 build: 1233 artifacts: [] 1234 manifests: 1235 rawYaml: 1236 - k8s/k8s-pod.yaml 1237 `, 1238 manifest: ` 1239 apiVersion: v1 1240 kind: Pod 1241 metadata: 1242 name: getting-started 1243 spec: 1244 containers: 1245 - name: getting-started 1246 image: skaffold-example`, 1247 }, 1248 } 1249 1250 for _, test := range tests { 1251 testutil.Run(t, test.description, func(t *testutil.T) { 1252 tmpDir := t.NewTempDir() 1253 tmpDir.Mkdir("k8s") 1254 tmpDir.Write("skaffold.yaml", test.config) 1255 tmpDir.Write("k8s/k8s-pod.yaml", test.manifest) 1256 tmpDir.Chdir() 1257 1258 args := []string{"--hydration-dir", hydrationDir} 1259 1260 skaffold.Render(args...).RunOrFail(t.T) 1261 1262 _, err := os.Stat(filepath.Join(tmpDir.Root(), hydrationDir)) 1263 1264 if test.shouldCreateHydrationDir { 1265 t.CheckFalse(os.IsNotExist(err)) 1266 } else { 1267 t.CheckTrue(os.IsNotExist(err)) 1268 } 1269 }) 1270 } 1271 } 1272 1273 func TestRenderParameterization(t *testing.T) { 1274 tests := []struct { 1275 description string 1276 args []string 1277 WithBuildArtifacts bool 1278 config string 1279 input map[string]string // file path => content 1280 expectedOut string 1281 }{ 1282 { 1283 description: "kubectl set manifest label with apply-setters", 1284 args: []string{"--offline=true"}, 1285 config: `apiVersion: skaffold/v4beta2 1286 kind: Config 1287 manifests: 1288 rawYaml: 1289 - k8s-pod.yaml 1290 transform: 1291 - name: apply-setters 1292 configMap: 1293 - "app1:from-apply-setters-1" 1294 `, 1295 input: map[string]string{ 1296 "k8s-pod.yaml": `apiVersion: v1 1297 kind: Pod 1298 metadata: 1299 name: getting-started 1300 labels: 1301 a: hhhh # kpt-set: ${app1} 1302 spec: 1303 containers: 1304 - name: getting-started 1305 image: skaffold-example`, 1306 }, expectedOut: `apiVersion: v1 1307 kind: Pod 1308 metadata: 1309 name: getting-started 1310 labels: 1311 a: from-apply-setters-1 1312 spec: 1313 containers: 1314 - name: getting-started 1315 image: skaffold-example 1316 `, 1317 }, 1318 {description: "kustomize set annotation with set-annotations transformer", 1319 args: []string{"--offline=true"}, 1320 config: `apiVersion: skaffold/v4beta2 1321 kind: Config 1322 manifests: 1323 kustomize: 1324 paths: 1325 - . 1326 transform: 1327 - name: set-annotations 1328 configMap: 1329 - "author:fake-author"`, 1330 input: map[string]string{ 1331 "kustomization.yaml": `resources: 1332 - deployment.yaml 1333 patchesStrategicMerge: 1334 - patch.yaml 1335 `, "deployment.yaml": `apiVersion: apps/v1 1336 kind: Deployment 1337 metadata: 1338 name: kustomize-test 1339 labels: 1340 app: kustomize-test 1341 spec: 1342 replicas: 1 1343 selector: 1344 matchLabels: 1345 app: kustomize-test 1346 template: 1347 metadata: 1348 labels: 1349 app: kustomize-test 1350 spec: 1351 containers: 1352 - name: kustomize-test 1353 image: not/a/valid/image 1354 `, "patch.yaml": `apiVersion: apps/v1 1355 kind: Deployment 1356 metadata: 1357 name: kustomize-test 1358 spec: 1359 template: 1360 spec: 1361 containers: 1362 - name: kustomize-test 1363 image: index.docker.io/library/busybox 1364 command: 1365 - sleep 1366 - "3600" 1367 `}, 1368 expectedOut: `apiVersion: apps/v1 1369 kind: Deployment 1370 metadata: 1371 annotations: 1372 author: fake-author 1373 labels: 1374 app: kustomize-test 1375 name: kustomize-test 1376 spec: 1377 replicas: 1 1378 selector: 1379 matchLabels: 1380 app: kustomize-test 1381 template: 1382 metadata: 1383 annotations: 1384 author: fake-author 1385 labels: 1386 app: kustomize-test 1387 spec: 1388 containers: 1389 - command: 1390 - sleep 1391 - "3600" 1392 image: index.docker.io/library/busybox 1393 name: kustomize-test 1394 `}, 1395 { 1396 description: "kustomize/overlay parameterization with --set flag", 1397 args: []string{"--offline", "--set", "env2=222a", "--set", "app1=111a"}, 1398 config: `apiVersion: skaffold/v4beta2 1399 kind: Config 1400 metadata: 1401 name: getting-started-kustomize 1402 manifests: 1403 kustomize: 1404 paths: 1405 - overlays/dev 1406 `, input: map[string]string{"base/kustomization.yaml": ` 1407 apiVersion: kustomize.config.k8s.io/v1beta1 1408 kind: Kustomization 1409 1410 resources: 1411 - deployment.yaml 1412 `, "base/deployment.yaml": `apiVersion: apps/v1 1413 kind: Deployment 1414 metadata: 1415 name: skaffold-kustomize 1416 labels: 1417 app: skaffold-kustomize # from-param: ${app1} 1418 spec: 1419 selector: 1420 matchLabels: 1421 app: skaffold-kustomize 1422 template: 1423 metadata: 1424 labels: 1425 app: skaffold-kustomize 1426 spec: 1427 containers: 1428 - name: skaffold-kustomize 1429 image: skaffold-kustomize 1430 `, "overlays/dev/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1 1431 kind: Kustomization 1432 1433 # namespace: dev 1434 nameSuffix: -dev 1435 1436 patchesStrategicMerge: 1437 - deployment.yaml 1438 1439 resources: 1440 - ../../base 1441 `, "overlays/dev/deployment.yaml": `apiVersion: apps/v1 1442 kind: Deployment 1443 metadata: 1444 name: skaffold-kustomize 1445 labels: 1446 env: dev # from-param: ${env2} 1447 `}, expectedOut: ` 1448 apiVersion: apps/v1 1449 kind: Deployment 1450 metadata: 1451 labels: 1452 app: 111a 1453 env: 222a 1454 name: skaffold-kustomize-dev 1455 spec: 1456 selector: 1457 matchLabels: 1458 app: skaffold-kustomize 1459 template: 1460 metadata: 1461 labels: 1462 app: skaffold-kustomize 1463 spec: 1464 containers: 1465 - image: skaffold-kustomize 1466 name: skaffold-kustomize 1467 `, 1468 }, 1469 { 1470 description: "kustomize parameterization success with patches", 1471 args: []string{"--offline", "--set", "app1=111a"}, 1472 config: `apiVersion: skaffold/v4beta2 1473 kind: Config 1474 metadata: 1475 name: getting-started-kustomize 1476 manifests: 1477 kustomize: 1478 paths: 1479 - base 1480 `, input: map[string]string{"base/kustomization.yaml": ` 1481 apiVersion: kustomize.config.k8s.io/v1beta1 1482 kind: Kustomization 1483 patches: 1484 - path: patch.yaml 1485 target: 1486 group: apps 1487 version: v1 1488 kind: Deployment 1489 name: skaffold-kustomize 1490 resources: 1491 - deployment.yaml 1492 `, "base/deployment.yaml": `apiVersion: apps/v1 1493 kind: Deployment 1494 metadata: 1495 name: skaffold-kustomize 1496 labels: 1497 app: skaffold-kustomize # from-param: ${app1} 1498 spec: 1499 selector: 1500 matchLabels: 1501 app: skaffold-kustomize 1502 template: 1503 metadata: 1504 labels: 1505 app: skaffold-kustomize 1506 spec: 1507 containers: 1508 - name: skaffold-kustomize 1509 image: skaffold-kustomize 1510 `, "base/patch.yaml": ` 1511 - op: add 1512 path: /metadata/annotations/example.com 1513 value: dummy 1514 `}, expectedOut: ` 1515 apiVersion: apps/v1 1516 kind: Deployment 1517 metadata: 1518 labels: 1519 app: 111a 1520 name: skaffold-kustomize 1521 annotations: 1522 example.com: dummy 1523 spec: 1524 selector: 1525 matchLabels: 1526 app: skaffold-kustomize 1527 template: 1528 metadata: 1529 labels: 1530 app: skaffold-kustomize 1531 spec: 1532 containers: 1533 - image: skaffold-kustomize 1534 name: skaffold-kustomize 1535 `, 1536 }, 1537 {description: "test set transformer values with value file", 1538 args: []string{"--offline=true", "--set-value-file", "values.env"}, 1539 config: ` 1540 apiVersion: skaffold/v4beta2 1541 kind: Config 1542 manifests: 1543 rawYaml: 1544 - k8s-pod.yaml 1545 `, 1546 input: map[string]string{ 1547 "k8s-pod.yaml": ` 1548 apiVersion: v1 1549 kind: Pod 1550 metadata: 1551 name: getting-started 1552 labels: 1553 a: hhhh # from-param: ${app1} 1554 spec: 1555 containers: 1556 - name: getting-started 1557 image: skaffold-example`, 1558 "values.env": `app1=from-file`, 1559 }, expectedOut: `apiVersion: v1 1560 kind: Pod 1561 metadata: 1562 name: getting-started 1563 labels: 1564 a: from-file 1565 spec: 1566 containers: 1567 - name: getting-started 1568 image: skaffold-example 1569 `, 1570 }, 1571 { 1572 description: "test set transformer values with value file and value from command-line", 1573 args: []string{"--offline=true", "--set-value-file", "values.env", "--set", "app2=from-command-line"}, 1574 config: ` 1575 apiVersion: skaffold/v4beta2 1576 kind: Config 1577 manifests: 1578 rawYaml: 1579 - k8s-pod.yaml 1580 transform: 1581 - name: apply-setters 1582 configMap: 1583 - "app1:from-apply-setters-1" 1584 `, 1585 input: map[string]string{ 1586 "k8s-pod.yaml": ` 1587 apiVersion: v1 1588 kind: Pod 1589 metadata: 1590 name: getting-started 1591 labels: 1592 a: hhhh # from-param: ${app1} 1593 b: hhhh # from-param: ${app2} 1594 spec: 1595 containers: 1596 - name: getting-started 1597 image: skaffold-example`, 1598 "values.env": `app1=from-file`, 1599 }, expectedOut: `apiVersion: v1 1600 kind: Pod 1601 metadata: 1602 name: getting-started 1603 labels: 1604 a: from-file 1605 b: from-command-line 1606 spec: 1607 containers: 1608 - name: getting-started 1609 image: skaffold-example 1610 `}, 1611 { 1612 description: "test set transformer file values respect values from command-line", 1613 args: []string{"--offline=true", "--set-value-file", "values.env", "--set", "app1=from-command-line"}, 1614 config: ` 1615 apiVersion: skaffold/v4beta2 1616 kind: Config 1617 manifests: 1618 rawYaml: 1619 - k8s-pod.yaml 1620 transform: 1621 - name: apply-setters 1622 configMap: 1623 - "app1:from-apply-setters-1" 1624 `, 1625 input: map[string]string{ 1626 "k8s-pod.yaml": ` 1627 apiVersion: v1 1628 kind: Pod 1629 metadata: 1630 name: getting-started 1631 labels: 1632 a: hhhh # from-param: ${app1} 1633 spec: 1634 containers: 1635 - name: getting-started 1636 image: skaffold-example`, 1637 "values.env": `app1=from-file`, 1638 }, expectedOut: `apiVersion: v1 1639 kind: Pod 1640 metadata: 1641 name: getting-started 1642 labels: 1643 a: from-command-line 1644 spec: 1645 containers: 1646 - name: getting-started 1647 image: skaffold-example 1648 `}, 1649 { 1650 description: "test set param with helm native template(replicaCount)", 1651 args: []string{"--offline=true", "--set", "replicaCount=5"}, 1652 config: ` 1653 apiVersion: skaffold/v4beta2 1654 kind: Config 1655 manifests: 1656 helm: 1657 releases: 1658 - name: skaffold-helm 1659 chartPath: charts 1660 namespace: helm-namespace 1661 `, 1662 input: map[string]string{ 1663 "charts/templates/deployments.yaml": ` 1664 apiVersion: apps/v1 1665 kind: Deployment 1666 metadata: 1667 name: {{ .Chart.Name }} 1668 namespace: {{ .Release.Namespace }} 1669 labels: 1670 app: {{ .Chart.Name }} 1671 spec: 1672 selector: 1673 matchLabels: 1674 app: {{ .Chart.Name }} 1675 replicas: {{ .Values.replicaCount }} 1676 template: 1677 metadata: 1678 labels: 1679 app: {{ .Chart.Name }} 1680 spec: 1681 containers: 1682 - name: {{ .Chart.Name }} 1683 image: {{ .Values.image }} 1684 `, 1685 "charts/Chart.yaml": ` 1686 apiVersion: v1 1687 description: Skaffold example with Helm 1688 name: skaffold-helm 1689 version: 0.1.0 1690 `, 1691 "charts/values.yaml": ` 1692 replicaCount: 2 1693 image: skaffold-helm:latest 1694 `, 1695 }, expectedOut: `apiVersion: apps/v1 1696 kind: Deployment 1697 metadata: 1698 name: skaffold-helm 1699 namespace: helm-namespace 1700 labels: 1701 app: skaffold-helm 1702 spec: 1703 selector: 1704 matchLabels: 1705 app: skaffold-helm 1706 replicas: 5 1707 template: 1708 metadata: 1709 labels: 1710 app: skaffold-helm 1711 spec: 1712 containers: 1713 - name: skaffold-helm 1714 image: skaffold-helm:latest 1715 `}, 1716 { 1717 description: "test set param with helm #from-param overrides native template(replicaCount) is comment templated field provided", 1718 args: []string{"--offline=true", "--set", "replicaCount=5", "--set", "count=6"}, 1719 WithBuildArtifacts: true, 1720 config: ` 1721 apiVersion: skaffold/v4beta2 1722 kind: Config 1723 manifests: 1724 helm: 1725 releases: 1726 - name: skaffold-helm 1727 chartPath: charts 1728 namespace: helm-namespace 1729 `, 1730 input: map[string]string{ 1731 "charts/templates/deployments.yaml": ` 1732 apiVersion: apps/v1 1733 kind: Deployment 1734 metadata: 1735 name: {{ .Chart.Name }} 1736 namespace: {{ .Release.Namespace }} 1737 labels: 1738 app: {{ .Chart.Name }} 1739 spec: 1740 selector: 1741 matchLabels: 1742 app: {{ .Chart.Name }} 1743 replicas: {{ .Values.replicaCount }} # from-param: ${count} 1744 template: 1745 metadata: 1746 labels: 1747 app: {{ .Chart.Name }} 1748 spec: 1749 containers: 1750 - name: {{ .Chart.Name }} 1751 image: {{ .Values.image }} 1752 `, 1753 "charts/Chart.yaml": ` 1754 apiVersion: v1 1755 description: Skaffold example with Helm 1756 name: skaffold-helm 1757 version: 0.1.0 1758 `, 1759 "charts/values.yaml": ` 1760 replicaCount: 2 1761 image: skaffold-helm:latest 1762 `, 1763 }, expectedOut: `apiVersion: apps/v1 1764 kind: Deployment 1765 metadata: 1766 name: skaffold-helm 1767 namespace: helm-namespace 1768 labels: 1769 app: skaffold-helm 1770 spec: 1771 selector: 1772 matchLabels: 1773 app: skaffold-helm 1774 replicas: 6 1775 template: 1776 metadata: 1777 labels: 1778 app: skaffold-helm 1779 spec: 1780 containers: 1781 - name: skaffold-helm 1782 image: skaffold-helm:latest 1783 `}, 1784 { 1785 description: "test set param with helm #from-param has no effect on native template(replicaCount) when comment templated field value not provided", 1786 args: []string{"--offline=true", "--set", "replicaCount=5"}, 1787 WithBuildArtifacts: true, 1788 config: ` 1789 apiVersion: skaffold/v4beta2 1790 kind: Config 1791 manifests: 1792 helm: 1793 releases: 1794 - name: skaffold-helm 1795 chartPath: charts 1796 namespace: helm-namespace 1797 `, 1798 input: map[string]string{ 1799 "charts/templates/deployments.yaml": ` 1800 apiVersion: apps/v1 1801 kind: Deployment 1802 metadata: 1803 name: {{ .Chart.Name }} 1804 namespace: {{ .Release.Namespace }} 1805 labels: 1806 app: {{ .Chart.Name }} 1807 spec: 1808 selector: 1809 matchLabels: 1810 app: {{ .Chart.Name }} 1811 replicas: {{ .Values.replicaCount }} # from-param: ${count} 1812 template: 1813 metadata: 1814 labels: 1815 app: {{ .Chart.Name }} 1816 spec: 1817 containers: 1818 - name: {{ .Chart.Name }} 1819 image: {{ .Values.image }} 1820 `, 1821 "charts/Chart.yaml": ` 1822 apiVersion: v1 1823 description: Skaffold example with Helm 1824 name: skaffold-helm 1825 version: 0.1.0 1826 `, 1827 "charts/values.yaml": ` 1828 replicaCount: 2 1829 image: skaffold-helm:latest 1830 `, 1831 }, expectedOut: `apiVersion: apps/v1 1832 kind: Deployment 1833 metadata: 1834 name: skaffold-helm 1835 namespace: helm-namespace 1836 labels: 1837 app: skaffold-helm 1838 spec: 1839 selector: 1840 matchLabels: 1841 app: skaffold-helm 1842 replicas: 5 1843 template: 1844 metadata: 1845 labels: 1846 app: skaffold-helm 1847 spec: 1848 containers: 1849 - name: skaffold-helm 1850 image: skaffold-helm:latest 1851 `}, 1852 { 1853 description: "test set param with helm #from-param, values are provided through file", 1854 args: []string{"--offline=true", "--set-value-file", "values.env"}, 1855 WithBuildArtifacts: true, 1856 config: ` 1857 apiVersion: skaffold/v4beta2 1858 kind: Config 1859 manifests: 1860 helm: 1861 releases: 1862 - name: skaffold-helm 1863 chartPath: charts 1864 namespace: helm-namespace 1865 `, 1866 input: map[string]string{ 1867 "charts/templates/deployments.yaml": ` 1868 apiVersion: apps/v1 1869 kind: Deployment 1870 metadata: 1871 name: {{ .Chart.Name }} 1872 namespace: {{ .Release.Namespace }} 1873 labels: 1874 app: {{ .Chart.Name }} 1875 spec: 1876 selector: 1877 matchLabels: 1878 app: {{ .Chart.Name }} 1879 replicas: {{ .Values.replicaCount }} # from-param: ${count} 1880 template: 1881 metadata: 1882 labels: 1883 app: {{ .Chart.Name }} 1884 spec: 1885 containers: 1886 - name: {{ .Chart.Name }} 1887 image: {{ .Values.image }} 1888 `, 1889 "charts/Chart.yaml": ` 1890 apiVersion: v1 1891 description: Skaffold example with Helm 1892 name: skaffold-helm 1893 version: 0.1.0 1894 `, 1895 "charts/values.yaml": ` 1896 replicaCount: 2 1897 image: skaffold-helm:latest 1898 `, 1899 "values.env": `count=3`, 1900 }, expectedOut: `apiVersion: apps/v1 1901 kind: Deployment 1902 metadata: 1903 name: skaffold-helm 1904 namespace: helm-namespace 1905 labels: 1906 app: skaffold-helm 1907 spec: 1908 selector: 1909 matchLabels: 1910 app: skaffold-helm 1911 replicas: 3 1912 template: 1913 metadata: 1914 labels: 1915 app: skaffold-helm 1916 spec: 1917 containers: 1918 - name: skaffold-helm 1919 image: skaffold-helm:latest 1920 `}, 1921 } 1922 1923 for _, test := range tests { 1924 testutil.Run(t, test.description, func(t *testutil.T) { 1925 MarkIntegrationTest(t.T, CanRunWithoutGcp) 1926 tmpDir := t.NewTempDir() 1927 tmpDir.Write("skaffold.yaml", test.config) 1928 1929 for filePath, content := range test.input { 1930 tmpDir.Write(filePath, content) 1931 } 1932 1933 if test.WithBuildArtifacts { 1934 dir, _ := os.Getwd() 1935 test.args = append(test.args, "--build-artifacts="+filepath.Join(dir, "testdata/render/build-output.json")) 1936 } 1937 1938 tmpDir.Chdir() 1939 output := skaffold.Render(test.args...).RunOrFailOutput(t.T) 1940 1941 t.CheckDeepEqual(test.expectedOut, string(output), testutil.YamlObj(t.T)) 1942 }) 1943 } 1944 } 1945 1946 func TestRenderWithTagFlag(t *testing.T) { 1947 MarkIntegrationTest(t, CanRunWithoutGcp) 1948 1949 tests := []struct { 1950 description string 1951 projectDir string 1952 expectedOutput string 1953 namespaceFlag string 1954 }{ 1955 { 1956 description: "tag flag in a single module project", 1957 projectDir: "testdata/getting-started", 1958 expectedOutput: `apiVersion: v1 1959 kind: Pod 1960 metadata: 1961 name: getting-started 1962 spec: 1963 containers: 1964 - image: gcr.io/k8s-skaffold/skaffold-example:customtag 1965 name: getting-started 1966 `, 1967 }, 1968 { 1969 description: "tag flag in a multi module project", 1970 projectDir: "testdata/multi-config-pods", 1971 expectedOutput: `apiVersion: v1 1972 kind: Pod 1973 metadata: 1974 name: module1 1975 spec: 1976 containers: 1977 - image: gcr.io/k8s-skaffold/multi-config-module1:customtag 1978 name: module1 1979 --- 1980 apiVersion: v1 1981 kind: Pod 1982 metadata: 1983 name: module2 1984 spec: 1985 containers: 1986 - image: gcr.io/k8s-skaffold/multi-config-module2:customtag 1987 name: module2 1988 `, 1989 }, 1990 { 1991 description: "tag flag, with namespace flag, in a single module project", 1992 projectDir: "testdata/getting-started", 1993 namespaceFlag: "mynamespace", 1994 expectedOutput: `apiVersion: v1 1995 kind: Pod 1996 metadata: 1997 name: getting-started 1998 namespace: mynamespace 1999 spec: 2000 containers: 2001 - image: gcr.io/k8s-skaffold/skaffold-example:customtag 2002 name: getting-started 2003 `, 2004 }, 2005 { 2006 description: "tag flag, with namespace flag, in a multi module project", 2007 projectDir: "testdata/multi-config-pods", 2008 namespaceFlag: "mynamespace", 2009 expectedOutput: `apiVersion: v1 2010 kind: Pod 2011 metadata: 2012 name: module1 2013 namespace: mynamespace 2014 spec: 2015 containers: 2016 - image: gcr.io/k8s-skaffold/multi-config-module1:customtag 2017 name: module1 2018 --- 2019 apiVersion: v1 2020 kind: Pod 2021 metadata: 2022 name: module2 2023 namespace: mynamespace 2024 spec: 2025 containers: 2026 - image: gcr.io/k8s-skaffold/multi-config-module2:customtag 2027 name: module2 2028 `, 2029 }, 2030 } 2031 2032 for _, test := range tests { 2033 testutil.Run(t, test.description, func(t *testutil.T) { 2034 args := []string{"--tag", "customtag", "--default-repo", "gcr.io/k8s-skaffold"} 2035 2036 if test.namespaceFlag != "" { 2037 args = append(args, "--namespace", test.namespaceFlag) 2038 } 2039 2040 output := skaffold.Render(args...).InDir(test.projectDir).RunOrFailOutput(t.T) 2041 t.CheckDeepEqual(string(output), test.expectedOutput, testutil.YamlObj(t.T)) 2042 }) 2043 } 2044 } 2045 2046 func TestRenderWithPostRenderHook(t *testing.T) { 2047 MarkIntegrationTest(t, CanRunWithoutGcp) 2048 2049 tests := []struct { 2050 description string 2051 projectDir string 2052 expectedOutput string 2053 expectedStderr string 2054 args []string 2055 }{ 2056 { 2057 description: "a single module project, one hook with change", 2058 projectDir: "testdata/post-render-hooks", 2059 args: []string{"-m", "m1", "-p", "change1", "-t", "customtag"}, 2060 expectedOutput: `apiVersion: v1 2061 kind: Pod 2062 metadata: 2063 name: module1 2064 labels: 2065 app1: after-change-1 2066 app2: before-change-2 2067 2068 spec: 2069 containers: 2070 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module1:customtag 2071 name: module1 2072 `, 2073 }, 2074 { 2075 description: "a single module project, two hook with change", 2076 projectDir: "testdata/post-render-hooks", 2077 args: []string{"-m", "m1", "-p", "two-changes", "-t", "customtag"}, 2078 expectedOutput: `apiVersion: v1 2079 kind: Pod 2080 metadata: 2081 name: module1 2082 labels: 2083 app1: after-change-1 2084 app2: after-change-2 2085 spec: 2086 containers: 2087 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module1:customtag 2088 name: module1 2089 `, 2090 }, 2091 { 2092 description: "a single module project, two hooks, one with change, one not", 2093 projectDir: "testdata/post-render-hooks", 2094 args: []string{"-m", "m1", "-p", "one-change-one-not", "-t", "customtag"}, 2095 expectedOutput: `apiVersion: v1 2096 kind: Pod 2097 metadata: 2098 name: module1 2099 labels: 2100 app1: before-change-1 2101 app2: after-change-2 2102 spec: 2103 containers: 2104 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module1:customtag 2105 name: module1 2106 `, 2107 }, 2108 { 2109 description: "multi-module project, two hooks, two changes", 2110 projectDir: "testdata/post-render-hooks", 2111 args: []string{"-m", "m1,m2", "-p", "change1", "-t", "customtag"}, 2112 expectedOutput: `apiVersion: v1 2113 kind: Pod 2114 metadata: 2115 labels: 2116 app1: after-change-1 2117 app2: before-change-2 2118 name: module1 2119 spec: 2120 containers: 2121 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module1:customtag 2122 name: module1 2123 --- 2124 apiVersion: v1 2125 kind: Pod 2126 metadata: 2127 labels: 2128 app1: before-change-1 2129 name: module2 2130 spec: 2131 containers: 2132 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module2:customtag 2133 name: module2 2134 `, 2135 }, 2136 { 2137 description: "multi-module project, one pipeline with two hooks have changes, one pipeline has no changes", 2138 projectDir: "testdata/post-render-hooks", 2139 args: []string{"-m", "m1,m2", "-p", "change1,nochange2", "-t", "customtag"}, 2140 expectedOutput: `apiVersion: v1 2141 kind: Pod 2142 metadata: 2143 labels: 2144 app1: after-change-1 2145 app2: before-change-2 2146 name: module1 2147 spec: 2148 containers: 2149 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module1:customtag 2150 name: module1 2151 --- 2152 apiVersion: v1 2153 kind: Pod 2154 metadata: 2155 labels: 2156 app1: before-change-1 2157 name: module2 2158 spec: 2159 containers: 2160 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module2:customtag 2161 name: module2 2162 `, 2163 }, 2164 { 2165 description: "single module project, one hook with changes, other without changes and with output", 2166 projectDir: "testdata/post-render-hooks", 2167 args: []string{"-m", "m1", "-p", "one-change-two-without-change-but-with-output", "-t", "customtag"}, 2168 expectedOutput: `apiVersion: v1 2169 kind: Pod 2170 metadata: 2171 labels: 2172 app1: before-change-1 2173 app2: after-change-2 2174 name: module1 2175 spec: 2176 containers: 2177 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/multi-config-module1:customtag 2178 name: module1 2179 `, 2180 expectedStderr: `Starting post-render hooks... 2181 running post-render hook 1 2182 running post-render hook 2 2183 Completed post-render hooks`, 2184 }, 2185 } 2186 2187 for _, test := range tests { 2188 testutil.Run(t, test.description, func(t *testutil.T) { 2189 stdout := new(bytes.Buffer) 2190 stderr := new(bytes.Buffer) 2191 skaffold.Render(test.args...).InDir(test.projectDir).RunWithStdoutAndStderrOrFail(t.T, stdout, stderr) 2192 t.CheckDeepEqual(test.expectedOutput, stdout.String(), testutil.YamlObj(t.T)) 2193 if test.expectedStderr != "" { 2194 t.CheckMatches(test.expectedStderr, stderr.String()) 2195 } 2196 }) 2197 } 2198 } 2199 2200 func TestKptRender(t *testing.T) { 2201 tests := []struct { 2202 description string 2203 args []string 2204 config string 2205 input map[string]string // file path => content 2206 expectedOut string 2207 }{ 2208 { 2209 description: "simple kpt render", 2210 config: `apiVersion: skaffold/v4beta2 2211 kind: Config 2212 metadata: 2213 name: getting-started-kustomize 2214 manifests: 2215 kpt: 2216 - apply-simple 2217 `, input: map[string]string{"apply-simple/Kptfile": `apiVersion: kpt.dev/v1 2218 kind: Kptfile 2219 metadata: 2220 name: apply-setters-simple 2221 upstream: 2222 type: git 2223 git: 2224 repo: https://github.com/GoogleContainerTools/kpt-functions-catalog 2225 directory: /examples/apply-setters-simple 2226 ref: apply-setters/v0.2.0 2227 updateStrategy: resource-merge 2228 upstreamLock: 2229 type: git 2230 git: 2231 repo: https://github.com/GoogleContainerTools/kpt-functions-catalog 2232 directory: /examples/apply-setters-simple 2233 ref: apply-setters/v0.2.0 2234 commit: 9b6ce80e355a53727d21b2b336f8da55e760e20ca 2235 pipeline: 2236 mutators: 2237 - image: gcr.io/kpt-fn/apply-setters:v0.2 2238 configMap: 2239 nginx-replicas: 3 2240 tag: 1.16.2 2241 `, "apply-simple/resources.yaml": `apiVersion: apps/v1 2242 kind: Deployment 2243 metadata: 2244 name: my-nginx 2245 spec: 2246 replicas: 4 # kpt-set: ${nginx-replicas} 2247 selector: 2248 matchLabels: 2249 app: nginx 2250 template: 2251 metadata: 2252 labels: 2253 app: nginx 2254 spec: 2255 containers: 2256 - name: nginx 2257 image: "nginx:1.16.1" # kpt-set: nginx:${tag} 2258 ports: 2259 - protocol: TCP 2260 containerPort: 80`}, 2261 expectedOut: `apiVersion: apps/v1 2262 kind: Deployment 2263 metadata: 2264 name: my-nginx 2265 spec: 2266 replicas: 3 2267 selector: 2268 matchLabels: 2269 app: nginx 2270 template: 2271 metadata: 2272 labels: 2273 app: nginx 2274 spec: 2275 containers: 2276 - name: nginx 2277 image: "nginx:1.16.2" 2278 ports: 2279 - protocol: TCP 2280 containerPort: 80 2281 `}, 2282 { 2283 description: "kpt render with data config file", 2284 config: `apiVersion: skaffold/v4beta2 2285 kind: Config 2286 metadata: 2287 name: getting-started-kustomize 2288 manifests: 2289 kpt: 2290 - set-annotations 2291 `, 2292 input: map[string]string{"set-annotations/Kptfile": `apiVersion: kpt.dev/v1 2293 kind: Kptfile 2294 metadata: 2295 name: example 2296 pipeline: 2297 mutators: 2298 - image: gcr.io/kpt-fn/set-annotations:v0.1.4 2299 configPath: fn-config.yaml`, 2300 "set-annotations/fn-config.yaml": `apiVersion: fn.kpt.dev/v1alpha1 2301 kind: SetAnnotations 2302 metadata: # kpt-merge: /my-func-config 2303 name: my-func-config 2304 annotations: 2305 config.kubernetes.io/local-config: "true" 2306 internal.kpt.dev/upstream-identifier: 'fn.kpt.dev|SetAnnotations|default|my-func-config' 2307 annotations: 2308 color: orange 2309 fruit: apple 2310 `, 2311 "set-annotations/resources.yaml": `apiVersion: apps/v1 2312 kind: Deployment 2313 metadata: 2314 name: my-nginx 2315 spec: 2316 replicas: 3 # kpt-set: ${nginx-replicas} 2317 selector: 2318 matchLabels: 2319 app: nginx 2320 template: 2321 metadata: 2322 labels: 2323 app: nginx 2324 spec: 2325 containers: 2326 - name: nginx 2327 image: "nginx:1.16.1" # kpt-set: nginx:${tag} 2328 ports: 2329 - protocol: TCP 2330 containerPort: 80`}, 2331 expectedOut: `apiVersion: apps/v1 2332 kind: Deployment 2333 metadata: 2334 name: my-nginx 2335 annotations: 2336 color: orange 2337 fruit: apple 2338 spec: 2339 replicas: 3 2340 selector: 2341 matchLabels: 2342 app: nginx 2343 template: 2344 metadata: 2345 annotations: 2346 color: orange 2347 fruit: apple 2348 labels: 2349 app: nginx 2350 spec: 2351 containers: 2352 - name: nginx 2353 image: "nginx:1.16.1" 2354 ports: 2355 - protocol: TCP 2356 containerPort: 80 2357 `}, 2358 { 2359 description: "simple kpt render with namespace flag", 2360 args: []string{"--namespace", "mynamespace"}, 2361 config: `apiVersion: skaffold/v4beta2 2362 kind: Config 2363 metadata: 2364 name: getting-started-kustomize 2365 manifests: 2366 kpt: 2367 - apply-simple 2368 `, 2369 input: map[string]string{"apply-simple/Kptfile": `apiVersion: kpt.dev/v1 2370 kind: Kptfile 2371 metadata: 2372 name: apply-setters-simple 2373 upstream: 2374 type: git 2375 git: 2376 repo: https://github.com/GoogleContainerTools/kpt-functions-catalog 2377 directory: /examples/apply-setters-simple 2378 ref: apply-setters/v0.2.0 2379 updateStrategy: resource-merge 2380 upstreamLock: 2381 type: git 2382 git: 2383 repo: https://github.com/GoogleContainerTools/kpt-functions-catalog 2384 directory: /examples/apply-setters-simple 2385 ref: apply-setters/v0.2.0 2386 commit: 9b6ce80e355a53727d21b2b336f8da55e760e20ca 2387 pipeline: 2388 mutators: 2389 - image: gcr.io/kpt-fn/apply-setters:v0.2 2390 configMap: 2391 nginx-replicas: 3 2392 tag: 1.16.2 2393 `, 2394 "apply-simple/resources.yaml": `apiVersion: apps/v1 2395 kind: Deployment 2396 metadata: 2397 name: my-nginx 2398 spec: 2399 replicas: 4 # kpt-set: ${nginx-replicas} 2400 selector: 2401 matchLabels: 2402 app: nginx 2403 template: 2404 metadata: 2405 labels: 2406 app: nginx 2407 spec: 2408 containers: 2409 - name: nginx 2410 image: "nginx:1.16.1" # kpt-set: nginx:${tag} 2411 ports: 2412 - protocol: TCP 2413 containerPort: 80 2414 `}, 2415 expectedOut: `apiVersion: apps/v1 2416 kind: Deployment 2417 metadata: 2418 name: my-nginx 2419 namespace: mynamespace 2420 spec: 2421 replicas: 3 2422 selector: 2423 matchLabels: 2424 app: nginx 2425 template: 2426 metadata: 2427 labels: 2428 app: nginx 2429 spec: 2430 containers: 2431 - name: nginx 2432 image: "nginx:1.16.2" 2433 ports: 2434 - protocol: TCP 2435 containerPort: 80 2436 `}, 2437 } 2438 2439 for _, test := range tests { 2440 testutil.Run(t, test.description, func(t *testutil.T) { 2441 MarkIntegrationTest(t.T, CanRunWithoutGcp) 2442 tmpDir := t.NewTempDir() 2443 tmpDir.Write("skaffold.yaml", test.config) 2444 2445 for filePath, content := range test.input { 2446 tmpDir.Write(filePath, content) 2447 } 2448 2449 tmpDir.Chdir() 2450 output := skaffold.Render(test.args...).RunOrFailOutput(t.T) 2451 var out map[string]any 2452 var ex map[string]any 2453 err := yaml.Unmarshal(output, &out) 2454 if err != nil { 2455 return 2456 } 2457 err = yaml.Unmarshal([]byte(test.expectedOut), &ex) 2458 if err != nil { 2459 return 2460 } 2461 2462 t.CheckDeepEqual(ex, out) 2463 }) 2464 } 2465 } 2466 2467 func TestHelmRenderWithImagesFlag(t *testing.T) { 2468 tests := []struct { 2469 description string 2470 dir string 2471 args []string 2472 builds []graph.Artifact 2473 helmReleases []latest.HelmRelease 2474 expectedOut string 2475 }{ 2476 { 2477 description: "verify --images flag work with helm render", 2478 dir: "testdata/helm-render", 2479 args: []string{"--profile=helm-render", "--images=us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold-helm:latest@sha256:3e8981b13fadcbb5f4d42d00fdf52a9de128feea5280f0a1f7fb542cf31f1a06"}, 2480 expectedOut: `apiVersion: v1 2481 kind: Service 2482 metadata: 2483 labels: 2484 app: skaffold-helm 2485 chart: skaffold-helm-0.1.0 2486 heritage: Helm 2487 release: skaffold-helm 2488 skaffold.dev/run-id: phony-run-id 2489 name: skaffold-helm-skaffold-helm 2490 spec: 2491 ports: 2492 - name: nginx 2493 port: 80 2494 protocol: TCP 2495 targetPort: 80 2496 selector: 2497 app: skaffold-helm 2498 release: skaffold-helm 2499 type: ClusterIP 2500 --- 2501 apiVersion: apps/v1 2502 kind: Deployment 2503 metadata: 2504 labels: 2505 app: skaffold-helm 2506 chart: skaffold-helm-0.1.0 2507 heritage: Helm 2508 release: skaffold-helm 2509 skaffold.dev/run-id: phony-run-id 2510 name: skaffold-helm 2511 spec: 2512 replicas: 1 2513 selector: 2514 matchLabels: 2515 app: skaffold-helm 2516 release: skaffold-helm 2517 template: 2518 metadata: 2519 labels: 2520 app: skaffold-helm 2521 release: skaffold-helm 2522 skaffold.dev/run-id: phony-run-id 2523 spec: 2524 containers: 2525 - image: us-central1-docker.pkg.dev/k8s-skaffold/testing/skaffold-helm:latest@sha256:3e8981b13fadcbb5f4d42d00fdf52a9de128feea5280f0a1f7fb542cf31f1a06 2526 imagePullPolicy: always 2527 name: skaffold-helm 2528 ports: 2529 - containerPort: 80 2530 resources: {} 2531 --- 2532 apiVersion: networking.k8s.io/v1 2533 kind: Ingress 2534 metadata: 2535 annotations: null 2536 labels: 2537 app: skaffold-helm 2538 chart: skaffold-helm-0.1.0 2539 heritage: Helm 2540 release: skaffold-helm 2541 name: skaffold-helm-skaffold-helm 2542 spec: 2543 rules: 2544 - http: 2545 paths: 2546 - backend: 2547 service: 2548 name: skaffold-helm-skaffold-helm 2549 port: 2550 number: 80 2551 path: / 2552 pathType: ImplementationSpecific 2553 `, 2554 }, 2555 } 2556 for _, test := range tests { 2557 t.Run(test.description, func(t *testing.T) { 2558 MarkIntegrationTest(t, CanRunWithoutGcp) 2559 out := skaffold.Render(append([]string{"--default-repo=", "--label=skaffold.dev/run-id=phony-run-id"}, test.args...)...).InDir(test.dir).RunOrFailOutput(t) 2560 2561 testutil.CheckDeepEqual(t, test.expectedOut, string(out), testutil.YamlObj(t)) 2562 }) 2563 } 2564 } 2565 2566 func TestRenderRemoteKustomize(t *testing.T) { 2567 testutil.Run(t, "render remote kustomize resource success", func(t *testutil.T) { 2568 MarkIntegrationTest(t.T, CanRunWithoutGcp) 2569 skaffold.Render().InDir("testdata/kustomize/remote").RunOrFail(t.T) 2570 }) 2571 }