github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/play_kube_test.go (about) 1 package integration 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io/ioutil" 8 "net" 9 "net/url" 10 "os" 11 "os/user" 12 "path/filepath" 13 "strconv" 14 "strings" 15 "text/template" 16 "time" 17 18 "github.com/hanks177/podman/v4/libpod/define" 19 "github.com/hanks177/podman/v4/pkg/bindings" 20 "github.com/hanks177/podman/v4/pkg/bindings/play" 21 "github.com/hanks177/podman/v4/pkg/util" 22 . "github.com/hanks177/podman/v4/test/utils" 23 "github.com/containers/storage/pkg/stringid" 24 "github.com/google/uuid" 25 . "github.com/onsi/ginkgo" 26 . "github.com/onsi/gomega" 27 "github.com/onsi/gomega/format" 28 . "github.com/onsi/gomega/gexec" 29 "github.com/opencontainers/selinux/go-selinux" 30 ) 31 32 var unknownKindYaml = ` 33 apiVersion: v1 34 kind: UnknownKind 35 metadata: 36 labels: 37 app: app1 38 name: unknown 39 spec: 40 hostname: unknown 41 ` 42 43 var workdirSymlinkPodYaml = ` 44 apiVersion: v1 45 kind: Pod 46 metadata: 47 labels: 48 app: test-symlink 49 name: test-symlink 50 spec: 51 containers: 52 - image: test-symlink 53 name: test-symlink 54 resources: {} 55 restartPolicy: Never 56 ` 57 58 var podnameEqualsContainerNameYaml = ` 59 apiVersion: v1 60 kind: Pod 61 metadata: 62 name: podnameEqualsContainerNameYaml 63 spec: 64 containers: 65 - name: podnameEqualsContainerNameYaml 66 image: quay.io/libpod/alpine:latest 67 ports: 68 - containerPort: 80 69 ` 70 71 var podWithoutAName = ` 72 apiVersion: v1 73 kind: Pod 74 spec: 75 containers: 76 - name: podDoesntHaveAName 77 image: quay.io/libpod/alpine:latest 78 ports: 79 - containerPort: 80 80 ` 81 82 var checkInfraImagePodYaml = ` 83 apiVersion: v1 84 kind: Pod 85 metadata: 86 labels: 87 app: check-infra-image 88 name: check-infra-image 89 spec: 90 containers: 91 - name: alpine 92 image: quay.io/libpod/alpine:latest 93 command: 94 - sleep 95 - 24h 96 status: {} 97 ` 98 99 var podWithoutConfigMapDefined = ` 100 apiVersion: v1 101 kind: Pod 102 metadata: 103 name: testpod1 104 spec: 105 containers: 106 - name: alpine 107 image: quay.io/libpod/alpine:latest 108 volumeMounts: 109 - name: mycm 110 mountPath: /mycm 111 volumes: 112 - name: mycm 113 configMap: 114 name: mycm 115 ` 116 117 var sharedNamespacePodYaml = ` 118 apiVersion: v1 119 kind: Pod 120 metadata: 121 creationTimestamp: "2021-05-07T17:25:01Z" 122 labels: 123 app: testpod1 124 name: testpod1 125 spec: 126 containers: 127 - command: 128 - top 129 - -d 130 - "1.5" 131 env: 132 - name: HOSTNAME 133 value: label-pod 134 image: quay.io/libpod/alpine:latest 135 name: alpine 136 resources: {} 137 securityContext: 138 allowPrivilegeEscalation: true 139 capabilities: {} 140 privileged: false 141 readOnlyRootFilesystem: false 142 seLinuxOptions: {} 143 workingDir: / 144 dnsConfig: {} 145 restartPolicy: Never 146 shareProcessNamespace: true 147 status: {} 148 ` 149 var livenessProbePodYaml = ` 150 apiVersion: apps/v1 151 kind: Deployment 152 metadata: 153 name: liveness-probe 154 labels: 155 app: alpine 156 spec: 157 replicas: 1 158 selector: 159 matchLabels: 160 app: alpine 161 template: 162 metadata: 163 labels: 164 app: alpine 165 spec: 166 containers: 167 - command: 168 - top 169 - -d 170 - "1.5" 171 name: alpine 172 image: quay.io/libpod/alpine:latest 173 ports: 174 - containerPort: 80 175 livenessProbe: 176 exec: 177 command: 178 - echo 179 - hello 180 initialDelaySeconds: 5 181 periodSeconds: 5 182 ` 183 var livenessProbeUnhealthyPodYaml = ` 184 apiVersion: apps/v1 185 kind: Deployment 186 metadata: 187 name: liveness-unhealthy-probe 188 labels: 189 app: alpine 190 spec: 191 replicas: 1 192 selector: 193 matchLabels: 194 app: alpine 195 template: 196 metadata: 197 labels: 198 app: alpine 199 spec: 200 restartPolicy: Never 201 containers: 202 - command: 203 - top 204 - -d 205 - "1.5" 206 name: alpine 207 image: quay.io/libpod/alpine:latest 208 ports: 209 - containerPort: 80 210 livenessProbe: 211 exec: 212 command: 213 - cat 214 - /randomfile 215 initialDelaySeconds: 0 216 periodSeconds: 1 217 ` 218 219 var selinuxLabelPodYaml = ` 220 apiVersion: v1 221 kind: Pod 222 metadata: 223 creationTimestamp: "2021-02-02T22:18:20Z" 224 labels: 225 app: label-pod 226 name: label-pod 227 spec: 228 containers: 229 - command: 230 - top 231 - -d 232 - "1.5" 233 env: 234 - name: HOSTNAME 235 value: label-pod 236 image: quay.io/libpod/alpine:latest 237 name: test 238 securityContext: 239 allowPrivilegeEscalation: true 240 capabilities: 241 drop: 242 - CAP_MKNOD 243 - CAP_NET_RAW 244 - CAP_AUDIT_WRITE 245 privileged: false 246 readOnlyRootFilesystem: false 247 seLinuxOptions: 248 user: unconfined_u 249 role: system_r 250 type: spc_t 251 level: s0 252 workingDir: / 253 status: {} 254 ` 255 256 var configMapYamlTemplate = ` 257 apiVersion: v1 258 kind: ConfigMap 259 metadata: 260 name: {{ .Name }} 261 data: 262 {{ with .Data }} 263 {{ range $key, $value := . }} 264 {{ $key }}: {{ $value }} 265 {{ end }} 266 {{ end }} 267 ` 268 269 var persistentVolumeClaimYamlTemplate = ` 270 apiVersion: v1 271 kind: PersistentVolumeClaim 272 metadata: 273 name: {{ .Name }} 274 {{ with .Annotations }} 275 annotations: 276 {{ range $key, $value := . }} 277 {{ $key }}: {{ $value }} 278 {{ end }} 279 {{ end }} 280 spec: 281 accessModes: 282 - "ReadWriteOnce" 283 resources: 284 requests: 285 storage: "1Gi" 286 storageClassName: default 287 ` 288 289 var podYamlTemplate = ` 290 apiVersion: v1 291 kind: Pod 292 metadata: 293 creationTimestamp: "2019-07-17T14:44:08Z" 294 name: {{ .Name }} 295 labels: 296 app: {{ .Name }} 297 {{ with .Labels }} 298 {{ range $key, $value := . }} 299 {{ $key }}: {{ $value }} 300 {{ end }} 301 {{ end }} 302 {{ with .Annotations }} 303 annotations: 304 {{ range $key, $value := . }} 305 {{ $key }}: {{ $value }} 306 {{ end }} 307 {{ end }} 308 309 spec: 310 restartPolicy: {{ .RestartPolicy }} 311 hostname: {{ .Hostname }} 312 hostNetwork: {{ .HostNetwork }} 313 hostAliases: 314 {{ range .HostAliases }} 315 - hostnames: 316 {{ range .HostName }} 317 - {{ . }} 318 {{ end }} 319 ip: {{ .IP }} 320 {{ end }} 321 initContainers: 322 {{ with .InitCtrs }} 323 {{ range . }} 324 - command: 325 {{ range .Cmd }} 326 - {{.}} 327 {{ end }} 328 image: {{ .Image }} 329 name: {{ .Name }} 330 {{ end }} 331 {{ end }} 332 {{ if .SecurityContext }} 333 securityContext: 334 {{ if .RunAsUser }}runAsUser: {{ .RunAsUser }}{{- end }} 335 {{ if .RunAsGroup }}runAsGroup: {{ .RunAsGroup }}{{- end }} 336 {{ end }} 337 containers: 338 {{ with .Ctrs }} 339 {{ range . }} 340 - command: 341 {{ range .Cmd }} 342 - {{.}} 343 {{ end }} 344 args: 345 {{ range .Arg }} 346 - {{.}} 347 {{ end }} 348 env: 349 - name: HOSTNAME 350 {{ range .Env }} 351 - name: {{ .Name }} 352 {{ if (eq .ValueFrom "configmap") }} 353 valueFrom: 354 configMapKeyRef: 355 name: {{ .RefName }} 356 key: {{ .RefKey }} 357 optional: {{ .Optional }} 358 {{ end }} 359 {{ if (eq .ValueFrom "secret") }} 360 valueFrom: 361 secretKeyRef: 362 name: {{ .RefName }} 363 key: {{ .RefKey }} 364 optional: {{ .Optional }} 365 {{ end }} 366 {{ if (eq .ValueFrom "") }} 367 value: {{ .Value }} 368 {{ end }} 369 {{ end }} 370 {{ with .EnvFrom}} 371 envFrom: 372 {{ range . }} 373 {{ if (eq .From "configmap") }} 374 - configMapRef: 375 name: {{ .Name }} 376 optional: {{ .Optional }} 377 {{ end }} 378 {{ if (eq .From "secret") }} 379 - secretRef: 380 name: {{ .Name }} 381 optional: {{ .Optional }} 382 {{ end }} 383 {{ end }} 384 {{ end }} 385 image: {{ .Image }} 386 name: {{ .Name }} 387 imagePullPolicy: {{ .PullPolicy }} 388 {{- if or .CPURequest .CPULimit .MemoryRequest .MemoryLimit }} 389 resources: 390 {{- if or .CPURequest .MemoryRequest }} 391 requests: 392 {{if .CPURequest }}cpu: {{ .CPURequest }}{{ end }} 393 {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} 394 {{- end }} 395 {{- if or .CPULimit .MemoryLimit }} 396 limits: 397 {{if .CPULimit }}cpu: {{ .CPULimit }}{{ end }} 398 {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} 399 {{- end }} 400 {{- end }} 401 {{ if .SecurityContext }} 402 securityContext: 403 {{ if .RunAsUser }}runAsUser: {{ .RunAsUser }}{{- end }} 404 {{ if .RunAsGroup }}runAsGroup: {{ .RunAsGroup }}{{- end }} 405 allowPrivilegeEscalation: true 406 {{ if .Caps }} 407 capabilities: 408 {{ with .CapAdd }} 409 add: 410 {{ range . }} 411 - {{.}} 412 {{ end }} 413 {{ end }} 414 {{ with .CapDrop }} 415 drop: 416 {{ range . }} 417 - {{.}} 418 {{ end }} 419 {{ end }} 420 {{ end }} 421 privileged: false 422 readOnlyRootFilesystem: false 423 ports: 424 - containerPort: {{ .Port }} 425 hostIP: {{ .HostIP }} 426 hostPort: {{ .Port }} 427 protocol: TCP 428 workingDir: / 429 volumeMounts: 430 {{ if .VolumeMount }} 431 - name: {{.VolumeName}} 432 mountPath: {{ .VolumeMountPath }} 433 readonly: {{.VolumeReadOnly}} 434 {{ end }} 435 {{ end }} 436 {{ end }} 437 {{ end }} 438 {{ with .Volumes }} 439 volumes: 440 {{ range . }} 441 - name: {{ .Name }} 442 {{- if (eq .VolumeType "HostPath") }} 443 hostPath: 444 path: {{ .HostPath.Path }} 445 type: {{ .HostPath.Type }} 446 {{- end }} 447 {{- if (eq .VolumeType "PersistentVolumeClaim") }} 448 persistentVolumeClaim: 449 claimName: {{ .PersistentVolumeClaim.ClaimName }} 450 {{- end }} 451 {{- if (eq .VolumeType "ConfigMap") }} 452 configMap: 453 name: {{ .ConfigMap.Name }} 454 optional: {{ .ConfigMap.Optional }} 455 {{- with .ConfigMap.Items }} 456 items: 457 {{- range . }} 458 - key: {{ .key }} 459 path: {{ .path }} 460 {{- end }} 461 {{- end }} 462 {{- end }} 463 {{ end }} 464 {{ end }} 465 status: {} 466 ` 467 468 var deploymentYamlTemplate = ` 469 apiVersion: v1 470 kind: Deployment 471 metadata: 472 creationTimestamp: "2019-07-17T14:44:08Z" 473 name: {{ .Name }} 474 labels: 475 app: {{ .Name }} 476 {{ with .Labels }} 477 {{ range $key, $value := . }} 478 {{ $key }}: {{ $value }} 479 {{ end }} 480 {{ end }} 481 {{ with .Annotations }} 482 annotations: 483 {{ range $key, $value := . }} 484 {{ $key }}: {{ $value }} 485 {{ end }} 486 {{ end }} 487 488 spec: 489 replicas: {{ .Replicas }} 490 selector: 491 matchLabels: 492 app: {{ .Name }} 493 template: 494 {{ with .PodTemplate }} 495 metadata: 496 labels: 497 app: {{ .Name }} 498 {{- with .Labels }}{{ range $key, $value := . }} 499 {{ $key }}: {{ $value }} 500 {{- end }}{{ end }} 501 {{- with .Annotations }} 502 annotations: 503 {{- range $key, $value := . }} 504 {{ $key }}: {{ $value }} 505 {{- end }} 506 {{- end }} 507 spec: 508 restartPolicy: {{ .RestartPolicy }} 509 hostname: {{ .Hostname }} 510 hostNetwork: {{ .HostNetwork }} 511 containers: 512 {{ with .Ctrs }} 513 {{ range . }} 514 - command: 515 {{ range .Cmd }} 516 - {{.}} 517 {{ end }} 518 args: 519 {{ range .Arg }} 520 - {{.}} 521 {{ end }} 522 env: 523 - name: HOSTNAME 524 {{ range .Env }} 525 - name: {{ .Name }} 526 {{ if (eq .ValueFrom "configmap") }} 527 valueFrom: 528 configMapKeyRef: 529 name: {{ .RefName }} 530 key: {{ .RefKey }} 531 optional: {{ .Optional }} 532 {{ end }} 533 {{ if (eq .ValueFrom "secret") }} 534 valueFrom: 535 secretKeyRef: 536 name: {{ .RefName }} 537 key: {{ .RefKey }} 538 optional: {{ .Optional }} 539 {{ end }} 540 {{ if (eq .ValueFrom "") }} 541 value: {{ .Value }} 542 {{ end }} 543 {{ end }} 544 {{ with .EnvFrom}} 545 envFrom: 546 {{ range . }} 547 {{ if (eq .From "configmap") }} 548 - configMapRef: 549 name: {{ .Name }} 550 optional: {{ .Optional }} 551 {{ end }} 552 {{ if (eq .From "secret") }} 553 - secretRef: 554 name: {{ .Name }} 555 optional: {{ .Optional }} 556 {{ end }} 557 {{ end }} 558 {{ end }} 559 image: {{ .Image }} 560 name: {{ .Name }} 561 imagePullPolicy: {{ .PullPolicy }} 562 {{- if or .CPURequest .CPULimit .MemoryRequest .MemoryLimit }} 563 resources: 564 {{- if or .CPURequest .MemoryRequest }} 565 requests: 566 {{if .CPURequest }}cpu: {{ .CPURequest }}{{ end }} 567 {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} 568 {{- end }} 569 {{- if or .CPULimit .MemoryLimit }} 570 limits: 571 {{if .CPULimit }}cpu: {{ .CPULimit }}{{ end }} 572 {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} 573 {{- end }} 574 {{- end }} 575 {{ if .SecurityContext }} 576 securityContext: 577 allowPrivilegeEscalation: true 578 {{ if .Caps }} 579 capabilities: 580 {{ with .CapAdd }} 581 add: 582 {{ range . }} 583 - {{.}} 584 {{ end }} 585 {{ end }} 586 {{ with .CapDrop }} 587 drop: 588 {{ range . }} 589 - {{.}} 590 {{ end }} 591 {{ end }} 592 {{ end }} 593 privileged: false 594 readOnlyRootFilesystem: false 595 workingDir: / 596 volumeMounts: 597 {{ if .VolumeMount }} 598 - name: {{.VolumeName}} 599 mountPath: {{ .VolumeMountPath }} 600 readonly: {{.VolumeReadOnly}} 601 {{ end }} 602 {{ end }} 603 {{ end }} 604 {{ end }} 605 {{ with .Volumes }} 606 volumes: 607 {{ range . }} 608 - name: {{ .Name }} 609 {{- if (eq .VolumeType "HostPath") }} 610 hostPath: 611 path: {{ .HostPath.Path }} 612 type: {{ .HostPath.Type }} 613 {{- end }} 614 {{- if (eq .VolumeType "PersistentVolumeClaim") }} 615 persistentVolumeClaim: 616 claimName: {{ .PersistentVolumeClaim.ClaimName }} 617 {{- end }} 618 {{ end }} 619 {{ end }} 620 {{ end }} 621 ` 622 623 var ( 624 defaultCtrName = "testCtr" 625 defaultCtrCmd = []string{"top"} 626 defaultCtrArg = []string{"-d", "1.5"} 627 defaultCtrImage = ALPINE 628 defaultPodName = "testPod" 629 defaultVolName = "testVol" 630 defaultDeploymentName = "testDeployment" 631 defaultConfigMapName = "testConfigMap" 632 defaultPVCName = "testPVC" 633 seccompPwdEPERM = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`) 634 // CPU Period in ms 635 defaultCPUPeriod = 100 636 // Default secret in JSON. Note that the values ("foo" and "bar") are base64 encoded. 637 defaultSecret = []byte(`{"FOO":"Zm9v","BAR":"YmFy"}`) 638 ) 639 640 // getKubeYaml returns a kubernetes YAML document. 641 func getKubeYaml(kind string, object interface{}) (string, error) { 642 var yamlTemplate string 643 templateBytes := &bytes.Buffer{} 644 645 switch kind { 646 case "configmap": 647 yamlTemplate = configMapYamlTemplate 648 case "pod": 649 yamlTemplate = podYamlTemplate 650 case "deployment": 651 yamlTemplate = deploymentYamlTemplate 652 case "persistentVolumeClaim": 653 yamlTemplate = persistentVolumeClaimYamlTemplate 654 default: 655 return "", fmt.Errorf("unsupported kubernetes kind") 656 } 657 658 t, err := template.New(kind).Parse(yamlTemplate) 659 if err != nil { 660 return "", err 661 } 662 663 if err := t.Execute(templateBytes, object); err != nil { 664 return "", err 665 } 666 667 return templateBytes.String(), nil 668 } 669 670 // generateKubeYaml writes a kubernetes YAML document. 671 func generateKubeYaml(kind string, object interface{}, pathname string) error { 672 k, err := getKubeYaml(kind, object) 673 if err != nil { 674 return err 675 } 676 677 return writeYaml(k, pathname) 678 } 679 680 // generateMultiDocKubeYaml writes multiple kube objects in one Yaml document. 681 func generateMultiDocKubeYaml(kubeObjects []string, pathname string) error { 682 var multiKube string 683 684 for _, k := range kubeObjects { 685 multiKube += "---\n" 686 multiKube += k 687 } 688 689 return writeYaml(multiKube, pathname) 690 } 691 692 func createSecret(podmanTest *PodmanTestIntegration, name string, value []byte) { //nolint:unparam 693 secretFilePath := filepath.Join(podmanTest.TempDir, "secret") 694 err := ioutil.WriteFile(secretFilePath, value, 0755) 695 Expect(err).To(BeNil()) 696 697 secret := podmanTest.Podman([]string{"secret", "create", name, secretFilePath}) 698 secret.WaitWithDefaultTimeout() 699 Expect(secret).Should(Exit(0)) 700 } 701 702 // CM describes the options a kube yaml can be configured at configmap level 703 type CM struct { 704 Name string 705 Data map[string]string 706 } 707 708 func getConfigMap(options ...configMapOption) *CM { 709 cm := CM{ 710 Name: defaultConfigMapName, 711 Data: map[string]string{}, 712 } 713 714 for _, option := range options { 715 option(&cm) 716 } 717 718 return &cm 719 } 720 721 type configMapOption func(*CM) 722 723 func withConfigMapName(name string) configMapOption { 724 return func(configmap *CM) { 725 configmap.Name = name 726 } 727 } 728 729 func withConfigMapData(k, v string) configMapOption { 730 return func(configmap *CM) { 731 configmap.Data[k] = v 732 } 733 } 734 735 // PVC describes the options a kube yaml can be configured at persistent volume claim level 736 type PVC struct { 737 Name string 738 Annotations map[string]string 739 } 740 741 func getPVC(options ...pvcOption) *PVC { 742 pvc := PVC{ 743 Name: defaultPVCName, 744 Annotations: map[string]string{}, 745 } 746 747 for _, option := range options { 748 option(&pvc) 749 } 750 751 return &pvc 752 } 753 754 type pvcOption func(*PVC) 755 756 func withPVCName(name string) pvcOption { 757 return func(pvc *PVC) { 758 pvc.Name = name 759 } 760 } 761 762 func withPVCAnnotations(k, v string) pvcOption { 763 return func(pvc *PVC) { 764 pvc.Annotations[k] = v 765 } 766 } 767 768 // Pod describes the options a kube yaml can be configured at pod level 769 type Pod struct { 770 Name string 771 RestartPolicy string 772 Hostname string 773 HostNetwork bool 774 HostAliases []HostAlias 775 Ctrs []*Ctr 776 InitCtrs []*Ctr 777 Volumes []*Volume 778 Labels map[string]string 779 Annotations map[string]string 780 SecurityContext bool 781 RunAsUser string 782 RunAsGroup string 783 } 784 785 type HostAlias struct { 786 IP string 787 HostName []string 788 } 789 790 // getPod takes a list of podOptions and returns a pod with sane defaults 791 // and the configured options 792 // if no containers are added, it will add the default container 793 func getPod(options ...podOption) *Pod { 794 p := Pod{ 795 Name: defaultPodName, 796 RestartPolicy: "Never", 797 Hostname: "", 798 HostNetwork: false, 799 HostAliases: nil, 800 Ctrs: make([]*Ctr, 0), 801 InitCtrs: make([]*Ctr, 0), 802 Volumes: make([]*Volume, 0), 803 Labels: make(map[string]string), 804 Annotations: make(map[string]string), 805 } 806 for _, option := range options { 807 option(&p) 808 } 809 if len(p.Ctrs) == 0 { 810 p.Ctrs = []*Ctr{getCtr()} 811 } 812 return &p 813 } 814 815 type podOption func(*Pod) 816 817 func withPodSecurityContext(sc bool) podOption { 818 return func(p *Pod) { 819 p.SecurityContext = sc 820 } 821 } 822 823 func withPodRunAsUser(runAsUser string) podOption { 824 return func(p *Pod) { 825 p.RunAsUser = runAsUser 826 } 827 } 828 829 func withPodRunAsGroup(runAsGroup string) podOption { 830 return func(p *Pod) { 831 p.RunAsGroup = runAsGroup 832 } 833 } 834 835 func withPodName(name string) podOption { 836 return func(pod *Pod) { 837 pod.Name = name 838 } 839 } 840 841 func withHostname(h string) podOption { 842 return func(pod *Pod) { 843 pod.Hostname = h 844 } 845 } 846 847 func withHostAliases(ip string, host []string) podOption { 848 return func(pod *Pod) { 849 pod.HostAliases = append(pod.HostAliases, HostAlias{ 850 IP: ip, 851 HostName: host, 852 }) 853 } 854 } 855 856 func withCtr(c *Ctr) podOption { 857 return func(pod *Pod) { 858 pod.Ctrs = append(pod.Ctrs, c) 859 } 860 } 861 862 func withPodInitCtr(ic *Ctr) podOption { 863 return func(pod *Pod) { 864 pod.InitCtrs = append(pod.InitCtrs, ic) 865 } 866 } 867 868 func withRestartPolicy(policy string) podOption { 869 return func(pod *Pod) { 870 pod.RestartPolicy = policy 871 } 872 } 873 874 func withLabel(k, v string) podOption { 875 return func(pod *Pod) { 876 pod.Labels[k] = v 877 } 878 } 879 880 func withAnnotation(k, v string) podOption { 881 return func(pod *Pod) { 882 pod.Annotations[k] = v 883 } 884 } 885 886 func withVolume(v *Volume) podOption { 887 return func(pod *Pod) { 888 pod.Volumes = append(pod.Volumes, v) 889 } 890 } 891 892 func withHostNetwork() podOption { 893 return func(pod *Pod) { 894 pod.HostNetwork = true 895 } 896 } 897 898 // Deployment describes the options a kube yaml can be configured at deployment level 899 type Deployment struct { 900 Name string 901 Replicas int32 902 Labels map[string]string 903 Annotations map[string]string 904 PodTemplate *Pod 905 } 906 907 func getDeployment(options ...deploymentOption) *Deployment { 908 d := Deployment{ 909 Name: defaultDeploymentName, 910 Replicas: 1, 911 Labels: make(map[string]string), 912 Annotations: make(map[string]string), 913 PodTemplate: getPod(), 914 } 915 for _, option := range options { 916 option(&d) 917 } 918 919 return &d 920 } 921 922 type deploymentOption func(*Deployment) 923 924 func withDeploymentAnnotation(k, v string) deploymentOption { 925 return func(deployment *Deployment) { 926 deployment.Annotations[k] = v 927 } 928 } 929 930 func withPod(pod *Pod) deploymentOption { 931 return func(d *Deployment) { 932 d.PodTemplate = pod 933 } 934 } 935 936 func withReplicas(replicas int32) deploymentOption { 937 return func(d *Deployment) { 938 d.Replicas = replicas 939 } 940 } 941 942 // getPodNamesInDeployment returns list of Pod objects 943 // with just their name set, so that it can be passed around 944 // and into getCtrNameInPod for ease of testing 945 func getPodNamesInDeployment(d *Deployment) []Pod { 946 var pods []Pod 947 var i int32 948 949 for i = 0; i < d.Replicas; i++ { 950 p := Pod{} 951 p.Name = fmt.Sprintf("%s-pod-%d", d.Name, i) 952 pods = append(pods, p) 953 } 954 955 return pods 956 } 957 958 // Ctr describes the options a kube yaml can be configured at container level 959 type Ctr struct { 960 Name string 961 Image string 962 Cmd []string 963 Arg []string 964 CPURequest string 965 CPULimit string 966 MemoryRequest string 967 MemoryLimit string 968 SecurityContext bool 969 Caps bool 970 CapAdd []string 971 CapDrop []string 972 PullPolicy string 973 HostIP string 974 Port string 975 VolumeMount bool 976 VolumeMountPath string 977 VolumeName string 978 VolumeReadOnly bool 979 Env []Env 980 EnvFrom []EnvFrom 981 InitCtrType string 982 RunAsUser string 983 RunAsGroup string 984 } 985 986 // getCtr takes a list of ctrOptions and returns a Ctr with sane defaults 987 // and the configured options 988 func getCtr(options ...ctrOption) *Ctr { 989 c := Ctr{ 990 Name: defaultCtrName, 991 Image: defaultCtrImage, 992 Cmd: defaultCtrCmd, 993 Arg: defaultCtrArg, 994 SecurityContext: true, 995 Caps: false, 996 CapAdd: nil, 997 CapDrop: nil, 998 PullPolicy: "", 999 HostIP: "", 1000 Port: "", 1001 VolumeMount: false, 1002 VolumeMountPath: "", 1003 VolumeName: "", 1004 VolumeReadOnly: false, 1005 Env: []Env{}, 1006 EnvFrom: []EnvFrom{}, 1007 InitCtrType: "", 1008 } 1009 for _, option := range options { 1010 option(&c) 1011 } 1012 return &c 1013 } 1014 1015 type ctrOption func(*Ctr) 1016 1017 func withName(name string) ctrOption { 1018 return func(c *Ctr) { 1019 c.Name = name 1020 } 1021 } 1022 1023 func withInitCtr() ctrOption { 1024 return func(c *Ctr) { 1025 c.InitCtrType = define.AlwaysInitContainer 1026 } 1027 } 1028 1029 func withCmd(cmd []string) ctrOption { 1030 return func(c *Ctr) { 1031 c.Cmd = cmd 1032 } 1033 } 1034 1035 func withArg(arg []string) ctrOption { 1036 return func(c *Ctr) { 1037 c.Arg = arg 1038 } 1039 } 1040 1041 func withImage(img string) ctrOption { 1042 return func(c *Ctr) { 1043 c.Image = img 1044 } 1045 } 1046 1047 func withCPURequest(request string) ctrOption { 1048 return func(c *Ctr) { 1049 c.CPURequest = request 1050 } 1051 } 1052 1053 func withCPULimit(limit string) ctrOption { 1054 return func(c *Ctr) { 1055 c.CPULimit = limit 1056 } 1057 } 1058 1059 func withMemoryRequest(request string) ctrOption { 1060 return func(c *Ctr) { 1061 c.MemoryRequest = request 1062 } 1063 } 1064 1065 func withMemoryLimit(limit string) ctrOption { 1066 return func(c *Ctr) { 1067 c.MemoryLimit = limit 1068 } 1069 } 1070 1071 func withSecurityContext(sc bool) ctrOption { 1072 return func(c *Ctr) { 1073 c.SecurityContext = sc 1074 } 1075 } 1076 1077 func withRunAsUser(runAsUser string) ctrOption { 1078 return func(c *Ctr) { 1079 c.RunAsUser = runAsUser 1080 } 1081 } 1082 1083 func withRunAsGroup(runAsGroup string) ctrOption { 1084 return func(c *Ctr) { 1085 c.RunAsGroup = runAsGroup 1086 } 1087 } 1088 1089 func withCapAdd(caps []string) ctrOption { 1090 return func(c *Ctr) { 1091 c.CapAdd = caps 1092 c.Caps = true 1093 } 1094 } 1095 1096 func withCapDrop(caps []string) ctrOption { 1097 return func(c *Ctr) { 1098 c.CapDrop = caps 1099 c.Caps = true 1100 } 1101 } 1102 1103 func withPullPolicy(policy string) ctrOption { 1104 return func(c *Ctr) { 1105 c.PullPolicy = policy 1106 } 1107 } 1108 1109 func withHostIP(ip string, port string) ctrOption { 1110 return func(c *Ctr) { 1111 c.HostIP = ip 1112 c.Port = port 1113 } 1114 } 1115 1116 func withVolumeMount(mountPath string, readonly bool) ctrOption { 1117 return func(c *Ctr) { 1118 c.VolumeMountPath = mountPath 1119 c.VolumeName = defaultVolName 1120 c.VolumeReadOnly = readonly 1121 c.VolumeMount = true 1122 } 1123 } 1124 1125 func withEnv(name, value, valueFrom, refName, refKey string, optional bool) ctrOption { //nolint:unparam 1126 return func(c *Ctr) { 1127 e := Env{ 1128 Name: name, 1129 Value: value, 1130 ValueFrom: valueFrom, 1131 RefName: refName, 1132 RefKey: refKey, 1133 Optional: optional, 1134 } 1135 1136 c.Env = append(c.Env, e) 1137 } 1138 } 1139 1140 func withEnvFrom(name, from string, optional bool) ctrOption { 1141 return func(c *Ctr) { 1142 e := EnvFrom{ 1143 Name: name, 1144 From: from, 1145 Optional: optional, 1146 } 1147 1148 c.EnvFrom = append(c.EnvFrom, e) 1149 } 1150 } 1151 1152 func makeCtrNameInPod(pod *Pod, containerName string) string { 1153 return fmt.Sprintf("%s-%s", pod.Name, containerName) 1154 } 1155 1156 func getCtrNameInPod(pod *Pod) string { 1157 return makeCtrNameInPod(pod, defaultCtrName) 1158 } 1159 1160 type HostPath struct { 1161 Path string 1162 Type string 1163 } 1164 1165 type PersistentVolumeClaim struct { 1166 ClaimName string 1167 } 1168 1169 type ConfigMap struct { 1170 Name string 1171 Items []map[string]string 1172 Optional bool 1173 } 1174 1175 type Volume struct { 1176 VolumeType string 1177 Name string 1178 HostPath 1179 PersistentVolumeClaim 1180 ConfigMap 1181 } 1182 1183 // getHostPathVolume takes a type and a location for a HostPath 1184 // volume giving it a default name of volName 1185 func getHostPathVolume(vType, vPath string) *Volume { 1186 return &Volume{ 1187 VolumeType: "HostPath", 1188 Name: defaultVolName, 1189 HostPath: HostPath{ 1190 Path: vPath, 1191 Type: vType, 1192 }, 1193 } 1194 } 1195 1196 // getHostPathVolume takes a name for a Persistentvolumeclaim 1197 // volume giving it a default name of volName 1198 func getPersistentVolumeClaimVolume(vName string) *Volume { 1199 return &Volume{ 1200 VolumeType: "PersistentVolumeClaim", 1201 Name: defaultVolName, 1202 PersistentVolumeClaim: PersistentVolumeClaim{ 1203 ClaimName: vName, 1204 }, 1205 } 1206 } 1207 1208 // getConfigMap returns a new ConfigMap Volume given the name and items 1209 // of the ConfigMap. 1210 func getConfigMapVolume(vName string, items []map[string]string, optional bool) *Volume { 1211 return &Volume{ 1212 VolumeType: "ConfigMap", 1213 Name: defaultVolName, 1214 ConfigMap: ConfigMap{ 1215 Name: vName, 1216 Items: items, 1217 Optional: optional, 1218 }, 1219 } 1220 } 1221 1222 type Env struct { 1223 Name string 1224 Value string 1225 ValueFrom string 1226 RefName string 1227 RefKey string 1228 Optional bool 1229 } 1230 1231 type EnvFrom struct { 1232 Name string 1233 From string 1234 Optional bool 1235 } 1236 1237 func milliCPUToQuota(milliCPU string) int { 1238 milli, _ := strconv.Atoi(strings.Trim(milliCPU, "m")) 1239 return milli * defaultCPUPeriod 1240 } 1241 1242 var _ = Describe("Podman play kube", func() { 1243 var ( 1244 tempdir string 1245 err error 1246 podmanTest *PodmanTestIntegration 1247 kubeYaml string 1248 ) 1249 1250 BeforeEach(func() { 1251 tempdir, err = CreateTempDirInTempDir() 1252 if err != nil { 1253 os.Exit(1) 1254 } 1255 podmanTest = PodmanTestCreate(tempdir) 1256 podmanTest.Setup() 1257 kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml") 1258 }) 1259 1260 AfterEach(func() { 1261 podmanTest.Cleanup() 1262 f := CurrentGinkgoTestDescription() 1263 processTestResult(f) 1264 }) 1265 1266 It("podman play kube fail with yaml of unsupported kind", func() { 1267 err := writeYaml(unknownKindYaml, kubeYaml) 1268 Expect(err).To(BeNil()) 1269 1270 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1271 kube.WaitWithDefaultTimeout() 1272 Expect(kube).To(ExitWithError()) 1273 1274 }) 1275 1276 It("podman play kube fail with custom selinux label", func() { 1277 if !selinux.GetEnabled() { 1278 Skip("SELinux not enabled") 1279 } 1280 err := writeYaml(selinuxLabelPodYaml, kubeYaml) 1281 Expect(err).To(BeNil()) 1282 1283 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1284 kube.WaitWithDefaultTimeout() 1285 Expect(kube).Should(Exit(0)) 1286 1287 inspect := podmanTest.Podman([]string{"inspect", "label-pod-test", "--format", "'{{ .ProcessLabel }}'"}) 1288 inspect.WaitWithDefaultTimeout() 1289 label := inspect.OutputToString() 1290 1291 Expect(label).To(ContainSubstring("unconfined_u:system_r:spc_t:s0")) 1292 }) 1293 1294 It("podman play kube --no-host", func() { 1295 err := writeYaml(checkInfraImagePodYaml, kubeYaml) 1296 Expect(err).To(BeNil()) 1297 1298 kube := podmanTest.Podman([]string{"play", "kube", "--no-hosts", kubeYaml}) 1299 kube.WaitWithDefaultTimeout() 1300 Expect(kube).Should(Exit(0)) 1301 1302 podInspect := podmanTest.Podman([]string{"pod", "inspect", "check-infra-image"}) 1303 podInspect.WaitWithDefaultTimeout() 1304 Expect(podInspect).Should(Exit(0)) 1305 1306 data := podInspect.InspectPodToJSON() 1307 for _, ctr := range data.Containers { 1308 if strings.HasSuffix(ctr.Name, "-infra") { 1309 continue 1310 } 1311 exec := podmanTest.Podman([]string{"exec", ctr.ID, "cat", "/etc/hosts"}) 1312 exec.WaitWithDefaultTimeout() 1313 Expect(exec).Should(Exit(0)) 1314 Expect(exec.OutputToString()).To(Not(ContainSubstring("check-infra-image"))) 1315 } 1316 }) 1317 1318 It("podman play kube with non-existing configmap", func() { 1319 err := writeYaml(podWithoutConfigMapDefined, kubeYaml) 1320 Expect(err).To(BeNil()) 1321 1322 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1323 kube.WaitWithDefaultTimeout() 1324 Expect(kube).Should(Exit(125)) 1325 Expect(kube.ErrorToString()).To(ContainSubstring("failed to create volume \"mycm\": no such ConfigMap \"mycm\"")) 1326 }) 1327 1328 It("podman play kube test HostAliases with --no-hosts", func() { 1329 pod := getPod(withHostAliases("192.168.1.2", []string{ 1330 "test1.podman.io", 1331 "test2.podman.io", 1332 }), 1333 withHostAliases("192.168.1.3", []string{ 1334 "test3.podman.io", 1335 "test4.podman.io", 1336 }), 1337 ) 1338 err := generateKubeYaml("pod", pod, kubeYaml) 1339 Expect(err).To(BeNil()) 1340 1341 kube := podmanTest.Podman([]string{"play", "kube", "--no-hosts", kubeYaml}) 1342 kube.WaitWithDefaultTimeout() 1343 Expect(kube).Should(Exit(125)) 1344 Expect(kube.ErrorToString()).To(ContainSubstring("HostAliases in yaml file will not work with --no-hosts")) 1345 }) 1346 1347 It("podman play kube should use customized infra_image", func() { 1348 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 1349 1350 infraImage := "k8s.gcr.io/pause:3.2" 1351 err := ioutil.WriteFile(conffile, []byte(fmt.Sprintf("[engine]\ninfra_image=\"%s\"\n", infraImage)), 0644) 1352 Expect(err).To(BeNil()) 1353 1354 os.Setenv("CONTAINERS_CONF", conffile) 1355 defer os.Unsetenv("CONTAINERS_CONF") 1356 1357 if IsRemote() { 1358 podmanTest.RestartRemoteService() 1359 } 1360 1361 err = writeYaml(checkInfraImagePodYaml, kubeYaml) 1362 Expect(err).To(BeNil()) 1363 1364 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1365 kube.WaitWithDefaultTimeout() 1366 Expect(kube).Should(Exit(0)) 1367 1368 podInspect := podmanTest.Podman([]string{"inspect", "check-infra-image", "--format", "{{ .InfraContainerID }}"}) 1369 podInspect.WaitWithDefaultTimeout() 1370 infraContainerID := podInspect.OutputToString() 1371 1372 conInspect := podmanTest.Podman([]string{"inspect", infraContainerID, "--format", "{{ .ImageName }}"}) 1373 conInspect.WaitWithDefaultTimeout() 1374 infraContainerImage := conInspect.OutputToString() 1375 Expect(infraContainerImage).To(Equal(infraImage)) 1376 }) 1377 1378 It("podman play kube should share ipc,net,uts when shareProcessNamespace is set", func() { 1379 SkipIfRootless("Requires root privileges for sharing few namespaces") 1380 err := writeYaml(sharedNamespacePodYaml, kubeYaml) 1381 Expect(err).To(BeNil()) 1382 1383 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1384 kube.WaitWithDefaultTimeout() 1385 Expect(kube).Should(Exit(0)) 1386 1387 inspect := podmanTest.Podman([]string{"inspect", "testpod1", "--format", "'{{ .SharedNamespaces }}'"}) 1388 inspect.WaitWithDefaultTimeout() 1389 sharednamespaces := inspect.OutputToString() 1390 Expect(sharednamespaces).To(ContainSubstring("ipc")) 1391 Expect(sharednamespaces).To(ContainSubstring("net")) 1392 Expect(sharednamespaces).To(ContainSubstring("uts")) 1393 Expect(sharednamespaces).To(ContainSubstring("pid")) 1394 }) 1395 1396 It("podman play kube should be able to run image where workdir is a symlink", func() { 1397 session := podmanTest.Podman([]string{ 1398 "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink", 1399 }) 1400 session.WaitWithDefaultTimeout() 1401 Expect(session).Should(Exit(0)) 1402 1403 err := writeYaml(workdirSymlinkPodYaml, kubeYaml) 1404 Expect(err).To(BeNil()) 1405 1406 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1407 kube.WaitWithDefaultTimeout() 1408 Expect(kube).Should(Exit(0)) 1409 1410 logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-symlink-test-symlink", "test-symlink"}) 1411 logs.WaitWithDefaultTimeout() 1412 Expect(logs).Should(Exit(0)) 1413 Expect(logs.OutputToString()).To(ContainSubstring("hello")) 1414 }) 1415 1416 It("podman play kube should not rename pod if container in pod has same name", func() { 1417 err := writeYaml(podnameEqualsContainerNameYaml, kubeYaml) 1418 Expect(err).To(BeNil()) 1419 1420 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1421 kube.WaitWithDefaultTimeout() 1422 Expect(kube).Should(Exit(0)) 1423 1424 testPodCreated := podmanTest.Podman([]string{"pod", "exists", "podnameEqualsContainerNameYaml"}) 1425 testPodCreated.WaitWithDefaultTimeout() 1426 Expect(testPodCreated).Should(Exit(0)) 1427 1428 inspect := podmanTest.Podman([]string{"inspect", "podnameEqualsContainerNameYaml"}) 1429 inspect.WaitWithDefaultTimeout() 1430 podInspect := inspect.InspectPodArrToJSON() 1431 Expect(podInspect).Should(HaveLen(1)) 1432 var containerNames []string 1433 for _, container := range podInspect[0].Containers { 1434 containerNames = append(containerNames, container.Name) 1435 } 1436 Expect(containerNames).To(ContainElement("podnameEqualsContainerNameYaml-podnameEqualsContainerNameYaml")) 1437 }) 1438 1439 It("podman play kube should error if pod dont have a name", func() { 1440 err := writeYaml(podWithoutAName, kubeYaml) 1441 Expect(err).To(BeNil()) 1442 1443 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1444 kube.WaitWithDefaultTimeout() 1445 Expect(kube).Should(Exit(125)) 1446 1447 }) 1448 1449 It("podman play kube support container liveness probe", func() { 1450 err := writeYaml(livenessProbePodYaml, kubeYaml) 1451 Expect(err).To(BeNil()) 1452 1453 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1454 kube.WaitWithDefaultTimeout() 1455 Expect(kube).Should(Exit(0)) 1456 1457 inspect := podmanTest.Podman([]string{"inspect", "liveness-probe-pod-0-alpine", "--format", "'{{ .Config.Healthcheck }}'"}) 1458 inspect.WaitWithDefaultTimeout() 1459 healthcheckcmd := inspect.OutputToString() 1460 // check if CMD-SHELL based equivalent health check is added to container 1461 Expect(healthcheckcmd).To(ContainSubstring("CMD-SHELL")) 1462 }) 1463 1464 It("podman play kube liveness probe should fail", func() { 1465 err := writeYaml(livenessProbeUnhealthyPodYaml, kubeYaml) 1466 Expect(err).To(BeNil()) 1467 1468 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1469 kube.WaitWithDefaultTimeout() 1470 Expect(kube).Should(Exit(0)) 1471 1472 time.Sleep(2 * time.Second) 1473 hc := podmanTest.Podman([]string{"healthcheck", "run", "liveness-unhealthy-probe-pod-0-alpine"}) 1474 hc.WaitWithDefaultTimeout() 1475 hcoutput := hc.OutputToString() 1476 Expect(hcoutput).To(ContainSubstring(define.HealthCheckUnhealthy)) 1477 }) 1478 1479 It("podman play kube fail with nonexistent authfile", func() { 1480 err := generateKubeYaml("pod", getPod(), kubeYaml) 1481 Expect(err).To(BeNil()) 1482 1483 kube := podmanTest.Podman([]string{"play", "kube", "--authfile", "/tmp/nonexistent", kubeYaml}) 1484 kube.WaitWithDefaultTimeout() 1485 Expect(kube).To(ExitWithError()) 1486 1487 }) 1488 1489 It("podman play kube test correct command", func() { 1490 pod := getPod() 1491 err := generateKubeYaml("pod", pod, kubeYaml) 1492 Expect(err).To(BeNil()) 1493 1494 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1495 kube.WaitWithDefaultTimeout() 1496 Expect(kube).Should(Exit(0)) 1497 1498 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 1499 inspect.WaitWithDefaultTimeout() 1500 Expect(inspect).Should(Exit(0)) 1501 cmd := inspect.OutputToString() 1502 1503 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 1504 inspect.WaitWithDefaultTimeout() 1505 Expect(inspect).Should(Exit(0)) 1506 ep := inspect.OutputToString() 1507 1508 // Use the defined command to override the image's command 1509 Expect(ep).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 1510 Expect(cmd).To(ContainSubstring(strings.Join(defaultCtrArg, " "))) 1511 }) 1512 1513 // If you do not supply command or args for a Container, the defaults defined in the Docker image are used. 1514 It("podman play kube test correct args and cmd when not specified", func() { 1515 pod := getPod(withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil)))) 1516 err := generateKubeYaml("pod", pod, kubeYaml) 1517 Expect(err).To(BeNil()) 1518 1519 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1520 kube.WaitWithDefaultTimeout() 1521 Expect(kube).Should(Exit(0)) 1522 1523 // this image's ENTRYPOINT is `/entrypoint.sh` 1524 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 1525 inspect.WaitWithDefaultTimeout() 1526 Expect(inspect).Should(Exit(0)) 1527 Expect(inspect.OutputToString()).To(ContainSubstring(`/entrypoint.sh`)) 1528 1529 // and its COMMAND is `/etc/docker/registry/config.yml` 1530 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 1531 inspect.WaitWithDefaultTimeout() 1532 Expect(inspect).Should(Exit(0)) 1533 Expect(inspect.OutputToString()).To(ContainSubstring(`[/etc/docker/registry/config.yml]`)) 1534 }) 1535 1536 // If you supply a command but no args for a Container, only the supplied command is used. 1537 // The default EntryPoint and the default Cmd defined in the Docker image are ignored. 1538 It("podman play kube test correct command with only set command in yaml file", func() { 1539 pod := getPod(withCtr(getCtr(withImage(registry), withCmd([]string{"echo", "hello"}), withArg(nil)))) 1540 err := generateKubeYaml("pod", pod, kubeYaml) 1541 Expect(err).To(BeNil()) 1542 1543 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1544 kube.WaitWithDefaultTimeout() 1545 Expect(kube).Should(Exit(0)) 1546 1547 // Use the defined command to override the image's command, and don't set the args 1548 // so the full command in result should not contains the image's command 1549 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 1550 inspect.WaitWithDefaultTimeout() 1551 Expect(inspect).Should(Exit(0)) 1552 Expect(inspect.OutputToString()).To(ContainSubstring(`echo hello`)) 1553 1554 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 1555 inspect.WaitWithDefaultTimeout() 1556 Expect(inspect).Should(Exit(0)) 1557 // an empty command is reported as '[]' 1558 Expect(inspect.OutputToString()).To(ContainSubstring(`[]`)) 1559 }) 1560 1561 // If you have an init container in the pod yaml, podman should create and run the init container with play kube 1562 It("podman play kube test with init containers", func() { 1563 pod := getPod(withPodInitCtr(getCtr(withImage(ALPINE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("init-test"))), withCtr(getCtr(withImage(ALPINE), withCmd([]string{"top"})))) 1564 err := generateKubeYaml("pod", pod, kubeYaml) 1565 Expect(err).To(BeNil()) 1566 1567 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1568 kube.WaitWithDefaultTimeout() 1569 Expect(kube).Should(Exit(0)) 1570 1571 // Expect the number of containers created to be 3, one init, infra, and regular container 1572 numOfCtrs := podmanTest.NumberOfContainers() 1573 Expect(numOfCtrs).To(Equal(3)) 1574 1575 // Init container should have exited after running 1576 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-init-test"}) 1577 inspect.WaitWithDefaultTimeout() 1578 Expect(inspect).Should(Exit(0)) 1579 Expect(inspect.OutputToString()).To(ContainSubstring("exited")) 1580 1581 // Regular container should be in running state 1582 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 1583 inspect.WaitWithDefaultTimeout() 1584 Expect(inspect).Should(Exit(0)) 1585 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 1586 }) 1587 1588 // If you supply only args for a Container, the default Entrypoint defined in the Docker image is run with the args that you supplied. 1589 It("podman play kube test correct command with only set args in yaml file", func() { 1590 pod := getPod(withCtr(getCtr(withImage(registry), withCmd(nil), withArg([]string{"echo", "hello"})))) 1591 err := generateKubeYaml("pod", pod, kubeYaml) 1592 Expect(err).To(BeNil()) 1593 1594 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1595 kube.WaitWithDefaultTimeout() 1596 Expect(kube).Should(Exit(0)) 1597 1598 // this image's ENTRYPOINT is `/entrypoint.sh` 1599 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 1600 inspect.WaitWithDefaultTimeout() 1601 Expect(inspect).Should(Exit(0)) 1602 Expect(inspect.OutputToString()).To(ContainSubstring(`/entrypoint.sh`)) 1603 1604 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 1605 inspect.WaitWithDefaultTimeout() 1606 Expect(inspect).Should(Exit(0)) 1607 Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`)) 1608 }) 1609 1610 // If you supply a command and args, 1611 // the default Entrypoint and the default Cmd defined in the Docker image are ignored. 1612 // Your command is run with your args. 1613 It("podman play kube test correct command with both set args and cmd in yaml file", func() { 1614 pod := getPod(withCtr(getCtr(withImage(registry), withCmd([]string{"echo"}), withArg([]string{"hello"})))) 1615 err := generateKubeYaml("pod", pod, kubeYaml) 1616 Expect(err).To(BeNil()) 1617 1618 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1619 kube.WaitWithDefaultTimeout() 1620 Expect(kube).Should(Exit(0)) 1621 1622 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 1623 inspect.WaitWithDefaultTimeout() 1624 Expect(inspect).Should(Exit(0)) 1625 Expect(inspect.OutputToString()).To(ContainSubstring(`echo`)) 1626 1627 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 1628 inspect.WaitWithDefaultTimeout() 1629 Expect(inspect).Should(Exit(0)) 1630 Expect(inspect.OutputToString()).To(ContainSubstring(`[hello]`)) 1631 }) 1632 1633 It("podman play kube test correct output", func() { 1634 p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"})))) 1635 1636 err := generateKubeYaml("pod", p, kubeYaml) 1637 Expect(err).To(BeNil()) 1638 1639 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1640 kube.WaitWithDefaultTimeout() 1641 Expect(kube).Should(Exit(0)) 1642 1643 logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(p)}) 1644 logs.WaitWithDefaultTimeout() 1645 Expect(logs).Should(Exit(0)) 1646 Expect(logs.OutputToString()).To(ContainSubstring("hello world")) 1647 }) 1648 1649 It("podman pod logs test", func() { 1650 SkipIfRemote("podman-remote pod logs -c is mandatory for remote machine") 1651 p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"})))) 1652 1653 err := generateKubeYaml("pod", p, kubeYaml) 1654 Expect(err).To(BeNil()) 1655 1656 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1657 kube.WaitWithDefaultTimeout() 1658 Expect(kube).Should(Exit(0)) 1659 1660 logs := podmanTest.Podman([]string{"pod", "logs", p.Name}) 1661 logs.WaitWithDefaultTimeout() 1662 Expect(logs).Should(Exit(0)) 1663 Expect(logs.OutputToString()).To(ContainSubstring("hello world")) 1664 }) 1665 1666 It("podman-remote pod logs test", func() { 1667 // -c or --container is required in podman-remote due to api limitation. 1668 p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"})))) 1669 1670 err := generateKubeYaml("pod", p, kubeYaml) 1671 Expect(err).To(BeNil()) 1672 1673 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1674 kube.WaitWithDefaultTimeout() 1675 Expect(kube).Should(Exit(0)) 1676 1677 logs := podmanTest.Podman([]string{"pod", "logs", "-c", getCtrNameInPod(p), p.Name}) 1678 logs.WaitWithDefaultTimeout() 1679 Expect(logs).Should(Exit(0)) 1680 Expect(logs.OutputToString()).To(ContainSubstring("hello world")) 1681 }) 1682 1683 It("podman play kube test restartPolicy", func() { 1684 // podName, set, expect 1685 testSli := [][]string{ 1686 {"testPod1", "", "always"}, // Default equal to always 1687 {"testPod2", "Always", "always"}, 1688 {"testPod3", "OnFailure", "on-failure"}, 1689 {"testPod4", "Never", "no"}, 1690 } 1691 for _, v := range testSli { 1692 pod := getPod(withPodName(v[0]), withRestartPolicy(v[1])) 1693 err := generateKubeYaml("pod", pod, kubeYaml) 1694 Expect(err).To(BeNil()) 1695 1696 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1697 kube.WaitWithDefaultTimeout() 1698 Expect(kube).Should(Exit(0)) 1699 1700 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{.HostConfig.RestartPolicy.Name}}"}) 1701 inspect.WaitWithDefaultTimeout() 1702 Expect(inspect).Should(Exit(0)) 1703 Expect(inspect.OutputToString()).To(Equal(v[2])) 1704 } 1705 }) 1706 1707 It("podman play kube test env value from configmap", func() { 1708 SkipIfRemote("configmap list is not supported as a param") 1709 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 1710 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 1711 err := generateKubeYaml("configmap", cm, cmYamlPathname) 1712 Expect(err).To(BeNil()) 1713 1714 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 1715 err = generateKubeYaml("pod", pod, kubeYaml) 1716 Expect(err).To(BeNil()) 1717 1718 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname}) 1719 kube.WaitWithDefaultTimeout() 1720 Expect(kube).Should(Exit(0)) 1721 1722 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 1723 inspect.WaitWithDefaultTimeout() 1724 Expect(inspect).Should(Exit(0)) 1725 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 1726 }) 1727 1728 It("podman play kube test env value from configmap and --replace should reuse the configmap volume", func() { 1729 SkipIfRemote("configmap list is not supported as a param") 1730 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 1731 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 1732 err := generateKubeYaml("configmap", cm, cmYamlPathname) 1733 Expect(err).To(BeNil()) 1734 1735 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 1736 err = generateKubeYaml("pod", pod, kubeYaml) 1737 Expect(err).To(BeNil()) 1738 1739 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname}) 1740 kube.WaitWithDefaultTimeout() 1741 Expect(kube).Should(Exit(0)) 1742 1743 // create pod again with --replace 1744 kube = podmanTest.Podman([]string{"play", "kube", "--replace", kubeYaml, "--configmap", cmYamlPathname}) 1745 kube.WaitWithDefaultTimeout() 1746 Expect(kube).Should(Exit(0)) 1747 1748 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 1749 inspect.WaitWithDefaultTimeout() 1750 Expect(inspect).Should(Exit(0)) 1751 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 1752 }) 1753 1754 It("podman play kube test required env value from configmap with missing key", func() { 1755 SkipIfRemote("configmap list is not supported as a param") 1756 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 1757 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 1758 err := generateKubeYaml("configmap", cm, cmYamlPathname) 1759 Expect(err).To(BeNil()) 1760 1761 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", false)))) 1762 err = generateKubeYaml("pod", pod, kubeYaml) 1763 Expect(err).To(BeNil()) 1764 1765 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname}) 1766 kube.WaitWithDefaultTimeout() 1767 Expect(kube).To(ExitWithError()) 1768 }) 1769 1770 It("podman play kube test required env value from missing configmap", func() { 1771 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "missing_cm", "FOO", false)))) 1772 err = generateKubeYaml("pod", pod, kubeYaml) 1773 Expect(err).To(BeNil()) 1774 1775 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1776 kube.WaitWithDefaultTimeout() 1777 Expect(kube).To(ExitWithError()) 1778 }) 1779 1780 It("podman play kube test optional env value from configmap with missing key", func() { 1781 SkipIfRemote("configmap list is not supported as a param") 1782 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 1783 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 1784 err := generateKubeYaml("configmap", cm, cmYamlPathname) 1785 Expect(err).To(BeNil()) 1786 1787 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", true)))) 1788 err = generateKubeYaml("pod", pod, kubeYaml) 1789 Expect(err).To(BeNil()) 1790 1791 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname}) 1792 kube.WaitWithDefaultTimeout() 1793 Expect(kube).Should(Exit(0)) 1794 1795 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 1796 inspect.WaitWithDefaultTimeout() 1797 Expect(inspect).Should(Exit(0)) 1798 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 1799 }) 1800 1801 It("podman play kube test optional env value from missing configmap", func() { 1802 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "missing_cm", "FOO", true)))) 1803 err = generateKubeYaml("pod", pod, kubeYaml) 1804 Expect(err).To(BeNil()) 1805 1806 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1807 kube.WaitWithDefaultTimeout() 1808 Expect(kube).Should(Exit(0)) 1809 1810 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 1811 inspect.WaitWithDefaultTimeout() 1812 Expect(inspect).Should(Exit(0)) 1813 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 1814 }) 1815 1816 It("podman play kube test get all key-value pairs from configmap as envs", func() { 1817 SkipIfRemote("configmap list is not supported as a param") 1818 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 1819 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2")) 1820 err := generateKubeYaml("configmap", cm, cmYamlPathname) 1821 Expect(err).To(BeNil()) 1822 1823 pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap", false)))) 1824 err = generateKubeYaml("pod", pod, kubeYaml) 1825 Expect(err).To(BeNil()) 1826 1827 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname}) 1828 kube.WaitWithDefaultTimeout() 1829 Expect(kube).Should(Exit(0)) 1830 1831 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 1832 inspect.WaitWithDefaultTimeout() 1833 Expect(inspect).Should(Exit(0)) 1834 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`)) 1835 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`)) 1836 }) 1837 1838 It("podman play kube test get all key-value pairs from required configmap as envs", func() { 1839 pod := getPod(withCtr(getCtr(withEnvFrom("missing_cm", "configmap", false)))) 1840 err = generateKubeYaml("pod", pod, kubeYaml) 1841 Expect(err).To(BeNil()) 1842 1843 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1844 kube.WaitWithDefaultTimeout() 1845 Expect(kube).To(ExitWithError()) 1846 }) 1847 1848 It("podman play kube test get all key-value pairs from optional configmap as envs", func() { 1849 pod := getPod(withCtr(getCtr(withEnvFrom("missing_cm", "configmap", true)))) 1850 err = generateKubeYaml("pod", pod, kubeYaml) 1851 Expect(err).To(BeNil()) 1852 1853 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1854 kube.WaitWithDefaultTimeout() 1855 Expect(kube).Should(Exit(0)) 1856 }) 1857 1858 It("podman play kube test env value from secret", func() { 1859 createSecret(podmanTest, "foo", defaultSecret) 1860 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "FOO", false)))) 1861 err = generateKubeYaml("pod", pod, kubeYaml) 1862 Expect(err).To(BeNil()) 1863 1864 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1865 kube.WaitWithDefaultTimeout() 1866 Expect(kube).Should(Exit(0)) 1867 1868 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 1869 inspect.WaitWithDefaultTimeout() 1870 Expect(inspect).Should(Exit(0)) 1871 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 1872 }) 1873 1874 It("podman play kube test required env value from missing secret", func() { 1875 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "FOO", false)))) 1876 err = generateKubeYaml("pod", pod, kubeYaml) 1877 Expect(err).To(BeNil()) 1878 1879 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1880 kube.WaitWithDefaultTimeout() 1881 Expect(kube).To(ExitWithError()) 1882 }) 1883 1884 It("podman play kube test required env value from secret with missing key", func() { 1885 createSecret(podmanTest, "foo", defaultSecret) 1886 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "MISSING", false)))) 1887 err = generateKubeYaml("pod", pod, kubeYaml) 1888 Expect(err).To(BeNil()) 1889 1890 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1891 kube.WaitWithDefaultTimeout() 1892 Expect(kube).To(ExitWithError()) 1893 }) 1894 1895 It("podman play kube test optional env value from missing secret", func() { 1896 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "FOO", true)))) 1897 err = generateKubeYaml("pod", pod, kubeYaml) 1898 Expect(err).To(BeNil()) 1899 1900 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1901 kube.WaitWithDefaultTimeout() 1902 Expect(kube).Should(Exit(0)) 1903 1904 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 1905 inspect.WaitWithDefaultTimeout() 1906 Expect(inspect).Should(Exit(0)) 1907 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 1908 }) 1909 1910 It("podman play kube test optional env value from secret with missing key", func() { 1911 createSecret(podmanTest, "foo", defaultSecret) 1912 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "MISSING", true)))) 1913 err = generateKubeYaml("pod", pod, kubeYaml) 1914 Expect(err).To(BeNil()) 1915 1916 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1917 kube.WaitWithDefaultTimeout() 1918 Expect(kube).Should(Exit(0)) 1919 1920 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 1921 inspect.WaitWithDefaultTimeout() 1922 Expect(inspect).Should(Exit(0)) 1923 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 1924 }) 1925 1926 It("podman play kube test get all key-value pairs from secret as envs", func() { 1927 createSecret(podmanTest, "foo", defaultSecret) 1928 pod := getPod(withCtr(getCtr(withEnvFrom("foo", "secret", false)))) 1929 err = generateKubeYaml("pod", pod, kubeYaml) 1930 Expect(err).To(BeNil()) 1931 1932 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1933 kube.WaitWithDefaultTimeout() 1934 Expect(kube).Should(Exit(0)) 1935 1936 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 1937 inspect.WaitWithDefaultTimeout() 1938 Expect(inspect).Should(Exit(0)) 1939 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 1940 Expect(inspect.OutputToString()).To(ContainSubstring(`BAR=bar`)) 1941 }) 1942 1943 It("podman play kube test get all key-value pairs from required secret as envs", func() { 1944 pod := getPod(withCtr(getCtr(withEnvFrom("missing_secret", "secret", false)))) 1945 err = generateKubeYaml("pod", pod, kubeYaml) 1946 Expect(err).To(BeNil()) 1947 1948 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1949 kube.WaitWithDefaultTimeout() 1950 Expect(kube).To(ExitWithError()) 1951 }) 1952 1953 It("podman play kube test get all key-value pairs from optional secret as envs", func() { 1954 pod := getPod(withCtr(getCtr(withEnvFrom("missing_secret", "secret", true)))) 1955 err = generateKubeYaml("pod", pod, kubeYaml) 1956 Expect(err).To(BeNil()) 1957 1958 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1959 kube.WaitWithDefaultTimeout() 1960 Expect(kube).Should(Exit(0)) 1961 }) 1962 1963 It("podman play kube test duplicate container name", func() { 1964 p := getPod(withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "hello"}))), withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "world"})))) 1965 1966 err := generateKubeYaml("pod", p, kubeYaml) 1967 Expect(err).To(BeNil()) 1968 1969 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1970 kube.WaitWithDefaultTimeout() 1971 Expect(kube).To(ExitWithError()) 1972 1973 p = getPod(withPodInitCtr(getCtr(withImage(ALPINE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("initctr"))), withCtr(getCtr(withImage(ALPINE), withName("initctr"), withCmd([]string{"top"})))) 1974 1975 err = generateKubeYaml("pod", p, kubeYaml) 1976 Expect(err).To(BeNil()) 1977 1978 kube = podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1979 kube.WaitWithDefaultTimeout() 1980 Expect(kube).To(ExitWithError()) 1981 }) 1982 1983 It("podman play kube test hostname", func() { 1984 pod := getPod() 1985 err := generateKubeYaml("pod", pod, kubeYaml) 1986 Expect(err).To(BeNil()) 1987 1988 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 1989 kube.WaitWithDefaultTimeout() 1990 Expect(kube).Should(Exit(0)) 1991 1992 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"}) 1993 inspect.WaitWithDefaultTimeout() 1994 Expect(inspect).Should(Exit(0)) 1995 Expect(inspect.OutputToString()).To(Equal(defaultPodName)) 1996 }) 1997 1998 It("podman play kube test with customized hostname", func() { 1999 hostname := "myhostname" 2000 pod := getPod(withHostname(hostname)) 2001 err := generateKubeYaml("pod", getPod(withHostname(hostname)), kubeYaml) 2002 Expect(err).To(BeNil()) 2003 2004 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2005 kube.WaitWithDefaultTimeout() 2006 Expect(kube).Should(Exit(0)) 2007 2008 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"}) 2009 inspect.WaitWithDefaultTimeout() 2010 Expect(inspect).Should(Exit(0)) 2011 Expect(inspect.OutputToString()).To(Equal(hostname)) 2012 2013 hostnameInCtr := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "hostname"}) 2014 hostnameInCtr.WaitWithDefaultTimeout() 2015 Expect(hostnameInCtr).Should(Exit(0)) 2016 Expect(hostnameInCtr.OutputToString()).To(Equal(hostname)) 2017 }) 2018 2019 It("podman play kube test HostAliases", func() { 2020 pod := getPod(withHostAliases("192.168.1.2", []string{ 2021 "test1.podman.io", 2022 "test2.podman.io", 2023 }), 2024 withHostAliases("192.168.1.3", []string{ 2025 "test3.podman.io", 2026 "test4.podman.io", 2027 }), 2028 ) 2029 err := generateKubeYaml("pod", pod, kubeYaml) 2030 Expect(err).To(BeNil()) 2031 2032 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2033 kube.WaitWithDefaultTimeout() 2034 Expect(kube).Should(Exit(0)) 2035 2036 inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.HostAdd}}"}) 2037 inspect.WaitWithDefaultTimeout() 2038 Expect(inspect).Should(Exit(0)) 2039 Expect(inspect.OutputToString()). 2040 To(Equal("[test1.podman.io:192.168.1.2 test2.podman.io:192.168.1.2 test3.podman.io:192.168.1.3 test4.podman.io:192.168.1.3]")) 2041 }) 2042 2043 It("podman play kube cap add", func() { 2044 capAdd := "CAP_SYS_ADMIN" 2045 ctr := getCtr(withCapAdd([]string{capAdd}), withCmd([]string{"cat", "/proc/self/status"}), withArg(nil)) 2046 2047 pod := getPod(withCtr(ctr)) 2048 err := generateKubeYaml("pod", pod, kubeYaml) 2049 Expect(err).To(BeNil()) 2050 2051 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2052 kube.WaitWithDefaultTimeout() 2053 Expect(kube).Should(Exit(0)) 2054 2055 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 2056 inspect.WaitWithDefaultTimeout() 2057 Expect(inspect).Should(Exit(0)) 2058 Expect(inspect.OutputToString()).To(ContainSubstring(capAdd)) 2059 }) 2060 2061 It("podman play kube cap drop", func() { 2062 capDrop := "CAP_CHOWN" 2063 ctr := getCtr(withCapDrop([]string{capDrop})) 2064 2065 pod := getPod(withCtr(ctr)) 2066 err := generateKubeYaml("pod", pod, kubeYaml) 2067 Expect(err).To(BeNil()) 2068 2069 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2070 kube.WaitWithDefaultTimeout() 2071 Expect(kube).Should(Exit(0)) 2072 2073 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 2074 inspect.WaitWithDefaultTimeout() 2075 Expect(inspect).Should(Exit(0)) 2076 Expect(inspect.OutputToString()).To(ContainSubstring(capDrop)) 2077 }) 2078 2079 It("podman play kube no security context", func() { 2080 // expect play kube to not fail if no security context is specified 2081 pod := getPod(withCtr(getCtr(withSecurityContext(false)))) 2082 err := generateKubeYaml("pod", pod, kubeYaml) 2083 Expect(err).To(BeNil()) 2084 2085 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2086 kube.WaitWithDefaultTimeout() 2087 Expect(kube).Should(Exit(0)) 2088 2089 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 2090 inspect.WaitWithDefaultTimeout() 2091 Expect(inspect).Should(Exit(0)) 2092 }) 2093 2094 It("podman play kube seccomp container level", func() { 2095 SkipIfRemote("podman-remote does not support --seccomp-profile-root flag") 2096 // expect play kube is expected to set a seccomp label if it's applied as an annotation 2097 jsonFile, err := podmanTest.CreateSeccompJSON(seccompPwdEPERM) 2098 if err != nil { 2099 fmt.Println(err) 2100 Skip("Failed to prepare seccomp.json for test.") 2101 } 2102 2103 ctrAnnotation := "container.seccomp.security.alpha.kubernetes.io/" + defaultCtrName 2104 ctr := getCtr(withCmd([]string{"pwd"}), withArg(nil)) 2105 2106 pod := getPod(withCtr(ctr), withAnnotation(ctrAnnotation, "localhost/"+filepath.Base(jsonFile))) 2107 err = generateKubeYaml("pod", pod, kubeYaml) 2108 Expect(err).To(BeNil()) 2109 2110 // CreateSeccompJSON will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look 2111 kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml}) 2112 kube.WaitWithDefaultTimeout() 2113 Expect(kube).Should(Exit(0)) 2114 2115 logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)}) 2116 logs.WaitWithDefaultTimeout() 2117 Expect(logs).Should(Exit(0)) 2118 Expect(logs.ErrorToString()).To(ContainSubstring("Operation not permitted")) 2119 }) 2120 2121 It("podman play kube seccomp pod level", func() { 2122 SkipIfRemote("podman-remote does not support --seccomp-profile-root flag") 2123 // expect play kube is expected to set a seccomp label if it's applied as an annotation 2124 jsonFile, err := podmanTest.CreateSeccompJSON(seccompPwdEPERM) 2125 if err != nil { 2126 fmt.Println(err) 2127 Skip("Failed to prepare seccomp.json for test.") 2128 } 2129 defer os.Remove(jsonFile) 2130 2131 ctr := getCtr(withCmd([]string{"pwd"}), withArg(nil)) 2132 2133 pod := getPod(withCtr(ctr), withAnnotation("seccomp.security.alpha.kubernetes.io/pod", "localhost/"+filepath.Base(jsonFile))) 2134 err = generateKubeYaml("pod", pod, kubeYaml) 2135 Expect(err).To(BeNil()) 2136 2137 // CreateSeccompJSON will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look 2138 kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml}) 2139 kube.WaitWithDefaultTimeout() 2140 Expect(kube).Should(Exit(0)) 2141 2142 logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)}) 2143 logs.WaitWithDefaultTimeout() 2144 Expect(logs).Should(Exit(0)) 2145 Expect(logs.ErrorToString()).To(ContainSubstring("Operation not permitted")) 2146 }) 2147 2148 It("podman play kube with pull policy of never should be 125", func() { 2149 ctr := getCtr(withPullPolicy("never"), withImage(BB_GLIBC)) 2150 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 2151 Expect(err).To(BeNil()) 2152 2153 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2154 kube.WaitWithDefaultTimeout() 2155 Expect(kube).Should(Exit(125)) 2156 }) 2157 2158 It("podman play kube with pull policy of missing", func() { 2159 ctr := getCtr(withPullPolicy("Missing"), withImage(BB)) 2160 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 2161 Expect(err).To(BeNil()) 2162 2163 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2164 kube.WaitWithDefaultTimeout() 2165 Expect(kube).Should(Exit(0)) 2166 }) 2167 2168 It("podman play kube with pull always", func() { 2169 oldBB := "quay.io/libpod/busybox:1.30.1" 2170 pull := podmanTest.Podman([]string{"pull", oldBB}) 2171 pull.WaitWithDefaultTimeout() 2172 2173 tag := podmanTest.Podman([]string{"tag", oldBB, BB}) 2174 tag.WaitWithDefaultTimeout() 2175 Expect(tag).Should(Exit(0)) 2176 2177 rmi := podmanTest.Podman([]string{"rmi", oldBB}) 2178 rmi.WaitWithDefaultTimeout() 2179 Expect(rmi).Should(Exit(0)) 2180 2181 inspect := podmanTest.Podman([]string{"inspect", BB}) 2182 inspect.WaitWithDefaultTimeout() 2183 oldBBinspect := inspect.InspectImageJSON() 2184 2185 ctr := getCtr(withPullPolicy("always"), withImage(BB)) 2186 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 2187 Expect(err).To(BeNil()) 2188 2189 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2190 kube.WaitWithDefaultTimeout() 2191 Expect(kube).Should(Exit(0)) 2192 2193 inspect = podmanTest.Podman([]string{"inspect", BB}) 2194 inspect.WaitWithDefaultTimeout() 2195 newBBinspect := inspect.InspectImageJSON() 2196 Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest))) 2197 }) 2198 2199 It("podman play kube with latest image should always pull", func() { 2200 oldBB := "quay.io/libpod/busybox:1.30.1" 2201 pull := podmanTest.Podman([]string{"pull", oldBB}) 2202 pull.WaitWithDefaultTimeout() 2203 2204 tag := podmanTest.Podman([]string{"tag", oldBB, BB}) 2205 tag.WaitWithDefaultTimeout() 2206 Expect(tag).Should(Exit(0)) 2207 2208 rmi := podmanTest.Podman([]string{"rmi", oldBB}) 2209 rmi.WaitWithDefaultTimeout() 2210 Expect(rmi).Should(Exit(0)) 2211 2212 inspect := podmanTest.Podman([]string{"inspect", BB}) 2213 inspect.WaitWithDefaultTimeout() 2214 oldBBinspect := inspect.InspectImageJSON() 2215 2216 ctr := getCtr(withImage(BB)) 2217 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 2218 Expect(err).To(BeNil()) 2219 2220 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2221 kube.WaitWithDefaultTimeout() 2222 Expect(kube).Should(Exit(0)) 2223 2224 inspect = podmanTest.Podman([]string{"inspect", BB}) 2225 inspect.WaitWithDefaultTimeout() 2226 newBBinspect := inspect.InspectImageJSON() 2227 Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest))) 2228 }) 2229 2230 It("podman play kube with image data", func() { 2231 testyaml := ` 2232 apiVersion: v1 2233 kind: Pod 2234 metadata: 2235 name: demo_pod 2236 spec: 2237 containers: 2238 - image: demo 2239 name: demo_kube 2240 ` 2241 pull := podmanTest.Podman([]string{"create", "--workdir", "/etc", "--name", "newBB", "--label", "key1=value1", "alpine"}) 2242 2243 pull.WaitWithDefaultTimeout() 2244 Expect(pull).Should(Exit(0)) 2245 2246 c := podmanTest.Podman([]string{"commit", "-c", "STOPSIGNAL=51", "newBB", "demo"}) 2247 c.WaitWithDefaultTimeout() 2248 Expect(c).Should(Exit(0)) 2249 2250 conffile := filepath.Join(podmanTest.TempDir, "kube.yaml") 2251 tempdir, err = CreateTempDirInTempDir() 2252 Expect(err).To(BeNil()) 2253 2254 err := ioutil.WriteFile(conffile, []byte(testyaml), 0755) 2255 Expect(err).To(BeNil()) 2256 2257 kube := podmanTest.Podman([]string{"play", "kube", conffile}) 2258 kube.WaitWithDefaultTimeout() 2259 Expect(kube).Should(Exit(0)) 2260 2261 inspect := podmanTest.Podman([]string{"inspect", "demo_pod-demo_kube"}) 2262 inspect.WaitWithDefaultTimeout() 2263 Expect(inspect).Should(Exit(0)) 2264 2265 ctr := inspect.InspectContainerToJSON() 2266 Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc")) 2267 Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1"))) 2268 Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1"))) 2269 Expect(ctr[0].Config).To(HaveField("StopSignal", uint(51))) 2270 }) 2271 2272 // Deployment related tests 2273 It("podman play kube deployment 1 replica test correct command", func() { 2274 deployment := getDeployment() 2275 err := generateKubeYaml("deployment", deployment, kubeYaml) 2276 Expect(err).To(BeNil()) 2277 2278 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2279 kube.WaitWithDefaultTimeout() 2280 Expect(kube).Should(Exit(0)) 2281 2282 podNames := getPodNamesInDeployment(deployment) 2283 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[0]), "--format", "'{{ .Config.Entrypoint }}'"}) 2284 inspect.WaitWithDefaultTimeout() 2285 Expect(inspect).Should(Exit(0)) 2286 // yaml's command should override the image's Entrypoint 2287 Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 2288 }) 2289 2290 It("podman play kube deployment more than 1 replica test correct command", func() { 2291 var i, numReplicas int32 2292 numReplicas = 5 2293 deployment := getDeployment(withReplicas(numReplicas)) 2294 err := generateKubeYaml("deployment", deployment, kubeYaml) 2295 Expect(err).To(BeNil()) 2296 2297 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2298 kube.WaitWithDefaultTimeout() 2299 Expect(kube).Should(Exit(0)) 2300 2301 podNames := getPodNamesInDeployment(deployment) 2302 for i = 0; i < numReplicas; i++ { 2303 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "'{{ .Config.Entrypoint }}'"}) 2304 inspect.WaitWithDefaultTimeout() 2305 Expect(inspect).Should(Exit(0)) 2306 Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 2307 } 2308 }) 2309 2310 It("podman play kube --ip and --mac-address", func() { 2311 var i, numReplicas int32 2312 numReplicas = 3 2313 deployment := getDeployment(withReplicas(numReplicas)) 2314 err := generateKubeYaml("deployment", deployment, kubeYaml) 2315 Expect(err).To(BeNil()) 2316 2317 net := "playkube" + stringid.GenerateNonCryptoID() 2318 session := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.31.0/24", net}) 2319 session.WaitWithDefaultTimeout() 2320 defer podmanTest.removeNetwork(net) 2321 Expect(session).Should(Exit(0)) 2322 2323 ips := []string{"10.25.31.5", "10.25.31.10", "10.25.31.15"} 2324 playArgs := []string{"play", "kube", "--network", net} 2325 for _, ip := range ips { 2326 playArgs = append(playArgs, "--ip", ip) 2327 } 2328 macs := []string{"e8:d8:82:c9:80:40", "e8:d8:82:c9:80:50", "e8:d8:82:c9:80:60"} 2329 for _, mac := range macs { 2330 playArgs = append(playArgs, "--mac-address", mac) 2331 } 2332 2333 kube := podmanTest.Podman(append(playArgs, kubeYaml)) 2334 kube.WaitWithDefaultTimeout() 2335 Expect(kube).Should(Exit(0)) 2336 2337 podNames := getPodNamesInDeployment(deployment) 2338 for i = 0; i < numReplicas; i++ { 2339 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "{{ .NetworkSettings.Networks." + net + ".IPAddress }}"}) 2340 inspect.WaitWithDefaultTimeout() 2341 Expect(inspect).Should(Exit(0)) 2342 Expect(inspect.OutputToString()).To(Equal(ips[i])) 2343 } 2344 2345 for i = 0; i < numReplicas; i++ { 2346 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "{{ .NetworkSettings.Networks." + net + ".MacAddress }}"}) 2347 inspect.WaitWithDefaultTimeout() 2348 Expect(inspect).Should(Exit(0)) 2349 Expect(inspect.OutputToString()).To(Equal(macs[i])) 2350 } 2351 }) 2352 2353 It("podman play kube with multiple networks", func() { 2354 ctr := getCtr(withImage(ALPINE)) 2355 pod := getPod(withCtr(ctr)) 2356 err := generateKubeYaml("pod", pod, kubeYaml) 2357 Expect(err).To(BeNil()) 2358 2359 net1 := "net1" + stringid.GenerateNonCryptoID() 2360 net2 := "net2" + stringid.GenerateNonCryptoID() 2361 2362 net := podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.11.0/24", net1}) 2363 net.WaitWithDefaultTimeout() 2364 defer podmanTest.removeNetwork(net1) 2365 Expect(net).Should(Exit(0)) 2366 2367 net = podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.12.0/24", net2}) 2368 net.WaitWithDefaultTimeout() 2369 defer podmanTest.removeNetwork(net2) 2370 Expect(net).Should(Exit(0)) 2371 2372 ip1 := "10.0.11.5" 2373 ip2 := "10.0.12.10" 2374 2375 kube := podmanTest.Podman([]string{"play", "kube", "--network", net1 + ":ip=" + ip1, "--network", net2 + ":ip=" + ip2, kubeYaml}) 2376 kube.WaitWithDefaultTimeout() 2377 Expect(kube).Should(Exit(0)) 2378 2379 inspect := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "ip", "addr"}) 2380 inspect.WaitWithDefaultTimeout() 2381 Expect(inspect).Should(Exit(0)) 2382 Expect(inspect.OutputToString()).To(ContainSubstring(ip1)) 2383 Expect(inspect.OutputToString()).To(ContainSubstring(ip2)) 2384 Expect(inspect.OutputToString()).To(ContainSubstring("eth0")) 2385 Expect(inspect.OutputToString()).To(ContainSubstring("eth1")) 2386 }) 2387 2388 It("podman play kube test with network portbindings", func() { 2389 ip := "127.0.0.100" 2390 port := "5000" 2391 ctr := getCtr(withHostIP(ip, port), withImage(BB)) 2392 2393 pod := getPod(withCtr(ctr)) 2394 err := generateKubeYaml("pod", pod, kubeYaml) 2395 Expect(err).To(BeNil()) 2396 2397 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2398 kube.WaitWithDefaultTimeout() 2399 Expect(kube).Should(Exit(0)) 2400 2401 inspect := podmanTest.Podman([]string{"port", getCtrNameInPod(pod)}) 2402 inspect.WaitWithDefaultTimeout() 2403 Expect(inspect).Should(Exit(0)) 2404 Expect(inspect.OutputToString()).To(Equal("5000/tcp -> 127.0.0.100:5000")) 2405 }) 2406 2407 It("podman play kube test with nonexistent empty HostPath type volume", func() { 2408 hostPathLocation := filepath.Join(tempdir, "file") 2409 2410 pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation))) 2411 err := generateKubeYaml("pod", pod, kubeYaml) 2412 Expect(err).To(BeNil()) 2413 2414 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2415 kube.WaitWithDefaultTimeout() 2416 Expect(kube).To(ExitWithError()) 2417 Expect(kube.ErrorToString()).To(ContainSubstring(defaultVolName)) 2418 }) 2419 2420 It("podman play kube test with empty HostPath type volume", func() { 2421 hostPathLocation := filepath.Join(tempdir, "file") 2422 f, err := os.Create(hostPathLocation) 2423 Expect(err).To(BeNil()) 2424 f.Close() 2425 2426 pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation))) 2427 err = generateKubeYaml("pod", pod, kubeYaml) 2428 Expect(err).To(BeNil()) 2429 2430 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2431 kube.WaitWithDefaultTimeout() 2432 Expect(kube).Should(Exit(0)) 2433 }) 2434 2435 It("podman play kube test with nonexistent File HostPath type volume", func() { 2436 hostPathLocation := filepath.Join(tempdir, "file") 2437 2438 pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation))) 2439 err := generateKubeYaml("pod", pod, kubeYaml) 2440 Expect(err).To(BeNil()) 2441 2442 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2443 kube.WaitWithDefaultTimeout() 2444 Expect(kube).To(ExitWithError()) 2445 }) 2446 2447 It("podman play kube test with File HostPath type volume", func() { 2448 hostPathLocation := filepath.Join(tempdir, "file") 2449 f, err := os.Create(hostPathLocation) 2450 Expect(err).To(BeNil()) 2451 f.Close() 2452 2453 pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation))) 2454 err = generateKubeYaml("pod", pod, kubeYaml) 2455 Expect(err).To(BeNil()) 2456 2457 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2458 kube.WaitWithDefaultTimeout() 2459 Expect(kube).Should(Exit(0)) 2460 }) 2461 2462 It("podman play kube test with FileOrCreate HostPath type volume", func() { 2463 hostPathLocation := filepath.Join(tempdir, "file") 2464 2465 pod := getPod(withVolume(getHostPathVolume("FileOrCreate", hostPathLocation))) 2466 err := generateKubeYaml("pod", pod, kubeYaml) 2467 Expect(err).To(BeNil()) 2468 2469 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2470 kube.WaitWithDefaultTimeout() 2471 Expect(kube).Should(Exit(0)) 2472 2473 // the file should have been created 2474 _, err = os.Stat(hostPathLocation) 2475 Expect(err).To(BeNil()) 2476 }) 2477 2478 It("podman play kube test with DirectoryOrCreate HostPath type volume", func() { 2479 hostPathLocation := filepath.Join(tempdir, "file") 2480 2481 pod := getPod(withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation))) 2482 err := generateKubeYaml("pod", pod, kubeYaml) 2483 Expect(err).To(BeNil()) 2484 2485 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2486 kube.WaitWithDefaultTimeout() 2487 Expect(kube).Should(Exit(0)) 2488 2489 // the file should have been created 2490 st, err := os.Stat(hostPathLocation) 2491 Expect(err).To(BeNil()) 2492 Expect(st.Mode().IsDir()).To(Equal(true)) 2493 }) 2494 2495 It("podman play kube test with Socket HostPath type volume should fail if not socket", func() { 2496 hostPathLocation := filepath.Join(tempdir, "file") 2497 f, err := os.Create(hostPathLocation) 2498 Expect(err).To(BeNil()) 2499 f.Close() 2500 2501 pod := getPod(withVolume(getHostPathVolume("Socket", hostPathLocation))) 2502 err = generateKubeYaml("pod", pod, kubeYaml) 2503 Expect(err).To(BeNil()) 2504 2505 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2506 kube.WaitWithDefaultTimeout() 2507 Expect(kube).To(ExitWithError()) 2508 }) 2509 2510 It("podman play kube test with read only HostPath volume", func() { 2511 hostPathLocation := filepath.Join(tempdir, "file") 2512 f, err := os.Create(hostPathLocation) 2513 Expect(err).To(BeNil()) 2514 f.Close() 2515 2516 ctr := getCtr(withVolumeMount(hostPathLocation, true), withImage(BB)) 2517 pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)), withCtr(ctr)) 2518 err = generateKubeYaml("pod", pod, kubeYaml) 2519 Expect(err).To(BeNil()) 2520 2521 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2522 kube.WaitWithDefaultTimeout() 2523 Expect(kube).Should(Exit(0)) 2524 2525 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{.HostConfig.Binds}}'"}) 2526 inspect.WaitWithDefaultTimeout() 2527 Expect(inspect).Should(Exit(0)) 2528 2529 correct := fmt.Sprintf("%s:%s:%s", hostPathLocation, hostPathLocation, "ro") 2530 Expect(inspect.OutputToString()).To(ContainSubstring(correct)) 2531 }) 2532 2533 It("podman play kube test duplicate volume destination between host path and image volumes", func() { 2534 // Create host test directory and file 2535 testdir := "testdir" 2536 testfile := "testfile" 2537 2538 hostPathDir := filepath.Join(tempdir, testdir) 2539 err := os.Mkdir(hostPathDir, 0755) 2540 Expect(err).To(BeNil()) 2541 2542 hostPathDirFile := filepath.Join(hostPathDir, testfile) 2543 f, err := os.Create(hostPathDirFile) 2544 Expect(err).To(BeNil()) 2545 f.Close() 2546 2547 // Create container image with named volume 2548 containerfile := fmt.Sprintf(` 2549 FROM %s 2550 VOLUME %s`, ALPINE, hostPathDir+"/") 2551 2552 image := "podman-kube-test:podman" 2553 podmanTest.BuildImage(containerfile, image, "false") 2554 2555 // Create and play kube pod 2556 ctr := getCtr(withVolumeMount(hostPathDir+"/", false), withImage(image)) 2557 pod := getPod(withCtr(ctr), withVolume(getHostPathVolume("Directory", hostPathDir+"/"))) 2558 err = generateKubeYaml("pod", pod, kubeYaml) 2559 Expect(err).To(BeNil()) 2560 2561 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2562 kube.WaitWithDefaultTimeout() 2563 Expect(kube).Should(Exit(0)) 2564 2565 result := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "ls", hostPathDir + "/" + testfile}) 2566 result.WaitWithDefaultTimeout() 2567 Expect(result).Should(Exit(0)) 2568 2569 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 2570 inspect.WaitWithDefaultTimeout() 2571 Expect(inspect).Should(Exit(0)) 2572 2573 // If two volumes are specified and share the same destination, 2574 // only one will be mounted. Host path volumes take precedence. 2575 ctrJSON := inspect.InspectContainerToJSON() 2576 Expect(ctrJSON[0].Mounts).To(HaveLen(1)) 2577 Expect(ctrJSON[0].Mounts[0]).To(HaveField("Type", "bind")) 2578 2579 }) 2580 2581 It("podman play kube test with PersistentVolumeClaim volume", func() { 2582 volumeName := "namedVolume" 2583 2584 ctr := getCtr(withVolumeMount("/test", false), withImage(BB)) 2585 pod := getPod(withVolume(getPersistentVolumeClaimVolume(volumeName)), withCtr(ctr)) 2586 err = generateKubeYaml("pod", pod, kubeYaml) 2587 Expect(err).To(BeNil()) 2588 2589 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2590 kube.WaitWithDefaultTimeout() 2591 Expect(kube).Should(Exit(0)) 2592 2593 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"}) 2594 inspect.WaitWithDefaultTimeout() 2595 Expect(inspect).Should(Exit(0)) 2596 2597 correct := fmt.Sprintf("volume:%s", volumeName) 2598 Expect(inspect.OutputToString()).To(Equal(correct)) 2599 }) 2600 2601 It("podman play kube ConfigMap volume with no items", func() { 2602 volumeName := "cmVol" 2603 cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar")) 2604 cmYaml, err := getKubeYaml("configmap", cm) 2605 Expect(err).To(BeNil()) 2606 2607 ctr := getCtr(withVolumeMount("/test", false), withImage(BB)) 2608 pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, false)), withCtr(ctr)) 2609 podYaml, err := getKubeYaml("pod", pod) 2610 Expect(err).To(BeNil()) 2611 yamls := []string{cmYaml, podYaml} 2612 err = generateMultiDocKubeYaml(yamls, kubeYaml) 2613 Expect(err).To(BeNil()) 2614 2615 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2616 kube.WaitWithDefaultTimeout() 2617 Expect(kube).Should(Exit(0)) 2618 2619 cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 2620 cmData.WaitWithDefaultTimeout() 2621 Expect(cmData).Should(Exit(0)) 2622 Expect(cmData.OutputToString()).To(Equal("foobar")) 2623 }) 2624 2625 It("podman play kube ConfigMap volume with items", func() { 2626 volumeName := "cmVol" 2627 cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar")) 2628 cmYaml, err := getKubeYaml("configmap", cm) 2629 Expect(err).To(BeNil()) 2630 volumeContents := []map[string]string{{ 2631 "key": "FOO", 2632 "path": "BAR", 2633 }} 2634 2635 ctr := getCtr(withVolumeMount("/test", false), withImage(BB)) 2636 pod := getPod(withVolume(getConfigMapVolume(volumeName, volumeContents, false)), withCtr(ctr)) 2637 podYaml, err := getKubeYaml("pod", pod) 2638 Expect(err).To(BeNil()) 2639 yamls := []string{cmYaml, podYaml} 2640 err = generateMultiDocKubeYaml(yamls, kubeYaml) 2641 Expect(err).To(BeNil()) 2642 2643 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2644 kube.WaitWithDefaultTimeout() 2645 Expect(kube).Should(Exit(0)) 2646 2647 cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/BAR"}) 2648 cmData.WaitWithDefaultTimeout() 2649 Expect(cmData).Should(Exit(0)) 2650 Expect(cmData.OutputToString()).To(Equal("foobar")) 2651 2652 cmData = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 2653 cmData.WaitWithDefaultTimeout() 2654 Expect(cmData).Should(Not(Exit(0))) 2655 }) 2656 2657 It("podman play kube with a missing optional ConfigMap volume", func() { 2658 volumeName := "cmVol" 2659 2660 ctr := getCtr(withVolumeMount("/test", false), withImage(BB)) 2661 pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, true)), withCtr(ctr)) 2662 err = generateKubeYaml("pod", pod, kubeYaml) 2663 Expect(err).To(BeNil()) 2664 2665 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2666 kube.WaitWithDefaultTimeout() 2667 Expect(kube).Should(Exit(0)) 2668 }) 2669 2670 It("podman play kube applies labels to pods", func() { 2671 var numReplicas int32 = 5 2672 expectedLabelKey := "key1" 2673 expectedLabelValue := "value1" 2674 deployment := getDeployment( 2675 withReplicas(numReplicas), 2676 withPod(getPod(withLabel(expectedLabelKey, expectedLabelValue))), 2677 ) 2678 err := generateKubeYaml("deployment", deployment, kubeYaml) 2679 Expect(err).To(BeNil()) 2680 2681 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2682 kube.WaitWithDefaultTimeout() 2683 Expect(kube).Should(Exit(0)) 2684 2685 correctLabels := expectedLabelKey + ":" + expectedLabelValue 2686 for _, pod := range getPodNamesInDeployment(deployment) { 2687 inspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{ .Labels }}'"}) 2688 inspect.WaitWithDefaultTimeout() 2689 Expect(inspect).Should(Exit(0)) 2690 Expect(inspect.OutputToString()).To(ContainSubstring(correctLabels)) 2691 } 2692 }) 2693 2694 It("podman play kube allows setting resource limits", func() { 2695 SkipIfContainerized("Resource limits require a running systemd") 2696 SkipIfRootless("CPU limits require root") 2697 podmanTest.CgroupManager = "systemd" 2698 2699 var ( 2700 numReplicas int32 = 3 2701 expectedCPURequest string = "100m" 2702 expectedCPULimit string = "200m" 2703 expectedMemoryRequest string = "10000000" 2704 expectedMemoryLimit string = "20000000" 2705 ) 2706 2707 expectedCPUQuota := milliCPUToQuota(expectedCPULimit) 2708 2709 deployment := getDeployment( 2710 withReplicas(numReplicas), 2711 withPod(getPod(withCtr(getCtr( 2712 withCPURequest(expectedCPURequest), 2713 withCPULimit(expectedCPULimit), 2714 withMemoryRequest(expectedMemoryRequest), 2715 withMemoryLimit(expectedMemoryLimit), 2716 ))))) 2717 err := generateKubeYaml("deployment", deployment, kubeYaml) 2718 Expect(err).To(BeNil()) 2719 2720 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2721 kube.WaitWithDefaultTimeout() 2722 Expect(kube).Should(Exit(0)) 2723 2724 for _, pod := range getPodNamesInDeployment(deployment) { 2725 pod := pod // copy into local scope 2726 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", ` 2727 CpuPeriod: {{ .HostConfig.CpuPeriod }} 2728 CpuQuota: {{ .HostConfig.CpuQuota }} 2729 Memory: {{ .HostConfig.Memory }} 2730 MemoryReservation: {{ .HostConfig.MemoryReservation }}`}) 2731 inspect.WaitWithDefaultTimeout() 2732 Expect(inspect).Should(Exit(0)) 2733 Expect(inspect.OutputToString()).To(ContainSubstring(fmt.Sprintf("%s: %d", "CpuQuota", expectedCPUQuota))) 2734 Expect(inspect.OutputToString()).To(ContainSubstring("MemoryReservation: " + expectedMemoryRequest)) 2735 Expect(inspect.OutputToString()).To(ContainSubstring("Memory: " + expectedMemoryLimit)) 2736 } 2737 }) 2738 2739 It("podman play kube allows setting resource limits with --cpus 1", func() { 2740 SkipIfContainerized("Resource limits require a running systemd") 2741 SkipIfRootless("CPU limits require root") 2742 podmanTest.CgroupManager = "systemd" 2743 2744 var ( 2745 expectedCPULimit string = "1" 2746 ) 2747 2748 deployment := getDeployment( 2749 withPod(getPod(withCtr(getCtr( 2750 withCPULimit(expectedCPULimit), 2751 ))))) 2752 err := generateKubeYaml("deployment", deployment, kubeYaml) 2753 Expect(err).To(BeNil()) 2754 2755 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2756 kube.WaitWithDefaultTimeout() 2757 Expect(kube).Should(Exit(0)) 2758 2759 for _, pod := range getPodNamesInDeployment(deployment) { 2760 pod := pod // copy into local scope 2761 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", `{{ .HostConfig.CpuPeriod }}:{{ .HostConfig.CpuQuota }}`}) 2762 2763 inspect.WaitWithDefaultTimeout() 2764 Expect(inspect).Should(Exit(0)) 2765 2766 parts := strings.Split(strings.Trim(inspect.OutputToString(), "\n"), ":") 2767 Expect(parts).To(HaveLen(2)) 2768 2769 Expect(parts[0]).To(Equal(parts[1])) 2770 } 2771 }) 2772 2773 It("podman play kube reports invalid image name", func() { 2774 invalidImageName := "./myimage" 2775 2776 pod := getPod( 2777 withCtr( 2778 getCtr( 2779 withImage(invalidImageName), 2780 ), 2781 ), 2782 ) 2783 err := generateKubeYaml("pod", pod, kubeYaml) 2784 Expect(err).To(BeNil()) 2785 2786 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2787 kube.WaitWithDefaultTimeout() 2788 Expect(kube).Should(Exit(125)) 2789 Expect(kube.ErrorToString()).To(ContainSubstring("invalid reference format")) 2790 }) 2791 2792 It("podman play kube applies log driver to containers", func() { 2793 SkipIfInContainer("journald inside a container doesn't work") 2794 pod := getPod() 2795 err := generateKubeYaml("pod", pod, kubeYaml) 2796 Expect(err).To(BeNil()) 2797 2798 kube := podmanTest.Podman([]string{"play", "kube", "--log-opt=max-size=10k", "--log-driver", "journald", kubeYaml}) 2799 kube.WaitWithDefaultTimeout() 2800 Expect(kube).Should(Exit(0)) 2801 2802 cid := getCtrNameInPod(pod) 2803 inspect := podmanTest.Podman([]string{"inspect", cid, "--format", "'{{ .HostConfig.LogConfig.Type }}'"}) 2804 inspect.WaitWithDefaultTimeout() 2805 Expect(inspect).Should(Exit(0)) 2806 Expect(inspect.OutputToString()).To(ContainSubstring("journald")) 2807 inspect = podmanTest.Podman([]string{"container", "inspect", "--format", "{{.HostConfig.LogConfig.Size}}", cid}) 2808 inspect.WaitWithDefaultTimeout() 2809 Expect(inspect).To(Exit(0)) 2810 Expect(inspect.OutputToString()).To(Equal("10kB")) 2811 }) 2812 2813 It("podman play kube test only creating the containers", func() { 2814 pod := getPod() 2815 err := generateKubeYaml("pod", pod, kubeYaml) 2816 Expect(err).To(BeNil()) 2817 2818 kube := podmanTest.Podman([]string{"play", "kube", "--start=false", kubeYaml}) 2819 kube.WaitWithDefaultTimeout() 2820 Expect(kube).Should(Exit(0)) 2821 2822 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .State.Running }}"}) 2823 inspect.WaitWithDefaultTimeout() 2824 Expect(inspect).Should(Exit(0)) 2825 Expect(inspect.OutputToString()).To(Equal("false")) 2826 }) 2827 2828 It("podman play kube test with HostNetwork", func() { 2829 pod := getPod(withHostNetwork(), withCtr(getCtr(withCmd([]string{"readlink", "/proc/self/ns/net"}), withArg(nil)))) 2830 err := generateKubeYaml("pod", pod, kubeYaml) 2831 Expect(err).To(BeNil()) 2832 2833 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2834 kube.WaitWithDefaultTimeout() 2835 Expect(kube).Should(Exit(0)) 2836 2837 inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.HostNetwork }}"}) 2838 inspect.WaitWithDefaultTimeout() 2839 Expect(inspect).Should(Exit(0)) 2840 Expect(inspect.OutputToString()).To(Equal("true")) 2841 2842 ns := SystemExec("readlink", []string{"/proc/self/ns/net"}) 2843 ns.WaitWithDefaultTimeout() 2844 Expect(ns).Should(Exit(0)) 2845 netns := ns.OutputToString() 2846 Expect(netns).ToNot(BeEmpty()) 2847 2848 logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)}) 2849 logs.WaitWithDefaultTimeout() 2850 Expect(logs).Should(Exit(0)) 2851 Expect(logs.OutputToString()).To(Equal(netns)) 2852 }) 2853 2854 It("podman play kube persistentVolumeClaim", func() { 2855 volName := "myvol" 2856 volDevice := "tmpfs" 2857 volType := "tmpfs" 2858 volOpts := "nodev,noexec" 2859 2860 pvc := getPVC(withPVCName(volName), 2861 withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice), 2862 withPVCAnnotations(util.VolumeTypeAnnotation, volType), 2863 withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts)) 2864 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 2865 Expect(err).To(BeNil()) 2866 2867 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2868 kube.WaitWithDefaultTimeout() 2869 Expect(kube).Should(Exit(0)) 2870 2871 inspect := podmanTest.Podman([]string{"inspect", volName, "--format", ` 2872 Name: {{ .Name }} 2873 Device: {{ .Options.device }} 2874 Type: {{ .Options.type }} 2875 o: {{ .Options.o }}`}) 2876 inspect.WaitWithDefaultTimeout() 2877 Expect(inspect).Should(Exit(0)) 2878 Expect(inspect.OutputToString()).To(ContainSubstring("Name: " + volName)) 2879 Expect(inspect.OutputToString()).To(ContainSubstring("Device: " + volDevice)) 2880 Expect(inspect.OutputToString()).To(ContainSubstring("Type: " + volType)) 2881 Expect(inspect.OutputToString()).To(ContainSubstring("o: " + volOpts)) 2882 }) 2883 2884 // Multi doc related tests 2885 It("podman play kube multi doc yaml with persistentVolumeClaim, service and deployment", func() { 2886 yamlDocs := []string{} 2887 2888 serviceTemplate := `apiVersion: v1 2889 kind: Service 2890 metadata: 2891 name: %s 2892 spec: 2893 ports: 2894 - port: 80 2895 protocol: TCP 2896 targetPort: 9376 2897 selector: 2898 app: %s 2899 ` 2900 // generate persistentVolumeClaim 2901 volName := "multiFoo" 2902 pvc := getPVC(withPVCName(volName)) 2903 2904 // generate deployment 2905 deploymentName := "multiFoo" 2906 podName := "multiFoo" 2907 ctrName := "ctr-01" 2908 ctr := getCtr(withVolumeMount("/test", false)) 2909 ctr.Name = ctrName 2910 pod := getPod(withPodName(podName), withVolume(getPersistentVolumeClaimVolume(volName)), withCtr(ctr)) 2911 deployment := getDeployment(withPod(pod)) 2912 deployment.Name = deploymentName 2913 2914 // add pvc 2915 k, err := getKubeYaml("persistentVolumeClaim", pvc) 2916 Expect(err).To(BeNil()) 2917 yamlDocs = append(yamlDocs, k) 2918 2919 // add service 2920 yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, deploymentName, deploymentName)) 2921 2922 // add deployment 2923 k, err = getKubeYaml("deployment", deployment) 2924 Expect(err).To(BeNil()) 2925 yamlDocs = append(yamlDocs, k) 2926 2927 // generate multi doc yaml 2928 err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) 2929 Expect(err).To(BeNil()) 2930 2931 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2932 kube.WaitWithDefaultTimeout() 2933 Expect(kube).Should(Exit(0)) 2934 2935 inspectVolume := podmanTest.Podman([]string{"inspect", volName, "--format", "'{{ .Name }}'"}) 2936 inspectVolume.WaitWithDefaultTimeout() 2937 Expect(inspectVolume).Should(Exit(0)) 2938 Expect(inspectVolume.OutputToString()).To(ContainSubstring(volName)) 2939 2940 inspectPod := podmanTest.Podman([]string{"inspect", podName + "-pod-0", "--format", "'{{ .State }}'"}) 2941 inspectPod.WaitWithDefaultTimeout() 2942 Expect(inspectPod).Should(Exit(0)) 2943 Expect(inspectPod.OutputToString()).To(ContainSubstring(`Running`)) 2944 2945 inspectMounts := podmanTest.Podman([]string{"inspect", podName + "-pod-0-" + ctrName, "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"}) 2946 inspectMounts.WaitWithDefaultTimeout() 2947 Expect(inspectMounts).Should(Exit(0)) 2948 2949 correct := fmt.Sprintf("volume:%s", volName) 2950 Expect(inspectMounts.OutputToString()).To(Equal(correct)) 2951 }) 2952 2953 It("podman play kube multi doc yaml with multiple services, pods and deployments", func() { 2954 yamlDocs := []string{} 2955 podNames := []string{} 2956 2957 serviceTemplate := `apiVersion: v1 2958 kind: Service 2959 metadata: 2960 name: %s 2961 spec: 2962 ports: 2963 - port: 80 2964 protocol: TCP 2965 targetPort: 9376 2966 selector: 2967 app: %s 2968 ` 2969 // generate services, pods and deployments 2970 for i := 0; i < 2; i++ { 2971 podName := fmt.Sprintf("testPod%d", i) 2972 deploymentName := fmt.Sprintf("testDeploy%d", i) 2973 deploymentPodName := fmt.Sprintf("%s-pod-0", deploymentName) 2974 2975 podNames = append(podNames, podName) 2976 podNames = append(podNames, deploymentPodName) 2977 2978 pod := getPod(withPodName(podName)) 2979 podDeployment := getPod(withPodName(deploymentName)) 2980 deployment := getDeployment(withPod(podDeployment)) 2981 deployment.Name = deploymentName 2982 2983 // add services 2984 yamlDocs = append([]string{ 2985 fmt.Sprintf(serviceTemplate, podName, podName), 2986 fmt.Sprintf(serviceTemplate, deploymentPodName, deploymentPodName)}, yamlDocs...) 2987 2988 // add pods 2989 k, err := getKubeYaml("pod", pod) 2990 Expect(err).To(BeNil()) 2991 yamlDocs = append(yamlDocs, k) 2992 2993 // add deployments 2994 k, err = getKubeYaml("deployment", deployment) 2995 Expect(err).To(BeNil()) 2996 yamlDocs = append(yamlDocs, k) 2997 } 2998 2999 // generate multi doc yaml 3000 err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) 3001 Expect(err).To(BeNil()) 3002 3003 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3004 kube.WaitWithDefaultTimeout() 3005 Expect(kube).Should(Exit(0)) 3006 3007 for _, n := range podNames { 3008 inspect := podmanTest.Podman([]string{"inspect", n, "--format", "'{{ .State }}'"}) 3009 inspect.WaitWithDefaultTimeout() 3010 Expect(inspect).Should(Exit(0)) 3011 Expect(inspect.OutputToString()).To(ContainSubstring(`Running`)) 3012 } 3013 }) 3014 3015 It("podman play kube invalid multi doc yaml", func() { 3016 yamlDocs := []string{} 3017 3018 serviceTemplate := `apiVersion: v1 3019 kind: Service 3020 metadata: 3021 name: %s 3022 spec: 3023 ports: 3024 - port: 80 3025 protocol: TCP 3026 targetPort: 9376 3027 selector: 3028 app: %s 3029 --- 3030 invalid kube kind 3031 ` 3032 // add invalid multi doc yaml 3033 yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, "foo", "foo")) 3034 3035 // add pod 3036 pod := getPod() 3037 k, err := getKubeYaml("pod", pod) 3038 Expect(err).To(BeNil()) 3039 yamlDocs = append(yamlDocs, k) 3040 3041 // generate multi doc yaml 3042 err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) 3043 Expect(err).To(BeNil()) 3044 3045 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3046 kube.WaitWithDefaultTimeout() 3047 Expect(kube).To(ExitWithError()) 3048 }) 3049 3050 It("podman play kube with auto update annotations for all containers", func() { 3051 ctr01Name := "ctr01" 3052 ctr02Name := "infra" 3053 podName := "foo" 3054 autoUpdateRegistry := "io.containers.autoupdate" 3055 autoUpdateRegistryValue := "registry" 3056 autoUpdateAuthfile := "io.containers.autoupdate.authfile" 3057 autoUpdateAuthfileValue := "/some/authfile.json" 3058 3059 ctr01 := getCtr(withName(ctr01Name)) 3060 ctr02 := getCtr(withName(ctr02Name)) 3061 3062 pod := getPod( 3063 withPodName(podName), 3064 withCtr(ctr01), 3065 withCtr(ctr02), 3066 withAnnotation(autoUpdateRegistry, autoUpdateRegistryValue), 3067 withAnnotation(autoUpdateAuthfile, autoUpdateAuthfileValue)) 3068 3069 err = generateKubeYaml("pod", pod, kubeYaml) 3070 Expect(err).To(BeNil()) 3071 3072 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3073 kube.WaitWithDefaultTimeout() 3074 Expect(kube).Should(Exit(0)) 3075 3076 for _, ctr := range []string{podName + "-" + ctr01Name, podName + "-" + ctr02Name} { 3077 inspect := podmanTest.Podman([]string{"inspect", ctr, "--format", "'{{.Config.Labels}}'"}) 3078 inspect.WaitWithDefaultTimeout() 3079 Expect(inspect).Should(Exit(0)) 3080 3081 Expect(inspect.OutputToString()).To(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) 3082 Expect(inspect.OutputToString()).To(ContainSubstring(autoUpdateAuthfile + ":" + autoUpdateAuthfileValue)) 3083 } 3084 }) 3085 3086 It("podman play kube with auto update annotations for first container only", func() { 3087 ctr01Name := "ctr01" 3088 ctr02Name := "ctr02" 3089 autoUpdateRegistry := "io.containers.autoupdate" 3090 autoUpdateRegistryValue := "local" 3091 3092 ctr01 := getCtr(withName(ctr01Name)) 3093 ctr02 := getCtr(withName(ctr02Name)) 3094 3095 pod := getPod( 3096 withCtr(ctr01), 3097 withCtr(ctr02), 3098 ) 3099 3100 deployment := getDeployment( 3101 withPod(pod), 3102 withDeploymentAnnotation(autoUpdateRegistry+"/"+ctr01Name, autoUpdateRegistryValue), 3103 ) 3104 3105 err = generateKubeYaml("deployment", deployment, kubeYaml) 3106 Expect(err).To(BeNil()) 3107 3108 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3109 kube.WaitWithDefaultTimeout() 3110 Expect(kube).Should(Exit(0)) 3111 3112 podName := getPodNamesInDeployment(deployment)[0].Name 3113 3114 inspect := podmanTest.Podman([]string{"inspect", podName + "-" + ctr01Name, "--format", "'{{.Config.Labels}}'"}) 3115 inspect.WaitWithDefaultTimeout() 3116 Expect(inspect).Should(Exit(0)) 3117 Expect(inspect.OutputToString()).To(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) 3118 3119 inspect = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"}) 3120 inspect.WaitWithDefaultTimeout() 3121 Expect(inspect).Should(Exit(0)) 3122 Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) 3123 }) 3124 3125 It("podman play kube teardown", func() { 3126 pod := getPod() 3127 err := generateKubeYaml("pod", pod, kubeYaml) 3128 Expect(err).To(BeNil()) 3129 3130 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3131 kube.WaitWithDefaultTimeout() 3132 Expect(kube).Should(Exit(0)) 3133 3134 ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 3135 ls.WaitWithDefaultTimeout() 3136 Expect(ls).Should(Exit(0)) 3137 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 3138 3139 // teardown 3140 teardown := podmanTest.Podman([]string{"play", "kube", "--down", kubeYaml}) 3141 teardown.WaitWithDefaultTimeout() 3142 Expect(teardown).Should(Exit(0)) 3143 3144 checkls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 3145 checkls.WaitWithDefaultTimeout() 3146 Expect(checkls).Should(Exit(0)) 3147 Expect(checkls.OutputToStringArray()).To(BeEmpty()) 3148 }) 3149 3150 It("podman play kube teardown pod does not exist", func() { 3151 // teardown 3152 teardown := podmanTest.Podman([]string{"play", "kube", "--down", kubeYaml}) 3153 teardown.WaitWithDefaultTimeout() 3154 Expect(teardown).Should(Exit(125)) 3155 }) 3156 3157 It("podman play kube teardown with volume", func() { 3158 3159 volName := RandomString(12) 3160 volDevice := "tmpfs" 3161 volType := "tmpfs" 3162 volOpts := "nodev,noexec" 3163 3164 pvc := getPVC(withPVCName(volName), 3165 withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice), 3166 withPVCAnnotations(util.VolumeTypeAnnotation, volType), 3167 withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts)) 3168 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 3169 Expect(err).To(BeNil()) 3170 3171 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3172 kube.WaitWithDefaultTimeout() 3173 Expect(kube).Should(Exit(0)) 3174 3175 exists := podmanTest.Podman([]string{"volume", "exists", volName}) 3176 exists.WaitWithDefaultTimeout() 3177 Expect(exists).To(Exit(0)) 3178 3179 teardown := podmanTest.Podman([]string{"play", "kube", "--down", kubeYaml}) 3180 teardown.WaitWithDefaultTimeout() 3181 Expect(teardown).To(Exit(0)) 3182 3183 // volume should not be deleted on teardown 3184 exists = podmanTest.Podman([]string{"volume", "exists", volName}) 3185 exists.WaitWithDefaultTimeout() 3186 Expect(exists).To(Exit(0)) 3187 }) 3188 3189 It("podman play kube use network mode from config", func() { 3190 confPath, err := filepath.Abs("config/containers-netns2.conf") 3191 Expect(err).ToNot(HaveOccurred()) 3192 os.Setenv("CONTAINERS_CONF", confPath) 3193 defer os.Unsetenv("CONTAINERS_CONF") 3194 if IsRemote() { 3195 podmanTest.RestartRemoteService() 3196 } 3197 3198 pod := getPod() 3199 err = generateKubeYaml("pod", pod, kubeYaml) 3200 Expect(err).To(BeNil()) 3201 3202 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3203 kube.WaitWithDefaultTimeout() 3204 Expect(kube).Should(Exit(0)) 3205 3206 podInspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "{{.InfraContainerID}}"}) 3207 podInspect.WaitWithDefaultTimeout() 3208 Expect(podInspect).To(Exit(0)) 3209 infraID := podInspect.OutputToString() 3210 3211 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.NetworkMode}}", infraID}) 3212 inspect.WaitWithDefaultTimeout() 3213 Expect(inspect).To(Exit(0)) 3214 Expect(inspect.OutputToString()).To(Equal("bridge")) 3215 }) 3216 3217 It("podman play kube replace", func() { 3218 pod := getPod() 3219 err := generateKubeYaml("pod", pod, kubeYaml) 3220 Expect(err).To(BeNil()) 3221 3222 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3223 kube.WaitWithDefaultTimeout() 3224 Expect(kube).Should(Exit(0)) 3225 3226 ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 3227 ls.WaitWithDefaultTimeout() 3228 Expect(ls).Should(Exit(0)) 3229 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 3230 3231 containerLen := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "{{len .Containers}}"}) 3232 containerLen.WaitWithDefaultTimeout() 3233 Expect(containerLen).Should(Exit(0)) 3234 Expect(containerLen.OutputToString()).To(Equal("2")) 3235 ctr01Name := "ctr01" 3236 ctr02Name := "ctr02" 3237 3238 ctr01 := getCtr(withName(ctr01Name)) 3239 ctr02 := getCtr(withName(ctr02Name)) 3240 3241 newPod := getPod( 3242 withCtr(ctr01), 3243 withCtr(ctr02), 3244 ) 3245 err = generateKubeYaml("pod", newPod, kubeYaml) 3246 Expect(err).To(BeNil()) 3247 3248 replace := podmanTest.Podman([]string{"play", "kube", "--replace", kubeYaml}) 3249 replace.WaitWithDefaultTimeout() 3250 Expect(replace).Should(Exit(0)) 3251 3252 newContainerLen := podmanTest.Podman([]string{"pod", "inspect", newPod.Name, "--format", "{{len .Containers}}"}) 3253 newContainerLen.WaitWithDefaultTimeout() 3254 Expect(newContainerLen).Should(Exit(0)) 3255 Expect(newContainerLen.OutputToString()).NotTo(Equal(containerLen.OutputToString())) 3256 }) 3257 3258 It("podman play kube replace non-existing pod", func() { 3259 pod := getPod() 3260 err := generateKubeYaml("pod", pod, kubeYaml) 3261 Expect(err).To(BeNil()) 3262 3263 replace := podmanTest.Podman([]string{"play", "kube", "--replace", kubeYaml}) 3264 replace.WaitWithDefaultTimeout() 3265 Expect(replace).Should(Exit(0)) 3266 3267 ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 3268 ls.WaitWithDefaultTimeout() 3269 Expect(ls).Should(Exit(0)) 3270 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 3271 }) 3272 3273 It("podman play kube RunAsUser", func() { 3274 ctr1Name := "ctr1" 3275 ctr2Name := "ctr2" 3276 ctr1 := getCtr(withName(ctr1Name), withSecurityContext(true), withRunAsUser("101"), withRunAsGroup("102")) 3277 ctr2 := getCtr(withName(ctr2Name), withSecurityContext(true)) 3278 3279 pod := getPod( 3280 withCtr(ctr1), 3281 withCtr(ctr2), 3282 withPodSecurityContext(true), 3283 withPodRunAsUser("103"), 3284 withPodRunAsGroup("104"), 3285 ) 3286 3287 err := generateKubeYaml("pod", pod, kubeYaml) 3288 Expect(err).To(BeNil()) 3289 3290 cmd := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3291 cmd.WaitWithDefaultTimeout() 3292 Expect(cmd).Should(Exit(0)) 3293 3294 // we expect the user:group as configured for the container 3295 inspect := podmanTest.Podman([]string{"container", "inspect", "--format", "'{{.Config.User}}'", makeCtrNameInPod(pod, ctr1Name)}) 3296 inspect.WaitWithDefaultTimeout() 3297 Expect(inspect.OutputToString()).To(Equal("'101:102'")) 3298 3299 // we expect the user:group as configured for the pod 3300 inspect = podmanTest.Podman([]string{"container", "inspect", "--format", "'{{.Config.User}}'", makeCtrNameInPod(pod, ctr2Name)}) 3301 inspect.WaitWithDefaultTimeout() 3302 Expect(inspect.OutputToString()).To(Equal("'103:104'")) 3303 }) 3304 3305 Describe("verify environment variables", func() { 3306 var maxLength int 3307 BeforeEach(func() { 3308 maxLength = format.MaxLength 3309 format.MaxLength = 0 3310 }) 3311 AfterEach(func() { 3312 format.MaxLength = maxLength 3313 }) 3314 3315 It("values containing equal sign", func() { 3316 javaToolOptions := `-XX:+IgnoreUnrecognizedVMOptions -XX:+IdleTuningGcOnIdle -Xshareclasses:name=openj9_system_scc,cacheDir=/opt/java/.scc,readonly,nonFatal` 3317 openj9JavaOptions := `-XX:+IgnoreUnrecognizedVMOptions -XX:+IdleTuningGcOnIdle -Xshareclasses:name=openj9_system_scc,cacheDir=/opt/java/.scc,readonly,nonFatal -Dosgi.checkConfiguration=false` 3318 3319 containerfile := fmt.Sprintf(`FROM %s 3320 ENV JAVA_TOOL_OPTIONS=%q 3321 ENV OPENJ9_JAVA_OPTIONS=%q 3322 `, 3323 ALPINE, javaToolOptions, openj9JavaOptions) 3324 3325 image := "podman-kube-test:env" 3326 podmanTest.BuildImage(containerfile, image, "false") 3327 ctnr := getCtr(withImage(image)) 3328 pod := getPod(withCtr(ctnr)) 3329 Expect(generateKubeYaml("pod", pod, kubeYaml)).Should(Succeed()) 3330 3331 play := podmanTest.Podman([]string{"play", "kube", "--start", kubeYaml}) 3332 play.WaitWithDefaultTimeout() 3333 Expect(play).Should(Exit(0)) 3334 3335 inspect := podmanTest.Podman([]string{"container", "inspect", "--format=json", getCtrNameInPod(pod)}) 3336 inspect.WaitWithDefaultTimeout() 3337 Expect(inspect).Should(Exit(0)) 3338 3339 contents := string(inspect.Out.Contents()) 3340 Expect(contents).To(ContainSubstring(javaToolOptions)) 3341 Expect(contents).To(ContainSubstring(openj9JavaOptions)) 3342 }) 3343 }) 3344 3345 Context("with configmap in multi-doc yaml", func() { 3346 It("podman play kube uses env value", func() { 3347 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3348 3349 cmYaml, err := getKubeYaml("configmap", cm) 3350 Expect(err).To(BeNil()) 3351 3352 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 3353 3354 podYaml, err := getKubeYaml("pod", pod) 3355 Expect(err).To(BeNil()) 3356 3357 yamls := []string{cmYaml, podYaml} 3358 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3359 Expect(err).To(BeNil()) 3360 3361 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3362 kube.WaitWithDefaultTimeout() 3363 Expect(kube).Should(Exit(0)) 3364 3365 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 3366 inspect.WaitWithDefaultTimeout() 3367 Expect(inspect).Should(Exit(0)) 3368 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 3369 }) 3370 3371 It("podman play kube fails for required env value with missing key", func() { 3372 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3373 3374 cmYaml, err := getKubeYaml("configmap", cm) 3375 Expect(err).To(BeNil()) 3376 3377 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", false)))) 3378 3379 podYaml, err := getKubeYaml("pod", pod) 3380 Expect(err).To(BeNil()) 3381 3382 yamls := []string{cmYaml, podYaml} 3383 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3384 Expect(err).To(BeNil()) 3385 3386 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3387 kube.WaitWithDefaultTimeout() 3388 Expect(kube).To(ExitWithError()) 3389 }) 3390 3391 It("podman play kube succeeds for optional env value with missing key", func() { 3392 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3393 3394 cmYaml, err := getKubeYaml("configmap", cm) 3395 Expect(err).To(BeNil()) 3396 3397 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", true)))) 3398 3399 podYaml, err := getKubeYaml("pod", pod) 3400 Expect(err).To(BeNil()) 3401 3402 yamls := []string{cmYaml, podYaml} 3403 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3404 Expect(err).To(BeNil()) 3405 3406 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3407 kube.WaitWithDefaultTimeout() 3408 Expect(kube).Should(Exit(0)) 3409 3410 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 3411 inspect.WaitWithDefaultTimeout() 3412 Expect(inspect).Should(Exit(0)) 3413 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 3414 }) 3415 3416 It("podman play kube uses all key-value pairs as envs", func() { 3417 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2")) 3418 cmYaml, err := getKubeYaml("configmap", cm) 3419 Expect(err).To(BeNil()) 3420 3421 pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap", false)))) 3422 3423 podYaml, err := getKubeYaml("pod", pod) 3424 Expect(err).To(BeNil()) 3425 3426 yamls := []string{cmYaml, podYaml} 3427 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3428 Expect(err).To(BeNil()) 3429 3430 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3431 kube.WaitWithDefaultTimeout() 3432 Expect(kube).Should(Exit(0)) 3433 3434 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 3435 inspect.WaitWithDefaultTimeout() 3436 Expect(inspect).Should(Exit(0)) 3437 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`)) 3438 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`)) 3439 }) 3440 3441 It("podman play kube deployment uses variable from config map", func() { 3442 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3443 3444 cmYaml, err := getKubeYaml("configmap", cm) 3445 Expect(err).To(BeNil()) 3446 3447 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 3448 3449 deployment := getDeployment(withPod(pod)) 3450 deploymentYaml, err := getKubeYaml("deployment", deployment) 3451 Expect(err).To(BeNil(), "getKubeYaml(deployment)") 3452 yamls := []string{cmYaml, deploymentYaml} 3453 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3454 Expect(err).To(BeNil()) 3455 3456 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3457 kube.WaitWithDefaultTimeout() 3458 Expect(kube).Should(Exit(0)) 3459 3460 inspect := podmanTest.Podman([]string{"inspect", fmt.Sprintf("%s-%s-%s", deployment.Name, "pod-0", defaultCtrName), "--format", "'{{ .Config }}'"}) 3461 inspect.WaitWithDefaultTimeout() 3462 Expect(inspect).Should(Exit(0)) 3463 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 3464 3465 }) 3466 3467 It("podman play kube uses env value from configmap for HTTP API client", func() { 3468 SkipIfRemote("cannot run in a remote setup") 3469 address := url.URL{ 3470 Scheme: "tcp", 3471 Host: net.JoinHostPort("localhost", randomPort()), 3472 } 3473 3474 session := podmanTest.Podman([]string{ 3475 "system", "service", "--log-level=debug", "--time=0", address.String(), 3476 }) 3477 defer session.Kill() 3478 3479 WaitForService(address) 3480 3481 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3482 cmYaml, err := getKubeYaml("configmap", cm) 3483 Expect(err).To(BeNil()) 3484 3485 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 3486 podYaml, err := getKubeYaml("pod", pod) 3487 Expect(err).To(BeNil()) 3488 yamls := []string{cmYaml, podYaml} 3489 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3490 Expect(err).To(BeNil()) 3491 3492 podmanConnection, err := bindings.NewConnection(context.Background(), address.String()) 3493 Expect(err).ToNot(HaveOccurred()) 3494 3495 _, err = play.Kube(podmanConnection, kubeYaml, nil) 3496 Expect(err).ToNot(HaveOccurred()) 3497 3498 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 3499 inspect.WaitWithDefaultTimeout() 3500 Expect(inspect).Should(Exit(0)) 3501 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 3502 }) 3503 }) 3504 3505 Context("with configmap in multi-doc yaml and files", func() { 3506 It("podman play kube uses env values from both sources", func() { 3507 SkipIfRemote("--configmaps is not supported for remote") 3508 3509 fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 3510 fsCm := getConfigMap(withConfigMapName("fooFs"), withConfigMapData("FOO_FS", "fooFS")) 3511 err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname) 3512 Expect(err).To(BeNil()) 3513 3514 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3515 3516 cmYaml, err := getKubeYaml("configmap", cm) 3517 Expect(err).To(BeNil()) 3518 3519 pod := getPod(withCtr(getCtr( 3520 withEnv("FOO_FS", "", "configmap", "fooFs", "FOO_FS", false), 3521 withEnv("FOO", "", "configmap", "foo", "FOO", false), 3522 ))) 3523 3524 podYaml, err := getKubeYaml("pod", pod) 3525 Expect(err).To(BeNil()) 3526 3527 yamls := []string{cmYaml, podYaml} 3528 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3529 Expect(err).To(BeNil()) 3530 3531 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", fsCmYamlPathname}) 3532 kube.WaitWithDefaultTimeout() 3533 Expect(kube).Should(Exit(0)) 3534 3535 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 3536 inspect.WaitWithDefaultTimeout() 3537 Expect(inspect).Should(Exit(0)) 3538 Expect(inspect.OutputToString()).To(And( 3539 ContainSubstring(`FOO=foo`), 3540 ContainSubstring(`FOO_FS=fooFS`), 3541 )) 3542 }) 3543 3544 It("podman play kube uses all env values from both sources", func() { 3545 SkipIfRemote("--configmaps is not supported for remote") 3546 3547 fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 3548 fsCm := getConfigMap(withConfigMapName("fooFs"), 3549 withConfigMapData("FOO_FS_1", "fooFS1"), 3550 withConfigMapData("FOO_FS_2", "fooFS2")) 3551 err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname) 3552 Expect(err).To(BeNil()) 3553 3554 cm := getConfigMap(withConfigMapName("foo"), 3555 withConfigMapData("FOO_1", "foo1"), 3556 withConfigMapData("FOO_2", "foo2"), 3557 ) 3558 3559 cmYaml, err := getKubeYaml("configmap", cm) 3560 Expect(err).To(BeNil()) 3561 3562 pod := getPod(withCtr(getCtr( 3563 withEnvFrom("foo", "configmap", false), 3564 withEnvFrom("fooFs", "configmap", false), 3565 ))) 3566 3567 podYaml, err := getKubeYaml("pod", pod) 3568 Expect(err).To(BeNil()) 3569 3570 yamls := []string{cmYaml, podYaml} 3571 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3572 Expect(err).To(BeNil()) 3573 3574 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", fsCmYamlPathname}) 3575 kube.WaitWithDefaultTimeout() 3576 Expect(kube).Should(Exit(0)) 3577 3578 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 3579 inspect.WaitWithDefaultTimeout() 3580 Expect(inspect).Should(Exit(0)) 3581 Expect(inspect.OutputToString()).To(And( 3582 ContainSubstring(`FOO_1=foo1`), 3583 ContainSubstring(`FOO_2=foo2`), 3584 ContainSubstring(`FOO_FS_1=fooFS1`), 3585 ContainSubstring(`FOO_FS_2=fooFS2`), 3586 )) 3587 }) 3588 3589 It("podman play kube reports error when the same configmap name is present in both sources", func() { 3590 SkipIfRemote("--configmaps is not supported for remote") 3591 3592 fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 3593 fsCm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "fooFS")) 3594 err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname) 3595 Expect(err).To(BeNil()) 3596 3597 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 3598 3599 cmYaml, err := getKubeYaml("configmap", cm) 3600 Expect(err).To(BeNil()) 3601 3602 pod := getPod(withCtr(getCtr( 3603 withEnv("FOO", "", "configmap", "foo", "FOO", false), 3604 ))) 3605 3606 podYaml, err := getKubeYaml("pod", pod) 3607 Expect(err).To(BeNil()) 3608 3609 yamls := []string{cmYaml, podYaml} 3610 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3611 Expect(err).To(BeNil()) 3612 3613 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", fsCmYamlPathname}) 3614 kube.WaitWithDefaultTimeout() 3615 Expect(kube).Should(Exit(125)) 3616 Expect(kube.ErrorToString()).To(ContainSubstring("ambiguous configuration: the same config map foo is present in YAML and in --configmaps")) 3617 }) 3618 }) 3619 3620 It("podman play kube --log-opt = tag test", func() { 3621 SkipIfContainerized("journald does not work inside the container") 3622 pod := getPod() 3623 err := generateKubeYaml("pod", pod, kubeYaml) 3624 Expect(err).To(BeNil()) 3625 3626 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--log-driver", "journald", "--log-opt", "tag={{.ImageName}}"}) 3627 kube.WaitWithDefaultTimeout() 3628 Expect(kube).Should(Exit(0)) 3629 3630 start := podmanTest.Podman([]string{"start", getCtrNameInPod(pod)}) 3631 start.WaitWithDefaultTimeout() 3632 Expect(start).Should(Exit(0)) 3633 3634 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 3635 inspect.WaitWithDefaultTimeout() 3636 Expect(start).Should(Exit(0)) 3637 Expect((inspect.InspectContainerToJSON()[0]).HostConfig.LogConfig.Tag).To(Equal("{{.ImageName}}")) 3638 }) 3639 3640 // Check that --userns=auto creates a user namespace 3641 It("podman play kube --userns=auto", func() { 3642 u, err := user.Current() 3643 Expect(err).To(BeNil()) 3644 name := u.Name 3645 if name == "root" { 3646 name = "containers" 3647 } 3648 content, err := ioutil.ReadFile("/etc/subuid") 3649 if err != nil { 3650 Skip("cannot read /etc/subuid") 3651 } 3652 if !strings.Contains(string(content), name) { 3653 Skip("cannot find mappings for the current user") 3654 } 3655 3656 initialUsernsConfig, err := ioutil.ReadFile("/proc/self/uid_map") 3657 Expect(err).To(BeNil()) 3658 if os.Geteuid() != 0 { 3659 unshare := podmanTest.Podman([]string{"unshare", "cat", "/proc/self/uid_map"}) 3660 unshare.WaitWithDefaultTimeout() 3661 Expect(unshare).Should(Exit(0)) 3662 initialUsernsConfig = unshare.Out.Contents() 3663 } 3664 3665 pod := getPod() 3666 err = generateKubeYaml("pod", pod, kubeYaml) 3667 Expect(err).To(BeNil()) 3668 3669 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3670 kube.WaitWithDefaultTimeout() 3671 Expect(kube).Should(Exit(0)) 3672 3673 usernsInCtr := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/proc/self/uid_map"}) 3674 usernsInCtr.WaitWithDefaultTimeout() 3675 Expect(usernsInCtr).Should(Exit(0)) 3676 // the conversion to string is needed for better error messages 3677 Expect(string(usernsInCtr.Out.Contents())).To(Equal(string(initialUsernsConfig))) 3678 3679 // PodmanNoCache is a workaround for https://github.com/containers/storage/issues/1232 3680 kube = podmanTest.PodmanNoCache([]string{"play", "kube", "--replace", "--userns=auto", kubeYaml}) 3681 kube.WaitWithDefaultTimeout() 3682 Expect(kube).Should(Exit(0)) 3683 3684 usernsInCtr = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/proc/self/uid_map"}) 3685 usernsInCtr.WaitWithDefaultTimeout() 3686 Expect(usernsInCtr).Should(Exit(0)) 3687 Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig)))) 3688 }) 3689 3690 // Check the block devices are exposed inside container 3691 It("podman play kube expose block device inside container", func() { 3692 SkipIfRootless("It needs root access to create devices") 3693 3694 // randomize the folder name to avoid error when running tests with multiple nodes 3695 uuid, err := uuid.NewUUID() 3696 Expect(err).To(BeNil()) 3697 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 3698 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(BeNil()) 3699 defer os.RemoveAll(devFolder) 3700 3701 devicePath := fmt.Sprintf("%s/blockdevice", devFolder) 3702 mknod := SystemExec("mknod", []string{devicePath, "b", "7", "0"}) 3703 mknod.WaitWithDefaultTimeout() 3704 Expect(mknod).Should(Exit(0)) 3705 3706 blockVolume := getHostPathVolume("BlockDevice", devicePath) 3707 3708 pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) 3709 err = generateKubeYaml("pod", pod, kubeYaml) 3710 Expect(err).To(BeNil()) 3711 3712 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3713 kube.WaitWithDefaultTimeout() 3714 Expect(kube).Should(Exit(0)) 3715 3716 // Container should be in running state 3717 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 3718 inspect.WaitWithDefaultTimeout() 3719 Expect(inspect).Should(Exit(0)) 3720 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 3721 3722 // Container should have a block device /dev/loop1 3723 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.Devices}}", "testPod-" + defaultCtrName}) 3724 inspect.WaitWithDefaultTimeout() 3725 Expect(inspect).Should(Exit(0)) 3726 Expect(inspect.OutputToString()).To(ContainSubstring(devicePath)) 3727 }) 3728 3729 // Check the char devices are exposed inside container 3730 It("podman play kube expose character device inside container", func() { 3731 SkipIfRootless("It needs root access to create devices") 3732 3733 // randomize the folder name to avoid error when running tests with multiple nodes 3734 uuid, err := uuid.NewUUID() 3735 Expect(err).To(BeNil()) 3736 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 3737 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(BeNil()) 3738 defer os.RemoveAll(devFolder) 3739 3740 devicePath := fmt.Sprintf("%s/chardevice", devFolder) 3741 mknod := SystemExec("mknod", []string{devicePath, "c", "3", "1"}) 3742 mknod.WaitWithDefaultTimeout() 3743 Expect(mknod).Should(Exit(0)) 3744 3745 charVolume := getHostPathVolume("CharDevice", devicePath) 3746 3747 pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) 3748 err = generateKubeYaml("pod", pod, kubeYaml) 3749 Expect(err).To(BeNil()) 3750 3751 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3752 kube.WaitWithDefaultTimeout() 3753 Expect(kube).Should(Exit(0)) 3754 3755 // Container should be in running state 3756 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 3757 inspect.WaitWithDefaultTimeout() 3758 Expect(inspect).Should(Exit(0)) 3759 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 3760 3761 // Container should have a block device /dev/loop1 3762 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.Devices}}", "testPod-" + defaultCtrName}) 3763 inspect.WaitWithDefaultTimeout() 3764 Expect(inspect).Should(Exit(0)) 3765 Expect(inspect.OutputToString()).To(ContainSubstring(devicePath)) 3766 }) 3767 3768 It("podman play kube reports error when the device does not exists", func() { 3769 SkipIfRootless("It needs root access to create devices") 3770 3771 devicePath := "/dev/foodevdir/baddevice" 3772 3773 blockVolume := getHostPathVolume("BlockDevice", devicePath) 3774 3775 pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) 3776 err = generateKubeYaml("pod", pod, kubeYaml) 3777 Expect(err).To(BeNil()) 3778 3779 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3780 kube.WaitWithDefaultTimeout() 3781 Expect(kube).Should(Exit(125)) 3782 }) 3783 3784 It("podman play kube reports error when we try to expose char device as block device", func() { 3785 SkipIfRootless("It needs root access to create devices") 3786 3787 // randomize the folder name to avoid error when running tests with multiple nodes 3788 uuid, err := uuid.NewUUID() 3789 Expect(err).To(BeNil()) 3790 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 3791 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(BeNil()) 3792 defer os.RemoveAll(devFolder) 3793 3794 devicePath := fmt.Sprintf("%s/chardevice", devFolder) 3795 mknod := SystemExec("mknod", []string{devicePath, "c", "3", "1"}) 3796 mknod.WaitWithDefaultTimeout() 3797 Expect(mknod).Should(Exit(0)) 3798 3799 charVolume := getHostPathVolume("BlockDevice", devicePath) 3800 3801 pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) 3802 err = generateKubeYaml("pod", pod, kubeYaml) 3803 Expect(err).To(BeNil()) 3804 3805 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3806 kube.WaitWithDefaultTimeout() 3807 Expect(kube).Should(Exit(125)) 3808 }) 3809 3810 It("podman play kube reports error when we try to expose block device as char device", func() { 3811 SkipIfRootless("It needs root access to create devices") 3812 3813 // randomize the folder name to avoid error when running tests with multiple nodes 3814 uuid, err := uuid.NewUUID() 3815 Expect(err).To(BeNil()) 3816 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 3817 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(BeNil()) 3818 3819 devicePath := fmt.Sprintf("%s/blockdevice", devFolder) 3820 mknod := SystemExec("mknod", []string{devicePath, "b", "7", "0"}) 3821 mknod.WaitWithDefaultTimeout() 3822 Expect(mknod).Should(Exit(0)) 3823 3824 charVolume := getHostPathVolume("CharDevice", devicePath) 3825 3826 pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) 3827 err = generateKubeYaml("pod", pod, kubeYaml) 3828 Expect(err).To(BeNil()) 3829 3830 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 3831 kube.WaitWithDefaultTimeout() 3832 Expect(kube).Should(Exit(125)) 3833 }) 3834 3835 })