github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/play_kube_test.go (about) 1 package integration 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/base64" 7 "encoding/json" 8 "fmt" 9 "io" 10 "net" 11 "net/http" 12 "net/url" 13 "os" 14 "os/exec" 15 "os/user" 16 "path/filepath" 17 "strconv" 18 "strings" 19 "text/template" 20 "time" 21 22 "github.com/containers/podman/v5/libpod/define" 23 "github.com/containers/podman/v5/pkg/bindings" 24 "github.com/containers/podman/v5/pkg/bindings/play" 25 v1 "github.com/containers/podman/v5/pkg/k8s.io/api/core/v1" 26 "github.com/containers/podman/v5/pkg/util" 27 . "github.com/containers/podman/v5/test/utils" 28 "github.com/containers/podman/v5/utils" 29 "github.com/containers/storage/pkg/stringid" 30 "github.com/google/uuid" 31 . "github.com/onsi/ginkgo/v2" 32 . "github.com/onsi/gomega" 33 "github.com/onsi/gomega/format" 34 . "github.com/onsi/gomega/gexec" 35 "github.com/opencontainers/selinux/go-selinux" 36 ) 37 38 var secretYaml = ` 39 apiVersion: v1 40 kind: Secret 41 metadata: 42 name: newsecret 43 type: Opaque 44 data: 45 username: dXNlcg== 46 password: NTRmNDFkMTJlOGZh 47 ` 48 49 var complexSecretYaml = ` 50 apiVersion: v1 51 kind: Secret 52 metadata: 53 name: newsecrettwo 54 type: Opaque 55 data: 56 username: Y2RvZXJu 57 password: dGVzdGluZ3Rlc3RpbmcK 58 note: a3ViZSBzZWNyZXRzIGFyZSBjb29sIQo= 59 stringData: 60 plain_note: This is a test 61 ` 62 63 var secretPodYaml = ` 64 apiVersion: v1 65 kind: Pod 66 metadata: 67 name: mypod 68 spec: 69 containers: 70 - name: myctr 71 image: ` + CITEST_IMAGE + ` 72 command: 73 - top 74 volumeMounts: 75 - name: foo 76 mountPath: /etc/foo 77 readOnly: true 78 volumes: 79 - name: foo 80 secret: 81 secretName: newsecret 82 optional: false 83 ` 84 85 var secretPodYamlTwo = ` 86 apiVersion: v1 87 kind: Pod 88 metadata: 89 name: mypod2 90 spec: 91 containers: 92 - name: myctr 93 image: ` + CITEST_IMAGE + ` 94 command: 95 - top 96 volumeMounts: 97 - name: foo 98 mountPath: /etc/foo 99 readOnly: true 100 - name: bar 101 mountPath: /etc/bar 102 readOnly: true 103 - name: baz 104 mountPath: /etc/baz 105 readOnly: true 106 volumes: 107 - name: foo 108 secret: 109 secretName: newsecret 110 optional: false 111 - name: bar 112 secret: 113 secretName: newsecrettwo 114 optional: false 115 - name: baz 116 secret: 117 secretName: newsecrettwo 118 optional: false 119 ` 120 121 var optionalExistingSecretPodYaml = ` 122 apiVersion: v1 123 kind: Pod 124 metadata: 125 name: mypod 126 spec: 127 containers: 128 - name: myctr 129 image: ` + CITEST_IMAGE + ` 130 command: 131 - top 132 volumeMounts: 133 - name: foo 134 mountPath: /etc/foo 135 readOnly: true 136 volumes: 137 - name: foo 138 secret: 139 secretName: newsecret 140 optional: true 141 ` 142 143 var optionalNonExistingSecretPodYaml = ` 144 apiVersion: v1 145 kind: Pod 146 metadata: 147 name: mypod 148 spec: 149 containers: 150 - name: myctr 151 image: ` + CITEST_IMAGE + ` 152 command: 153 - top 154 volumeMounts: 155 - name: foo 156 mountPath: /etc/foo 157 readOnly: true 158 volumes: 159 - name: foo 160 secret: 161 secretName: oldsecret 162 optional: true 163 ` 164 165 var noOptionalExistingSecretPodYaml = ` 166 apiVersion: v1 167 kind: Pod 168 metadata: 169 name: mypod 170 spec: 171 containers: 172 - name: myctr 173 image: ` + CITEST_IMAGE + ` 174 command: 175 - top 176 volumeMounts: 177 - name: foo 178 mountPath: /etc/foo 179 readOnly: true 180 volumes: 181 - name: foo 182 secret: 183 secretName: newsecret 184 ` 185 186 var noOptionalNonExistingSecretPodYaml = ` 187 apiVersion: v1 188 kind: Pod 189 metadata: 190 name: mypod 191 spec: 192 containers: 193 - name: myctr 194 image: ` + CITEST_IMAGE + ` 195 command: 196 - top 197 volumeMounts: 198 - name: foo 199 mountPath: /etc/foo 200 readOnly: true 201 volumes: 202 - name: foo 203 secret: 204 secretName: oldsecret` 205 206 var simplePodYaml = ` 207 apiVersion: v1 208 kind: Pod 209 metadata: 210 name: libpod-test 211 spec: 212 containers: 213 - image: ` + CITEST_IMAGE + ` 214 command: 215 - sleep 216 - "3600"` 217 218 var unknownKindYaml = ` 219 apiVersion: v1 220 kind: UnknownKind 221 metadata: 222 labels: 223 app: app1 224 name: unknown 225 spec: 226 hostname: unknown 227 ` 228 229 var workdirSymlinkPodYaml = ` 230 apiVersion: v1 231 kind: Pod 232 metadata: 233 labels: 234 app: test-symlink 235 name: test-symlink 236 spec: 237 containers: 238 - image: test-symlink 239 name: test-symlink 240 resources: {} 241 restartPolicy: Never 242 ` 243 244 var podnameEqualsContainerNameYaml = ` 245 apiVersion: v1 246 kind: Pod 247 metadata: 248 name: podnameEqualsContainerNameYaml 249 spec: 250 containers: 251 - name: podnameEqualsContainerNameYaml 252 image: ` + CITEST_IMAGE + ` 253 ` 254 255 var podWithoutAName = ` 256 apiVersion: v1 257 kind: Pod 258 spec: 259 containers: 260 - name: podDoesntHaveAName 261 image: ` + CITEST_IMAGE + ` 262 ports: 263 - containerPort: 80 264 ` 265 266 var subpathTestNamedVolume = ` 267 apiVersion: v1 268 kind: Pod 269 metadata: 270 name: testpod 271 spec: 272 containers: 273 - name: testctr 274 image: ` + CITEST_IMAGE + ` 275 command: 276 - /bin/sh 277 - -c 278 - | 279 trap exit SIGTERM 280 while :; do sleep 0.1; done 281 volumeMounts: 282 - mountPath: /var 283 name: testing 284 subPath: testing/onlythis 285 volumes: 286 - name: testing 287 persistentVolumeClaim: 288 claimName: testvol 289 ` 290 291 var signalTest = ` 292 apiVersion: v1 293 kind: Pod 294 metadata: 295 name: testpod 296 spec: 297 containers: 298 - name: testctr 299 image: ` + CITEST_IMAGE + ` 300 command: 301 - /bin/sh 302 - -c 303 - | 304 trap 'echo TERMINATED > /testvol/termfile; exit' SIGTERM 305 while true; do sleep 0.1; done 306 volumeMounts: 307 - mountPath: /testvol 308 name: testvol 309 volumes: 310 - name: testvol 311 persistentVolumeClaim: 312 claimName: testvol 313 ` 314 315 var checkInfraImagePodYaml = ` 316 apiVersion: v1 317 kind: Pod 318 metadata: 319 labels: 320 app: check-infra-image 321 name: check-infra-image 322 spec: 323 containers: 324 - name: testimage 325 image: ` + CITEST_IMAGE + ` 326 command: 327 - sleep 328 - 24h 329 status: {} 330 ` 331 332 var podWithoutConfigMapDefined = ` 333 apiVersion: v1 334 kind: Pod 335 metadata: 336 name: testpod1 337 spec: 338 containers: 339 - name: testimage 340 image: ` + CITEST_IMAGE + ` 341 volumeMounts: 342 - name: mycm 343 mountPath: /mycm 344 volumes: 345 - name: mycm 346 configMap: 347 name: mycm 348 ` 349 350 var sharedNamespacePodYaml = ` 351 apiVersion: v1 352 kind: Pod 353 metadata: 354 creationTimestamp: "2021-05-07T17:25:01Z" 355 labels: 356 app: testpod1 357 name: testpod1 358 spec: 359 containers: 360 - command: 361 - top 362 - -d 363 - "1.5" 364 env: 365 - name: HOSTNAME 366 value: label-pod 367 image: ` + CITEST_IMAGE + ` 368 name: testimage 369 resources: {} 370 securityContext: 371 allowPrivilegeEscalation: true 372 capabilities: {} 373 privileged: false 374 readOnlyRootFilesystem: false 375 seLinuxOptions: {} 376 workingDir: / 377 dnsConfig: {} 378 restartPolicy: Never 379 shareProcessNamespace: true 380 status: {} 381 ` 382 var livenessProbePodYaml = ` 383 apiVersion: apps/v1 384 kind: Deployment 385 metadata: 386 name: liveness-probe 387 labels: 388 app: testimage 389 spec: 390 replicas: 1 391 selector: 392 matchLabels: 393 app: testimage 394 template: 395 metadata: 396 labels: 397 app: testimage 398 spec: 399 containers: 400 - command: 401 - top 402 - -d 403 - "1.5" 404 name: testimage 405 image: ` + CITEST_IMAGE + ` 406 livenessProbe: 407 exec: 408 command: 409 - echo 410 - hello 411 initialDelaySeconds: 5 412 periodSeconds: 5 413 ` 414 var livenessProbeUnhealthyPodYaml = ` 415 apiVersion: apps/v1 416 kind: Deployment 417 metadata: 418 name: liveness-unhealthy-probe 419 labels: 420 app: testimage 421 spec: 422 replicas: 1 423 selector: 424 matchLabels: 425 app: testimage 426 template: 427 metadata: 428 labels: 429 app: testimage 430 spec: 431 restartPolicy: Never 432 containers: 433 - command: 434 - top 435 - -d 436 - "1.5" 437 name: testimage 438 image: ` + CITEST_IMAGE + ` 439 livenessProbe: 440 exec: 441 command: 442 - cat 443 - /randomfile 444 initialDelaySeconds: 0 445 periodSeconds: 1 446 ` 447 448 var startupProbePodYaml = ` 449 apiVersion: apps/v1 450 kind: Deployment 451 metadata: 452 name: startup-healthy-probe 453 labels: 454 app: testimage 455 spec: 456 replicas: 1 457 selector: 458 matchLabels: 459 app: testimage 460 template: 461 metadata: 462 labels: 463 app: testimage 464 spec: 465 restartPolicy: Never 466 containers: 467 - command: 468 - top 469 - -d 470 - "1.5" 471 name: testimage 472 image: ` + CITEST_IMAGE + ` 473 startupProbe: 474 exec: 475 command: 476 - /bin/sh 477 - -c 478 - cat /testfile 479 initialDelaySeconds: 0 480 periodSeconds: 1 481 livenessProbe: 482 exec: 483 command: 484 - echo 485 - liveness probe 486 initialDelaySeconds: 0 487 periodSeconds: 1 488 ` 489 490 var selinuxLabelPodYaml = ` 491 apiVersion: v1 492 kind: Pod 493 metadata: 494 creationTimestamp: "2021-02-02T22:18:20Z" 495 labels: 496 app: label-pod 497 name: label-pod 498 spec: 499 containers: 500 - command: 501 - top 502 - -d 503 - "1.5" 504 env: 505 - name: HOSTNAME 506 value: label-pod 507 image: ` + CITEST_IMAGE + ` 508 name: test 509 securityContext: 510 allowPrivilegeEscalation: true 511 privileged: false 512 readOnlyRootFilesystem: false 513 seLinuxOptions: 514 user: unconfined_u 515 role: system_r 516 type: spc_t 517 level: s0 518 workingDir: / 519 status: {} 520 ` 521 522 var volumesFromPodYaml = ` 523 apiVersion: v1 524 kind: Pod 525 metadata: 526 annotations: 527 io.podman.annotations.volumes-from/tgtctr: srcctr:ro 528 name: volspod 529 spec: 530 containers: 531 - name: srcctr 532 image: ` + CITEST_IMAGE + ` 533 command: 534 - sleep 535 - inf 536 volumeMounts: 537 - mountPath: /mnt/vol 538 name: testing 539 - name: tgtctr 540 image: ` + CITEST_IMAGE + ` 541 command: 542 - sleep 543 - inf 544 volumes: 545 - name: testing 546 persistentVolumeClaim: 547 claimName: testvol 548 ` 549 550 var configMapYamlTemplate = ` 551 apiVersion: v1 552 kind: ConfigMap 553 metadata: 554 name: {{ .Name }} 555 data: 556 {{ with .Data }} 557 {{ range $key, $value := . }} 558 {{ $key }}: {{ $value }} 559 {{ end }} 560 {{ end }} 561 ` 562 563 var secretYamlTemplate = ` 564 apiVersion: v1 565 kind: Secret 566 metadata: 567 name: {{ .Name }} 568 data: 569 {{ with .Data }} 570 {{ range $key, $value := . }} 571 {{ $key }}: {{ $value }} 572 {{ end }} 573 {{ end }} 574 ` 575 576 var persistentVolumeClaimYamlTemplate = ` 577 apiVersion: v1 578 kind: PersistentVolumeClaim 579 metadata: 580 name: {{ .Name }} 581 {{ with .Annotations }} 582 annotations: 583 {{ range $key, $value := . }} 584 {{ $key }}: {{ $value }} 585 {{ end }} 586 {{ end }} 587 spec: 588 accessModes: 589 - "ReadWriteOnce" 590 resources: 591 requests: 592 storage: "1Gi" 593 storageClassName: default 594 ` 595 596 var podYamlTemplate = ` 597 apiVersion: v1 598 kind: Pod 599 metadata: 600 creationTimestamp: "2019-07-17T14:44:08Z" 601 name: {{ .Name }} 602 labels: 603 app: {{ .Name }} 604 {{ with .Labels }} 605 {{ range $key, $value := . }} 606 {{ $key }}: {{ $value }} 607 {{ end }} 608 {{ end }} 609 {{ with .Annotations }} 610 annotations: 611 {{ range $key, $value := . }} 612 {{ $key }}: {{ $value }} 613 {{ end }} 614 {{ end }} 615 616 spec: 617 restartPolicy: {{ .RestartPolicy }} 618 hostname: {{ .Hostname }} 619 hostNetwork: {{ .HostNetwork }} 620 {{ if .HostUsers }} 621 hostUsers: {{ .HostUsers }} 622 {{ end }} 623 hostAliases: 624 {{ range .HostAliases }} 625 - hostnames: 626 {{ range .HostName }} 627 - {{ . }} 628 {{ end }} 629 ip: {{ .IP }} 630 {{ end }} 631 initContainers: 632 {{ with .InitCtrs }} 633 {{ range . }} 634 - command: 635 {{ range .Cmd }} 636 - {{.}} 637 {{ end }} 638 image: {{ .Image }} 639 name: {{ .Name }} 640 {{ end }} 641 {{ end }} 642 {{ if .SecurityContext }} 643 securityContext: 644 {{ if .RunAsUser }}runAsUser: {{ .RunAsUser }}{{- end }} 645 {{ if .RunAsGroup }}runAsGroup: {{ .RunAsGroup }}{{- end }} 646 {{ end }} 647 containers: 648 {{ with .Ctrs }} 649 {{ range . }} 650 - command: 651 {{ range .Cmd }} 652 - {{.}} 653 {{ end }} 654 args: 655 {{ range .Arg }} 656 - {{.}} 657 {{ end }} 658 env: 659 - name: HOSTNAME 660 {{ range .Env }} 661 - name: {{ .Name }} 662 {{ if (eq .ValueFrom "configmap") }} 663 valueFrom: 664 configMapKeyRef: 665 name: {{ .RefName }} 666 key: {{ .RefKey }} 667 optional: {{ .Optional }} 668 {{ end }} 669 {{ if (eq .ValueFrom "secret") }} 670 valueFrom: 671 secretKeyRef: 672 name: {{ .RefName }} 673 key: {{ .RefKey }} 674 optional: {{ .Optional }} 675 {{ end }} 676 {{ if (eq .ValueFrom "") }} 677 value: {{ .Value }} 678 {{ end }} 679 {{ end }} 680 {{ with .EnvFrom}} 681 envFrom: 682 {{ range . }} 683 {{ if (eq .From "configmap") }} 684 - configMapRef: 685 name: {{ .Name }} 686 optional: {{ .Optional }} 687 {{ end }} 688 {{ if (eq .From "secret") }} 689 - secretRef: 690 name: {{ .Name }} 691 optional: {{ .Optional }} 692 {{ end }} 693 {{ end }} 694 {{ end }} 695 image: {{ .Image }} 696 name: {{ .Name }} 697 imagePullPolicy: {{ .PullPolicy }} 698 {{- if or .CPURequest .CPULimit .MemoryRequest .MemoryLimit }} 699 resources: 700 {{- if or .CPURequest .MemoryRequest }} 701 requests: 702 {{if .CPURequest }}cpu: {{ .CPURequest }}{{ end }} 703 {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} 704 {{- end }} 705 {{- if or .CPULimit .MemoryLimit }} 706 limits: 707 {{if .CPULimit }}cpu: {{ .CPULimit }}{{ end }} 708 {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} 709 {{- end }} 710 {{- end }} 711 {{ if .SecurityContext }} 712 securityContext: 713 {{ if .RunAsUser }}runAsUser: {{ .RunAsUser }}{{- end }} 714 {{ if .RunAsGroup }}runAsGroup: {{ .RunAsGroup }}{{- end }} 715 allowPrivilegeEscalation: true 716 {{ if .Caps }} 717 capabilities: 718 {{ with .CapAdd }} 719 add: 720 {{ range . }} 721 - {{.}} 722 {{ end }} 723 {{ end }} 724 {{ with .CapDrop }} 725 drop: 726 {{ range . }} 727 - {{.}} 728 {{ end }} 729 {{ end }} 730 {{ end }} 731 privileged: false 732 readOnlyRootFilesystem: false 733 ports: 734 - containerPort: {{ .Port }} 735 hostIP: {{ .HostIP }} 736 hostPort: {{ .Port }} 737 protocol: TCP 738 workingDir: / 739 volumeMounts: 740 {{ if .VolumeMount }} 741 - name: {{.VolumeName}} 742 mountPath: {{ .VolumeMountPath }} 743 subPath: {{ .VolumeSubPath }} 744 readonly: {{.VolumeReadOnly}} 745 {{ end }} 746 {{ end }} 747 {{ end }} 748 {{ end }} 749 {{ with .Volumes }} 750 volumes: 751 {{ range . }} 752 - name: {{ .Name }} 753 {{- if (eq .VolumeType "EmptyDir") }} 754 emptyDir: {} 755 {{- end }} 756 {{- if (eq .VolumeType "HostPath") }} 757 hostPath: 758 path: {{ .HostPath.Path }} 759 type: {{ .HostPath.Type }} 760 {{- end }} 761 {{- if (eq .VolumeType "PersistentVolumeClaim") }} 762 persistentVolumeClaim: 763 claimName: {{ .PersistentVolumeClaim.ClaimName }} 764 {{- end }} 765 {{- if (eq .VolumeType "ConfigMap") }} 766 configMap: 767 name: {{ .ConfigMap.Name }} 768 optional: {{ .ConfigMap.Optional }} 769 defaultMode: {{ .ConfigMap.DefaultMode }} 770 {{- with .ConfigMap.Items }} 771 items: 772 {{- range . }} 773 - key: {{ .key }} 774 path: {{ .path }} 775 {{- end }} 776 {{- end }} 777 {{- end }} 778 {{- if (eq .VolumeType "Secret") }} 779 secret: 780 secretName: {{ .SecretVol.SecretName }} 781 optional: {{ .SecretVol.Optional }} 782 defaultMode: {{ .SecretVol.DefaultMode }} 783 {{- with .SecretVol.Items }} 784 items: 785 {{- range . }} 786 - key: {{ .key }} 787 path: {{ .path }} 788 {{- end }} 789 {{- end }} 790 {{- end }} 791 {{ end }} 792 {{ end }} 793 status: {} 794 ` 795 796 var daemonSetYamlTemplate = ` 797 apiVersion: v1 798 kind: DaemonSet 799 metadata: 800 creationTimestamp: "2019-07-17T14:44:08Z" 801 name: {{ .Name }} 802 labels: 803 app: {{ .Name }} 804 {{ with .Labels }} 805 {{ range $key, $value := . }} 806 {{ $key }}: {{ $value }} 807 {{ end }} 808 {{ end }} 809 {{ with .Annotations }} 810 annotations: 811 {{ range $key, $value := . }} 812 {{ $key }}: {{ $value }} 813 {{ end }} 814 {{ end }} 815 816 spec: 817 selector: 818 matchLabels: 819 app: {{ .Name }} 820 template: 821 {{ with .PodTemplate }} 822 metadata: 823 labels: 824 app: {{ .Name }} 825 {{- with .Labels }}{{ range $key, $value := . }} 826 {{ $key }}: {{ $value }} 827 {{- end }}{{ end }} 828 {{- with .Annotations }} 829 annotations: 830 {{- range $key, $value := . }} 831 {{ $key }}: {{ $value }} 832 {{- end }} 833 {{- end }} 834 spec: 835 restartPolicy: {{ .RestartPolicy }} 836 hostname: {{ .Hostname }} 837 hostNetwork: {{ .HostNetwork }} 838 containers: 839 {{ with .Ctrs }} 840 {{ range . }} 841 - command: 842 {{ range .Cmd }} 843 - {{.}} 844 {{ end }} 845 args: 846 {{ range .Arg }} 847 - {{.}} 848 {{ end }} 849 env: 850 - name: HOSTNAME 851 {{ range .Env }} 852 - name: {{ .Name }} 853 {{ if (eq .ValueFrom "configmap") }} 854 valueFrom: 855 configMapKeyRef: 856 name: {{ .RefName }} 857 key: {{ .RefKey }} 858 optional: {{ .Optional }} 859 {{ end }} 860 {{ if (eq .ValueFrom "secret") }} 861 valueFrom: 862 secretKeyRef: 863 name: {{ .RefName }} 864 key: {{ .RefKey }} 865 optional: {{ .Optional }} 866 {{ end }} 867 {{ if (eq .ValueFrom "") }} 868 value: {{ .Value }} 869 {{ end }} 870 {{ end }} 871 {{ with .EnvFrom}} 872 envFrom: 873 {{ range . }} 874 {{ if (eq .From "configmap") }} 875 - configMapRef: 876 name: {{ .Name }} 877 optional: {{ .Optional }} 878 {{ end }} 879 {{ if (eq .From "secret") }} 880 - secretRef: 881 name: {{ .Name }} 882 optional: {{ .Optional }} 883 {{ end }} 884 {{ end }} 885 {{ end }} 886 image: {{ .Image }} 887 name: {{ .Name }} 888 imagePullPolicy: {{ .PullPolicy }} 889 {{- if or .CPURequest .CPULimit .MemoryRequest .MemoryLimit }} 890 resources: 891 {{- if or .CPURequest .MemoryRequest }} 892 requests: 893 {{if .CPURequest }}cpu: {{ .CPURequest }}{{ end }} 894 {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} 895 {{- end }} 896 {{- if or .CPULimit .MemoryLimit }} 897 limits: 898 {{if .CPULimit }}cpu: {{ .CPULimit }}{{ end }} 899 {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} 900 {{- end }} 901 {{- end }} 902 {{ if .SecurityContext }} 903 securityContext: 904 allowPrivilegeEscalation: true 905 {{ if .Caps }} 906 capabilities: 907 {{ with .CapAdd }} 908 add: 909 {{ range . }} 910 - {{.}} 911 {{ end }} 912 {{ end }} 913 {{ with .CapDrop }} 914 drop: 915 {{ range . }} 916 - {{.}} 917 {{ end }} 918 {{ end }} 919 {{ end }} 920 privileged: false 921 readOnlyRootFilesystem: false 922 workingDir: / 923 volumeMounts: 924 {{ if .VolumeMount }} 925 - name: {{.VolumeName}} 926 mountPath: {{ .VolumeMountPath }} 927 readonly: {{.VolumeReadOnly}} 928 {{ end }} 929 {{ end }} 930 {{ end }} 931 {{ end }} 932 {{ with .Volumes }} 933 volumes: 934 {{ range . }} 935 - name: {{ .Name }} 936 {{- if (eq .VolumeType "HostPath") }} 937 hostPath: 938 path: {{ .HostPath.Path }} 939 type: {{ .HostPath.Type }} 940 {{- end }} 941 {{- if (eq .VolumeType "PersistentVolumeClaim") }} 942 persistentVolumeClaim: 943 claimName: {{ .PersistentVolumeClaim.ClaimName }} 944 {{- end }} 945 {{ end }} 946 {{ end }} 947 {{ end }} 948 ` 949 var deploymentYamlTemplate = ` 950 apiVersion: v1 951 kind: Deployment 952 metadata: 953 creationTimestamp: "2019-07-17T14:44:08Z" 954 name: {{ .Name }} 955 labels: 956 app: {{ .Name }} 957 {{ with .Labels }} 958 {{ range $key, $value := . }} 959 {{ $key }}: {{ $value }} 960 {{ end }} 961 {{ end }} 962 {{ with .Annotations }} 963 annotations: 964 {{ range $key, $value := . }} 965 {{ $key }}: {{ $value }} 966 {{ end }} 967 {{ end }} 968 969 spec: 970 replicas: {{ .Replicas }} 971 selector: 972 matchLabels: 973 app: {{ .Name }} 974 template: 975 {{ with .PodTemplate }} 976 metadata: 977 labels: 978 app: {{ .Name }} 979 {{- with .Labels }}{{ range $key, $value := . }} 980 {{ $key }}: {{ $value }} 981 {{- end }}{{ end }} 982 {{- with .Annotations }} 983 annotations: 984 {{- range $key, $value := . }} 985 {{ $key }}: {{ $value }} 986 {{- end }} 987 {{- end }} 988 spec: 989 restartPolicy: {{ .RestartPolicy }} 990 hostname: {{ .Hostname }} 991 hostNetwork: {{ .HostNetwork }} 992 containers: 993 {{ with .Ctrs }} 994 {{ range . }} 995 - command: 996 {{ range .Cmd }} 997 - {{.}} 998 {{ end }} 999 args: 1000 {{ range .Arg }} 1001 - {{.}} 1002 {{ end }} 1003 env: 1004 - name: HOSTNAME 1005 {{ range .Env }} 1006 - name: {{ .Name }} 1007 {{ if (eq .ValueFrom "configmap") }} 1008 valueFrom: 1009 configMapKeyRef: 1010 name: {{ .RefName }} 1011 key: {{ .RefKey }} 1012 optional: {{ .Optional }} 1013 {{ end }} 1014 {{ if (eq .ValueFrom "secret") }} 1015 valueFrom: 1016 secretKeyRef: 1017 name: {{ .RefName }} 1018 key: {{ .RefKey }} 1019 optional: {{ .Optional }} 1020 {{ end }} 1021 {{ if (eq .ValueFrom "") }} 1022 value: {{ .Value }} 1023 {{ end }} 1024 {{ end }} 1025 {{ with .EnvFrom}} 1026 envFrom: 1027 {{ range . }} 1028 {{ if (eq .From "configmap") }} 1029 - configMapRef: 1030 name: {{ .Name }} 1031 optional: {{ .Optional }} 1032 {{ end }} 1033 {{ if (eq .From "secret") }} 1034 - secretRef: 1035 name: {{ .Name }} 1036 optional: {{ .Optional }} 1037 {{ end }} 1038 {{ end }} 1039 {{ end }} 1040 image: {{ .Image }} 1041 name: {{ .Name }} 1042 imagePullPolicy: {{ .PullPolicy }} 1043 {{- if or .CPURequest .CPULimit .MemoryRequest .MemoryLimit }} 1044 resources: 1045 {{- if or .CPURequest .MemoryRequest }} 1046 requests: 1047 {{if .CPURequest }}cpu: {{ .CPURequest }}{{ end }} 1048 {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} 1049 {{- end }} 1050 {{- if or .CPULimit .MemoryLimit }} 1051 limits: 1052 {{if .CPULimit }}cpu: {{ .CPULimit }}{{ end }} 1053 {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} 1054 {{- end }} 1055 {{- end }} 1056 {{ if .SecurityContext }} 1057 securityContext: 1058 allowPrivilegeEscalation: true 1059 {{ if .Caps }} 1060 capabilities: 1061 {{ with .CapAdd }} 1062 add: 1063 {{ range . }} 1064 - {{.}} 1065 {{ end }} 1066 {{ end }} 1067 {{ with .CapDrop }} 1068 drop: 1069 {{ range . }} 1070 - {{.}} 1071 {{ end }} 1072 {{ end }} 1073 {{ end }} 1074 privileged: false 1075 readOnlyRootFilesystem: false 1076 workingDir: / 1077 volumeMounts: 1078 {{ if .VolumeMount }} 1079 - name: {{.VolumeName}} 1080 mountPath: {{ .VolumeMountPath }} 1081 readonly: {{.VolumeReadOnly}} 1082 {{ end }} 1083 {{ end }} 1084 {{ end }} 1085 {{ end }} 1086 {{ with .Volumes }} 1087 volumes: 1088 {{ range . }} 1089 - name: {{ .Name }} 1090 {{- if (eq .VolumeType "HostPath") }} 1091 hostPath: 1092 path: {{ .HostPath.Path }} 1093 type: {{ .HostPath.Type }} 1094 {{- end }} 1095 {{- if (eq .VolumeType "PersistentVolumeClaim") }} 1096 persistentVolumeClaim: 1097 claimName: {{ .PersistentVolumeClaim.ClaimName }} 1098 {{- end }} 1099 {{ end }} 1100 {{ end }} 1101 {{ end }} 1102 ` 1103 1104 var publishPortsPodWithoutPorts = ` 1105 apiVersion: v1 1106 kind: Pod 1107 metadata: 1108 name: nginx 1109 spec: 1110 containers: 1111 - name: nginx 1112 image: ` + NGINX_IMAGE + ` 1113 imagePullPolicy: missing 1114 ` 1115 1116 var publishPortsPodWithContainerPort = ` 1117 apiVersion: v1 1118 kind: Pod 1119 metadata: 1120 name: nginx 1121 spec: 1122 containers: 1123 - name: nginx 1124 image: ` + NGINX_IMAGE + ` 1125 imagePullPolicy: missing 1126 ports: 1127 - containerPort: 80 1128 ` 1129 1130 var publishPortsPodWithContainerHostPort = ` 1131 apiVersion: v1 1132 kind: Pod 1133 metadata: 1134 name: nginx 1135 spec: 1136 containers: 1137 - name: nginx 1138 image: ` + NGINX_IMAGE + ` 1139 imagePullPolicy: missing 1140 ports: 1141 - containerPort: 80 1142 hostPort: 19001 1143 ` 1144 1145 var publishPortsEchoWithHostPortUDP = ` 1146 apiVersion: v1 1147 kind: Pod 1148 metadata: 1149 name: network-echo 1150 spec: 1151 containers: 1152 - name: udp-echo 1153 image: ` + CITEST_IMAGE + ` 1154 command: 1155 - "/bin/sh" 1156 - "-c" 1157 - "nc -ulk -p 19008 -e /bin/cat" 1158 ports: 1159 - containerPort: 19008 1160 hostPort: 19009 1161 protocol: udp 1162 - name: tcp-echo 1163 image: ` + CITEST_IMAGE + ` 1164 command: 1165 - "/bin/sh" 1166 - "-c" 1167 - "nc -lk -p 19008 -e /bin/cat" 1168 ` 1169 1170 var publishPortsEchoWithHostPortTCP = ` 1171 apiVersion: v1 1172 kind: Pod 1173 metadata: 1174 name: network-echo 1175 spec: 1176 containers: 1177 - name: udp-echo 1178 image: ` + CITEST_IMAGE + ` 1179 command: 1180 - "/bin/sh" 1181 - "-c" 1182 - "nc -ulk -p 19008 -e /bin/cat" 1183 - name: tcp-echo 1184 image: ` + CITEST_IMAGE + ` 1185 command: 1186 - "/bin/sh" 1187 - "-c" 1188 - "nc -lk -p 19008 -e /bin/cat" 1189 ports: 1190 - containerPort: 19008 1191 hostPort: 19011 1192 protocol: tcp 1193 ` 1194 1195 var podWithHostPIDDefined = ` 1196 apiVersion: v1 1197 kind: Pod 1198 metadata: 1199 name: test-hostpid 1200 spec: 1201 hostPID: true 1202 containers: 1203 - name: testimage 1204 image: ` + CITEST_IMAGE + ` 1205 command: ['sh', '-c', 'echo $$'] 1206 ` 1207 1208 var podWithHostIPCDefined = ` 1209 apiVersion: v1 1210 kind: Pod 1211 metadata: 1212 name: test-hostipc 1213 spec: 1214 hostIPC: true 1215 containers: 1216 - name: testimage 1217 image: ` + CITEST_IMAGE + ` 1218 command: ['ls', '-l', '/proc/self/ns/ipc'] 1219 restartPolicy: Never 1220 ` 1221 1222 var podWithSysctlDefined = ` 1223 apiVersion: v1 1224 kind: Pod 1225 metadata: 1226 name: test-sysctl 1227 spec: 1228 securityContext: 1229 sysctls: 1230 - name: kernel.msgmax 1231 value: "65535" 1232 - name: net.core.somaxconn 1233 value: "65535" 1234 containers: 1235 - name: testimage 1236 image: ` + CITEST_IMAGE + ` 1237 command: 1238 - "/bin/sh" 1239 - "-c" 1240 - "sysctl kernel.msgmax;sysctl net.core.somaxconn" 1241 restartPolicy: Never 1242 ` 1243 1244 var podWithSysctlHostNetDefined = ` 1245 apiVersion: v1 1246 kind: Pod 1247 metadata: 1248 name: test-sysctl 1249 spec: 1250 securityContext: 1251 sysctls: 1252 - name: kernel.msgmax 1253 value: "65535" 1254 - name: net.core.somaxconn 1255 value: "65535" 1256 hostNetwork: true 1257 containers: 1258 - name: testimage 1259 image: ` + CITEST_IMAGE + ` 1260 command: 1261 - "/bin/sh" 1262 - "-c" 1263 - "sysctl kernel.msgmax" 1264 ` 1265 1266 var listPodAndConfigMap = ` 1267 apiVersion: v1 1268 kind: List 1269 items: 1270 - apiVersion: v1 1271 kind: ConfigMap 1272 metadata: 1273 name: test-list-configmap 1274 data: 1275 foo: bar 1276 - apiVersion: v1 1277 kind: Pod 1278 metadata: 1279 name: test-list-pod 1280 spec: 1281 containers: 1282 - name: container 1283 image: ` + CITEST_IMAGE + ` 1284 command: [ "/bin/sh", "-c", "env" ] 1285 env: 1286 - name: FOO 1287 valueFrom: 1288 configMapKeyRef: 1289 name: test-list-configmap 1290 key: foo 1291 restartPolicy: Never 1292 ` 1293 1294 var ( 1295 defaultCtrName = "testCtr" 1296 defaultCtrCmd = []string{"top"} 1297 defaultCtrArg = []string{"-d", "1.5"} 1298 defaultCtrImage = CITEST_IMAGE 1299 defaultPodName = "testPod" 1300 defaultVolName = "testVol" 1301 defaultDaemonSetName = "testDaemonSet" 1302 defaultDeploymentName = "testDeployment" 1303 defaultConfigMapName = "testConfigMap" 1304 defaultSecretName = "testSecret" 1305 defaultPVCName = "testPVC" 1306 seccompLinkEPERM = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"link","action":"SCMP_ACT_ERRNO"}]}`) 1307 // CPU Period in ms 1308 defaultCPUPeriod = 100 1309 // Default secret in JSON. Note that the values ("foo" and "bar") are base64 encoded. 1310 defaultSecret = []byte(`{"FOO":"Zm9v","BAR":"YmFy"}`) 1311 ) 1312 1313 // getKubeYaml returns a kubernetes YAML document. 1314 func getKubeYaml(kind string, object interface{}) (string, error) { 1315 var yamlTemplate string 1316 templateBytes := &bytes.Buffer{} 1317 1318 switch kind { 1319 case "configmap": 1320 yamlTemplate = configMapYamlTemplate 1321 case "pod": 1322 yamlTemplate = podYamlTemplate 1323 case "daemonset": 1324 yamlTemplate = daemonSetYamlTemplate 1325 case "deployment": 1326 yamlTemplate = deploymentYamlTemplate 1327 case "persistentVolumeClaim": 1328 yamlTemplate = persistentVolumeClaimYamlTemplate 1329 case "secret": 1330 yamlTemplate = secretYamlTemplate 1331 default: 1332 return "", fmt.Errorf("unsupported kubernetes kind") 1333 } 1334 1335 t, err := template.New(kind).Parse(yamlTemplate) 1336 if err != nil { 1337 return "", err 1338 } 1339 1340 if err := t.Execute(templateBytes, object); err != nil { 1341 return "", err 1342 } 1343 1344 return templateBytes.String(), nil 1345 } 1346 1347 // generateKubeYaml writes a kubernetes YAML document. 1348 func generateKubeYaml(kind string, object interface{}, pathname string) error { 1349 k, err := getKubeYaml(kind, object) 1350 if err != nil { 1351 return err 1352 } 1353 1354 return writeYaml(k, pathname) 1355 } 1356 1357 // generateMultiDocKubeYaml writes multiple kube objects in one Yaml document. 1358 func generateMultiDocKubeYaml(kubeObjects []string, pathname string) error { 1359 var multiKube string 1360 1361 for _, k := range kubeObjects { 1362 multiKube += "---\n" 1363 multiKube += k 1364 } 1365 1366 return writeYaml(multiKube, pathname) 1367 } 1368 1369 func createSecret(podmanTest *PodmanTestIntegration, name string, value []byte) { //nolint:unparam 1370 secretFilePath := filepath.Join(podmanTest.TempDir, "secret") 1371 err := os.WriteFile(secretFilePath, value, 0755) 1372 Expect(err).ToNot(HaveOccurred()) 1373 1374 secret := podmanTest.Podman([]string{"secret", "create", name, secretFilePath}) 1375 secret.WaitWithDefaultTimeout() 1376 Expect(secret).Should(ExitCleanly()) 1377 } 1378 1379 // Secret describes the options a kube yaml can be configured at secret level 1380 type Secret struct { 1381 Name string 1382 Data map[string]string 1383 } 1384 1385 func getSecret(options ...secretOption) *Secret { 1386 secret := Secret{ 1387 Name: defaultSecretName, 1388 Data: map[string]string{}, 1389 } 1390 1391 for _, option := range options { 1392 option(&secret) 1393 } 1394 1395 return &secret 1396 } 1397 1398 type secretOption func(*Secret) 1399 1400 func withSecretName(name string) secretOption { 1401 return func(secret *Secret) { 1402 secret.Name = name 1403 } 1404 } 1405 1406 func withSecretData(k, v string) secretOption { 1407 return func(secret *Secret) { 1408 secret.Data[k] = base64.StdEncoding.EncodeToString([]byte(v)) 1409 } 1410 } 1411 1412 // CM describes the options a kube yaml can be configured at configmap level 1413 type CM struct { 1414 Name string 1415 Data map[string]string 1416 } 1417 1418 func getConfigMap(options ...configMapOption) *CM { 1419 cm := CM{ 1420 Name: defaultConfigMapName, 1421 Data: map[string]string{}, 1422 } 1423 1424 for _, option := range options { 1425 option(&cm) 1426 } 1427 1428 return &cm 1429 } 1430 1431 type configMapOption func(*CM) 1432 1433 func withConfigMapName(name string) configMapOption { 1434 return func(configmap *CM) { 1435 configmap.Name = name 1436 } 1437 } 1438 1439 func withConfigMapData(k, v string) configMapOption { 1440 return func(configmap *CM) { 1441 configmap.Data[k] = v 1442 } 1443 } 1444 1445 // PVC describes the options a kube yaml can be configured at persistent volume claim level 1446 type PVC struct { 1447 Name string 1448 Annotations map[string]string 1449 } 1450 1451 func getPVC(options ...pvcOption) *PVC { 1452 pvc := PVC{ 1453 Name: defaultPVCName, 1454 Annotations: map[string]string{}, 1455 } 1456 1457 for _, option := range options { 1458 option(&pvc) 1459 } 1460 1461 return &pvc 1462 } 1463 1464 type pvcOption func(*PVC) 1465 1466 func withPVCName(name string) pvcOption { 1467 return func(pvc *PVC) { 1468 pvc.Name = name 1469 } 1470 } 1471 1472 func withPVCAnnotations(k, v string) pvcOption { 1473 return func(pvc *PVC) { 1474 pvc.Annotations[k] = v 1475 } 1476 } 1477 1478 // Pod describes the options a kube yaml can be configured at pod level 1479 type Pod struct { 1480 Name string 1481 RestartPolicy string 1482 Hostname string 1483 HostNetwork bool 1484 HostUsers *bool 1485 HostAliases []HostAlias 1486 Ctrs []*Ctr 1487 InitCtrs []*Ctr 1488 Volumes []*Volume 1489 Labels map[string]string 1490 Annotations map[string]string 1491 SecurityContext bool 1492 RunAsUser string 1493 RunAsGroup string 1494 } 1495 1496 type HostAlias struct { 1497 IP string 1498 HostName []string 1499 } 1500 1501 // getPod takes a list of podOptions and returns a pod with sane defaults 1502 // and the configured options 1503 // if no containers are added, it will add the default container 1504 func getPod(options ...podOption) *Pod { 1505 p := Pod{ 1506 Name: defaultPodName, 1507 RestartPolicy: "Never", 1508 Hostname: "", 1509 HostNetwork: false, 1510 HostAliases: nil, 1511 Ctrs: make([]*Ctr, 0), 1512 InitCtrs: make([]*Ctr, 0), 1513 Volumes: make([]*Volume, 0), 1514 Labels: make(map[string]string), 1515 Annotations: make(map[string]string), 1516 } 1517 for _, option := range options { 1518 option(&p) 1519 } 1520 if len(p.Ctrs) == 0 { 1521 p.Ctrs = []*Ctr{getCtr()} 1522 } 1523 return &p 1524 } 1525 1526 type podOption func(*Pod) 1527 1528 func withPodSecurityContext(sc bool) podOption { 1529 return func(p *Pod) { 1530 p.SecurityContext = sc 1531 } 1532 } 1533 1534 func withPodRunAsUser(runAsUser string) podOption { 1535 return func(p *Pod) { 1536 p.RunAsUser = runAsUser 1537 } 1538 } 1539 1540 func withPodRunAsGroup(runAsGroup string) podOption { 1541 return func(p *Pod) { 1542 p.RunAsGroup = runAsGroup 1543 } 1544 } 1545 1546 func withPodName(name string) podOption { 1547 return func(pod *Pod) { 1548 pod.Name = name 1549 } 1550 } 1551 1552 func withHostname(h string) podOption { 1553 return func(pod *Pod) { 1554 pod.Hostname = h 1555 } 1556 } 1557 1558 func withHostAliases(ip string, host []string) podOption { 1559 return func(pod *Pod) { 1560 pod.HostAliases = append(pod.HostAliases, HostAlias{ 1561 IP: ip, 1562 HostName: host, 1563 }) 1564 } 1565 } 1566 1567 func withCtr(c *Ctr) podOption { 1568 return func(pod *Pod) { 1569 pod.Ctrs = append(pod.Ctrs, c) 1570 } 1571 } 1572 1573 func withPodInitCtr(ic *Ctr) podOption { 1574 return func(pod *Pod) { 1575 pod.InitCtrs = append(pod.InitCtrs, ic) 1576 } 1577 } 1578 1579 func withRestartPolicy(policy string) podOption { 1580 return func(pod *Pod) { 1581 pod.RestartPolicy = policy 1582 } 1583 } 1584 1585 func withLabel(k, v string) podOption { 1586 return func(pod *Pod) { 1587 pod.Labels[k] = v 1588 } 1589 } 1590 1591 func withAnnotation(k, v string) podOption { 1592 return func(pod *Pod) { 1593 pod.Annotations[k] = v 1594 } 1595 } 1596 1597 func withVolume(v *Volume) podOption { 1598 return func(pod *Pod) { 1599 pod.Volumes = append(pod.Volumes, v) 1600 } 1601 } 1602 1603 func withHostNetwork() podOption { 1604 return func(pod *Pod) { 1605 pod.HostNetwork = true 1606 } 1607 } 1608 1609 func withHostUsers(val bool) podOption { 1610 return func(pod *Pod) { 1611 pod.HostUsers = &val 1612 } 1613 } 1614 1615 // Deployment describes the options a kube yaml can be configured at deployment level 1616 type DaemonSet struct { 1617 Name string 1618 Labels map[string]string 1619 Annotations map[string]string 1620 PodTemplate *Pod 1621 } 1622 1623 func getDaemonSet(options ...daemonSetOption) *DaemonSet { 1624 d := DaemonSet{ 1625 Name: defaultDaemonSetName, 1626 Labels: make(map[string]string), 1627 Annotations: make(map[string]string), 1628 PodTemplate: getPod(), 1629 } 1630 for _, option := range options { 1631 option(&d) 1632 } 1633 1634 return &d 1635 } 1636 1637 type daemonSetOption func(*DaemonSet) 1638 1639 type Deployment struct { 1640 Name string 1641 Replicas int32 1642 Labels map[string]string 1643 Annotations map[string]string 1644 PodTemplate *Pod 1645 } 1646 1647 func getDeployment(options ...deploymentOption) *Deployment { 1648 d := Deployment{ 1649 Name: defaultDeploymentName, 1650 Replicas: 1, 1651 Labels: make(map[string]string), 1652 Annotations: make(map[string]string), 1653 PodTemplate: getPod(), 1654 } 1655 for _, option := range options { 1656 option(&d) 1657 } 1658 1659 return &d 1660 } 1661 1662 type deploymentOption func(*Deployment) 1663 1664 func withDeploymentAnnotation(k, v string) deploymentOption { 1665 return func(deployment *Deployment) { 1666 deployment.Annotations[k] = v 1667 } 1668 } 1669 1670 func withPod(pod *Pod) deploymentOption { 1671 return func(d *Deployment) { 1672 d.PodTemplate = pod 1673 } 1674 } 1675 1676 func withReplicas(replicas int32) deploymentOption { 1677 return func(d *Deployment) { 1678 d.Replicas = replicas 1679 } 1680 } 1681 1682 // getPodNameInDeployment returns the Pod object 1683 // with just its name set, so that it can be passed around 1684 // and into getCtrNameInPod for ease of testing 1685 func getPodNameInDaemonSet(d *DaemonSet) Pod { 1686 p := Pod{} 1687 p.Name = fmt.Sprintf("%s-pod", d.Name) 1688 1689 return p 1690 } 1691 1692 // getPodNameInDeployment returns the Pod object 1693 // with just its name set, so that it can be passed around 1694 // and into getCtrNameInPod for ease of testing 1695 func getPodNameInDeployment(d *Deployment) Pod { 1696 p := Pod{} 1697 p.Name = fmt.Sprintf("%s-pod", d.Name) 1698 1699 return p 1700 } 1701 1702 // Ctr describes the options a kube yaml can be configured at container level 1703 type Ctr struct { 1704 Name string 1705 Image string 1706 Cmd []string 1707 Arg []string 1708 CPURequest string 1709 CPULimit string 1710 MemoryRequest string 1711 MemoryLimit string 1712 SecurityContext bool 1713 Caps bool 1714 CapAdd []string 1715 CapDrop []string 1716 PullPolicy string 1717 HostIP string 1718 Port string 1719 VolumeMount bool 1720 VolumeMountPath string 1721 VolumeName string 1722 VolumeSubPath string 1723 VolumeReadOnly bool 1724 Env []Env 1725 EnvFrom []EnvFrom 1726 InitCtrType string 1727 RunAsUser string 1728 RunAsGroup string 1729 } 1730 1731 // getCtr takes a list of ctrOptions and returns a Ctr with sane defaults 1732 // and the configured options 1733 func getCtr(options ...ctrOption) *Ctr { 1734 c := Ctr{ 1735 Name: defaultCtrName, 1736 Image: defaultCtrImage, 1737 Cmd: defaultCtrCmd, 1738 Arg: defaultCtrArg, 1739 SecurityContext: true, 1740 Caps: false, 1741 CapAdd: nil, 1742 CapDrop: nil, 1743 PullPolicy: "missing", 1744 HostIP: "", 1745 Port: "", 1746 VolumeMount: false, 1747 VolumeMountPath: "", 1748 VolumeName: "", 1749 VolumeReadOnly: false, 1750 VolumeSubPath: "", 1751 Env: []Env{}, 1752 EnvFrom: []EnvFrom{}, 1753 InitCtrType: "", 1754 } 1755 for _, option := range options { 1756 option(&c) 1757 } 1758 return &c 1759 } 1760 1761 type ctrOption func(*Ctr) 1762 1763 func withName(name string) ctrOption { 1764 return func(c *Ctr) { 1765 c.Name = name 1766 } 1767 } 1768 1769 func withInitCtr() ctrOption { 1770 return func(c *Ctr) { 1771 c.InitCtrType = define.AlwaysInitContainer 1772 } 1773 } 1774 1775 func withCmd(cmd []string) ctrOption { 1776 return func(c *Ctr) { 1777 c.Cmd = cmd 1778 } 1779 } 1780 1781 func withArg(arg []string) ctrOption { 1782 return func(c *Ctr) { 1783 c.Arg = arg 1784 } 1785 } 1786 1787 func withImage(img string) ctrOption { 1788 return func(c *Ctr) { 1789 c.Image = img 1790 } 1791 } 1792 1793 func withCPURequest(request string) ctrOption { 1794 return func(c *Ctr) { 1795 c.CPURequest = request 1796 } 1797 } 1798 1799 func withCPULimit(limit string) ctrOption { 1800 return func(c *Ctr) { 1801 c.CPULimit = limit 1802 } 1803 } 1804 1805 func withMemoryRequest(request string) ctrOption { 1806 return func(c *Ctr) { 1807 c.MemoryRequest = request 1808 } 1809 } 1810 1811 func withMemoryLimit(limit string) ctrOption { 1812 return func(c *Ctr) { 1813 c.MemoryLimit = limit 1814 } 1815 } 1816 1817 func withSecurityContext(sc bool) ctrOption { 1818 return func(c *Ctr) { 1819 c.SecurityContext = sc 1820 } 1821 } 1822 1823 func withRunAsUser(runAsUser string) ctrOption { 1824 return func(c *Ctr) { 1825 c.RunAsUser = runAsUser 1826 } 1827 } 1828 1829 func withRunAsGroup(runAsGroup string) ctrOption { 1830 return func(c *Ctr) { 1831 c.RunAsGroup = runAsGroup 1832 } 1833 } 1834 1835 func withCapAdd(caps []string) ctrOption { 1836 return func(c *Ctr) { 1837 c.CapAdd = caps 1838 c.Caps = true 1839 } 1840 } 1841 1842 func withCapDrop(caps []string) ctrOption { 1843 return func(c *Ctr) { 1844 c.CapDrop = caps 1845 c.Caps = true 1846 } 1847 } 1848 1849 func withPullPolicy(policy string) ctrOption { 1850 return func(c *Ctr) { 1851 c.PullPolicy = policy 1852 } 1853 } 1854 1855 func withHostIP(ip string, port string) ctrOption { 1856 return func(c *Ctr) { 1857 c.HostIP = ip 1858 c.Port = port 1859 } 1860 } 1861 1862 func withVolumeMount(mountPath, subpath string, readonly bool) ctrOption { 1863 return func(c *Ctr) { 1864 c.VolumeMountPath = mountPath 1865 c.VolumeName = defaultVolName 1866 c.VolumeReadOnly = readonly 1867 c.VolumeMount = true 1868 if len(subpath) > 0 { 1869 c.VolumeSubPath = subpath 1870 } 1871 } 1872 } 1873 1874 func withEnv(name, value, valueFrom, refName, refKey string, optional bool) ctrOption { //nolint:unparam 1875 return func(c *Ctr) { 1876 e := Env{ 1877 Name: name, 1878 Value: value, 1879 ValueFrom: valueFrom, 1880 RefName: refName, 1881 RefKey: refKey, 1882 Optional: optional, 1883 } 1884 1885 c.Env = append(c.Env, e) 1886 } 1887 } 1888 1889 func withEnvFrom(name, from string, optional bool) ctrOption { 1890 return func(c *Ctr) { 1891 e := EnvFrom{ 1892 Name: name, 1893 From: from, 1894 Optional: optional, 1895 } 1896 1897 c.EnvFrom = append(c.EnvFrom, e) 1898 } 1899 } 1900 1901 func makeCtrNameInPod(pod *Pod, containerName string) string { 1902 return fmt.Sprintf("%s-%s", pod.Name, containerName) 1903 } 1904 1905 func getCtrNameInPod(pod *Pod) string { 1906 return makeCtrNameInPod(pod, defaultCtrName) 1907 } 1908 1909 type HostPath struct { 1910 Path string 1911 Type string 1912 } 1913 1914 type PersistentVolumeClaim struct { 1915 ClaimName string 1916 } 1917 1918 type ConfigMap struct { 1919 Name string 1920 Items []map[string]string 1921 Optional bool 1922 DefaultMode int32 1923 } 1924 1925 type SecretVol struct { 1926 SecretName string 1927 Items []map[string]string 1928 Optional bool 1929 DefaultMode int32 1930 } 1931 1932 type EmptyDir struct{} 1933 1934 type Volume struct { 1935 VolumeType string 1936 Name string 1937 HostPath 1938 PersistentVolumeClaim 1939 ConfigMap 1940 EmptyDir 1941 SecretVol 1942 } 1943 1944 // getHostPathVolume takes a type and a location for a HostPath 1945 // volume giving it a default name of volName 1946 func getHostPathVolume(vType, vPath string) *Volume { 1947 return &Volume{ 1948 VolumeType: "HostPath", 1949 Name: defaultVolName, 1950 HostPath: HostPath{ 1951 Path: vPath, 1952 Type: vType, 1953 }, 1954 } 1955 } 1956 1957 // getHostPathVolume takes a name for a Persistentvolumeclaim 1958 // volume giving it a default name of volName 1959 func getPersistentVolumeClaimVolume(vName string) *Volume { 1960 return &Volume{ 1961 VolumeType: "PersistentVolumeClaim", 1962 Name: defaultVolName, 1963 PersistentVolumeClaim: PersistentVolumeClaim{ 1964 ClaimName: vName, 1965 }, 1966 } 1967 } 1968 1969 // getConfigMap returns a new ConfigMap Volume given the name and items 1970 // of the ConfigMap. 1971 func getConfigMapVolume(vName string, items []map[string]string, optional bool, defaultMode *int32) *Volume { //nolint:unparam 1972 vol := &Volume{ 1973 VolumeType: "ConfigMap", 1974 Name: defaultVolName, 1975 ConfigMap: ConfigMap{ 1976 Name: vName, 1977 Items: items, 1978 Optional: optional, 1979 DefaultMode: v1.ConfigMapVolumeSourceDefaultMode, 1980 }, 1981 } 1982 if defaultMode != nil { 1983 vol.ConfigMap.DefaultMode = *defaultMode 1984 } 1985 return vol 1986 } 1987 1988 func getSecretVolume(vName string, items []map[string]string, optional bool, defaultMode *int32) *Volume { 1989 vol := &Volume{ 1990 VolumeType: "Secret", 1991 Name: defaultVolName, 1992 SecretVol: SecretVol{ 1993 SecretName: vName, 1994 Items: items, 1995 Optional: optional, 1996 DefaultMode: v1.SecretVolumeSourceDefaultMode, 1997 }, 1998 } 1999 if defaultMode != nil { 2000 vol.SecretVol.DefaultMode = *defaultMode 2001 } 2002 return vol 2003 } 2004 2005 func getEmptyDirVolume() *Volume { 2006 return &Volume{ 2007 VolumeType: "EmptyDir", 2008 Name: defaultVolName, 2009 EmptyDir: EmptyDir{}, 2010 } 2011 } 2012 2013 type Env struct { 2014 Name string 2015 Value string 2016 ValueFrom string 2017 RefName string 2018 RefKey string 2019 Optional bool 2020 } 2021 2022 type EnvFrom struct { 2023 Name string 2024 From string 2025 Optional bool 2026 } 2027 2028 func milliCPUToQuota(milliCPU string) int { 2029 milli, _ := strconv.Atoi(strings.Trim(milliCPU, "m")) 2030 return milli * defaultCPUPeriod 2031 } 2032 2033 func createSourceTarFile(fileName, fileContent, tarFilePath string) error { 2034 dir := GinkgoT().TempDir() 2035 2036 file, err := os.Create(filepath.Join(dir, fileName)) 2037 if err != nil { 2038 return err 2039 } 2040 2041 _, err = file.WriteString(fileContent) 2042 if err != nil { 2043 return err 2044 } 2045 2046 err = file.Close() 2047 if err != nil { 2048 return err 2049 } 2050 2051 tarFile, err := os.Create(tarFilePath) 2052 if err != nil { 2053 return err 2054 } 2055 defer tarFile.Close() 2056 2057 return utils.TarToFilesystem(dir, tarFile) 2058 } 2059 2060 func createAndTestSecret(podmanTest *PodmanTestIntegration, secretYamlString, secretName, fileName string) { 2061 err := writeYaml(secretYamlString, fileName) 2062 Expect(err).ToNot(HaveOccurred()) 2063 2064 kube := podmanTest.Podman([]string{"kube", "play", fileName}) 2065 kube.WaitWithDefaultTimeout() 2066 Expect(kube).Should(ExitCleanly()) 2067 2068 secretList := podmanTest.Podman([]string{"secret", "list"}) 2069 secretList.WaitWithDefaultTimeout() 2070 Expect(secretList).Should(ExitCleanly()) 2071 Expect(secretList.OutputToString()).Should(ContainSubstring(secretName)) 2072 2073 // test if secret ID is printed once created 2074 secretListQuiet := podmanTest.Podman([]string{"secret", "list", "--quiet"}) 2075 secretListQuiet.WaitWithDefaultTimeout() 2076 Expect(secretListQuiet).Should(ExitCleanly()) 2077 Expect(kube.OutputToString()).Should(ContainSubstring(secretListQuiet.OutputToString())) 2078 } 2079 2080 func deleteAndTestSecret(podmanTest *PodmanTestIntegration, secretName string) { 2081 secretRm := podmanTest.Podman([]string{"secret", "rm", secretName}) 2082 secretRm.WaitWithDefaultTimeout() 2083 Expect(secretRm).Should(ExitCleanly()) 2084 } 2085 2086 func testPodWithSecret(podmanTest *PodmanTestIntegration, podYamlString, fileName string, succeed, exists bool) { 2087 err := writeYaml(podYamlString, fileName) 2088 Expect(err).ToNot(HaveOccurred()) 2089 2090 kube := podmanTest.Podman([]string{"kube", "play", fileName}) 2091 kube.WaitWithDefaultTimeout() 2092 if !succeed { 2093 Expect(kube).Should(Exit(-1)) 2094 return 2095 } 2096 Expect(kube).Should(ExitCleanly()) 2097 2098 exec := podmanTest.Podman([]string{"exec", "mypod-myctr", "cat", "/etc/foo/username"}) 2099 exec.WaitWithDefaultTimeout() 2100 if exists { 2101 Expect(exec).Should(ExitCleanly()) 2102 username, _ := base64.StdEncoding.DecodeString("dXNlcg==") 2103 Expect(exec.OutputToString()).Should(ContainSubstring(string(username))) 2104 } else { 2105 Expect(exec).Should(Exit(-1)) 2106 } 2107 2108 podRm := podmanTest.Podman([]string{"pod", "rm", "-f", "mypod"}) 2109 podRm.WaitWithDefaultTimeout() 2110 Expect(podRm).Should(ExitCleanly()) 2111 } 2112 2113 func testHTTPServer(port string, shouldErr bool, expectedResponse string) { 2114 address := url.URL{ 2115 Scheme: "http", 2116 Host: net.JoinHostPort("localhost", port), 2117 } 2118 2119 interval := 250 * time.Millisecond 2120 var err error 2121 var resp *http.Response 2122 for i := 0; i < 6; i++ { 2123 resp, err = http.Get(address.String()) 2124 if err != nil && shouldErr { 2125 Expect(err.Error()).To(ContainSubstring(expectedResponse)) 2126 return 2127 } 2128 if err == nil { 2129 defer resp.Body.Close() 2130 break 2131 } 2132 time.Sleep(interval) 2133 interval *= 2 2134 } 2135 Expect(err).ToNot(HaveOccurred()) 2136 2137 body, err := io.ReadAll(resp.Body) 2138 Expect(err).ToNot(HaveOccurred()) 2139 Expect(string(body)).Should(Equal(expectedResponse)) 2140 } 2141 2142 func verifyPodPorts(podmanTest *PodmanTestIntegration, podName string, ports ...string) { 2143 podInspect := podmanTest.Podman([]string{"pod", "inspect", podName, "--format", "{{.InfraContainerID}}"}) 2144 podInspect.WaitWithDefaultTimeout() 2145 Expect(podInspect).To(ExitCleanly()) 2146 infraID := podInspect.OutputToString() 2147 2148 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.NetworkSettings.Ports}}", infraID}) 2149 inspect.WaitWithDefaultTimeout() 2150 Expect(inspect).To(ExitCleanly()) 2151 2152 for _, port := range ports { 2153 Expect(inspect.OutputToString()).Should(ContainSubstring(port)) 2154 } 2155 } 2156 2157 var _ = Describe("Podman kube play", func() { 2158 var kubeYaml string 2159 2160 BeforeEach(func() { 2161 kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml") 2162 }) 2163 2164 It("[play kube] fail with yaml of unsupported kind", func() { 2165 err := writeYaml(unknownKindYaml, kubeYaml) 2166 Expect(err).ToNot(HaveOccurred()) 2167 2168 kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) 2169 kube.WaitWithDefaultTimeout() 2170 expect := "YAML document does not contain any supported kube kind" 2171 // On anything kube-related, podman-remote emits a magic prefix 2172 // that regular podman doesn't. Test for it here, but let's not 2173 // do so in every single test. 2174 if IsRemote() { 2175 expect = "playing YAML file: " + expect 2176 } 2177 Expect(kube).To(ExitWithError(125, expect)) 2178 }) 2179 2180 It("fail with custom selinux label", func() { 2181 if !selinux.GetEnabled() { 2182 Skip("SELinux not enabled") 2183 } 2184 err := writeYaml(selinuxLabelPodYaml, kubeYaml) 2185 Expect(err).ToNot(HaveOccurred()) 2186 2187 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2188 kube.WaitWithDefaultTimeout() 2189 Expect(kube).Should(ExitCleanly()) 2190 2191 inspect := podmanTest.Podman([]string{"inspect", "label-pod-test", "--format", "'{{ .ProcessLabel }}'"}) 2192 inspect.WaitWithDefaultTimeout() 2193 label := inspect.OutputToString() 2194 2195 Expect(label).To(ContainSubstring("unconfined_u:system_r:spc_t:s0")) 2196 }) 2197 2198 It("--no-host", func() { 2199 err := writeYaml(checkInfraImagePodYaml, kubeYaml) 2200 Expect(err).ToNot(HaveOccurred()) 2201 2202 kube := podmanTest.Podman([]string{"kube", "play", "--no-hosts", kubeYaml}) 2203 kube.WaitWithDefaultTimeout() 2204 Expect(kube).Should(ExitCleanly()) 2205 2206 podInspect := podmanTest.Podman([]string{"pod", "inspect", "check-infra-image"}) 2207 podInspect.WaitWithDefaultTimeout() 2208 Expect(podInspect).Should(ExitCleanly()) 2209 2210 data := podInspect.InspectPodToJSON() 2211 for _, ctr := range data.Containers { 2212 if strings.HasSuffix(ctr.Name, "-infra") { 2213 continue 2214 } 2215 exec := podmanTest.Podman([]string{"exec", ctr.ID, "cat", "/etc/hosts"}) 2216 exec.WaitWithDefaultTimeout() 2217 Expect(exec).Should(ExitCleanly()) 2218 Expect(exec.OutputToString()).To(Not(ContainSubstring("check-infra-image"))) 2219 } 2220 }) 2221 2222 It("with non-existing configmap", func() { 2223 err := writeYaml(podWithoutConfigMapDefined, kubeYaml) 2224 Expect(err).ToNot(HaveOccurred()) 2225 2226 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2227 kube.WaitWithDefaultTimeout() 2228 Expect(kube).Should(ExitWithError(125, `failed to create volume "mycm": no such ConfigMap "mycm"`)) 2229 }) 2230 2231 It("test HostAliases with --no-hosts", func() { 2232 pod := getPod(withHostAliases("192.168.1.2", []string{ 2233 "test1.podman.io", 2234 "test2.podman.io", 2235 }), 2236 withHostAliases("192.168.1.3", []string{ 2237 "test3.podman.io", 2238 "test4.podman.io", 2239 }), 2240 ) 2241 err := generateKubeYaml("pod", pod, kubeYaml) 2242 Expect(err).ToNot(HaveOccurred()) 2243 2244 kube := podmanTest.Podman([]string{"kube", "play", "--no-hosts", kubeYaml}) 2245 kube.WaitWithDefaultTimeout() 2246 Expect(kube).Should(ExitWithError(125, "HostAliases in yaml file will not work with --no-hosts")) 2247 }) 2248 2249 It("should use customized infra_image", func() { 2250 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 2251 2252 infraImage := INFRA_IMAGE 2253 err := os.WriteFile(conffile, []byte(fmt.Sprintf("[engine]\ninfra_image=\"%s\"\n", infraImage)), 0644) 2254 Expect(err).ToNot(HaveOccurred()) 2255 2256 os.Setenv("CONTAINERS_CONF", conffile) 2257 2258 if IsRemote() { 2259 podmanTest.RestartRemoteService() 2260 } 2261 2262 err = writeYaml(checkInfraImagePodYaml, kubeYaml) 2263 Expect(err).ToNot(HaveOccurred()) 2264 2265 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2266 kube.WaitWithDefaultTimeout() 2267 Expect(kube).Should(ExitCleanly()) 2268 2269 podInspect := podmanTest.Podman([]string{"inspect", "check-infra-image", "--format", "{{ .InfraContainerID }}"}) 2270 podInspect.WaitWithDefaultTimeout() 2271 infraContainerID := podInspect.OutputToString() 2272 2273 conInspect := podmanTest.Podman([]string{"inspect", infraContainerID, "--format", "{{ .ImageName }}"}) 2274 conInspect.WaitWithDefaultTimeout() 2275 infraContainerImage := conInspect.OutputToString() 2276 Expect(infraContainerImage).To(Equal(infraImage)) 2277 }) 2278 2279 It("should share ipc,net,uts when shareProcessNamespace is set", func() { 2280 SkipIfRootless("Requires root privileges for sharing few namespaces") 2281 err := writeYaml(sharedNamespacePodYaml, kubeYaml) 2282 Expect(err).ToNot(HaveOccurred()) 2283 2284 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2285 kube.WaitWithDefaultTimeout() 2286 Expect(kube).Should(ExitCleanly()) 2287 2288 inspect := podmanTest.Podman([]string{"inspect", "testpod1", "--format", "'{{ .SharedNamespaces }}'"}) 2289 inspect.WaitWithDefaultTimeout() 2290 sharednamespaces := inspect.OutputToString() 2291 Expect(sharednamespaces).To(ContainSubstring("ipc")) 2292 Expect(sharednamespaces).To(ContainSubstring("net")) 2293 Expect(sharednamespaces).To(ContainSubstring("uts")) 2294 Expect(sharednamespaces).To(ContainSubstring("pid")) 2295 }) 2296 2297 It("should be able to run image where workdir is a symlink", func() { 2298 session := podmanTest.Podman([]string{ 2299 "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink", 2300 }) 2301 session.WaitWithDefaultTimeout() 2302 Expect(session).Should(ExitCleanly()) 2303 2304 err := writeYaml(workdirSymlinkPodYaml, kubeYaml) 2305 Expect(err).ToNot(HaveOccurred()) 2306 2307 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2308 kube.WaitWithDefaultTimeout() 2309 Expect(kube).Should(ExitCleanly()) 2310 2311 wait := podmanTest.Podman([]string{"wait", "test-symlink-test-symlink"}) 2312 wait.WaitWithDefaultTimeout() 2313 Expect(wait).Should(ExitCleanly()) 2314 Expect(wait.OutputToString()).To(Equal("0")) 2315 2316 logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-symlink-test-symlink", "test-symlink"}) 2317 logs.WaitWithDefaultTimeout() 2318 Expect(logs).Should(ExitCleanly()) 2319 Expect(logs.OutputToString()).To(ContainSubstring("hello")) 2320 }) 2321 2322 It("should not rename pod if container in pod has same name", func() { 2323 err := writeYaml(podnameEqualsContainerNameYaml, kubeYaml) 2324 Expect(err).ToNot(HaveOccurred()) 2325 2326 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2327 kube.WaitWithDefaultTimeout() 2328 Expect(kube).Should(ExitCleanly()) 2329 2330 testPodCreated := podmanTest.Podman([]string{"pod", "exists", "podnameEqualsContainerNameYaml"}) 2331 testPodCreated.WaitWithDefaultTimeout() 2332 Expect(testPodCreated).Should(ExitCleanly()) 2333 2334 inspect := podmanTest.Podman([]string{"inspect", "podnameEqualsContainerNameYaml"}) 2335 inspect.WaitWithDefaultTimeout() 2336 podInspect := inspect.InspectPodArrToJSON() 2337 Expect(podInspect).Should(HaveLen(1)) 2338 var containerNames []string 2339 for _, container := range podInspect[0].Containers { 2340 containerNames = append(containerNames, container.Name) 2341 } 2342 Expect(containerNames).To(ContainElement("podnameEqualsContainerNameYaml-podnameEqualsContainerNameYaml")) 2343 }) 2344 2345 It("should error if pod doesn't have a name", func() { 2346 err := writeYaml(podWithoutAName, kubeYaml) 2347 Expect(err).ToNot(HaveOccurred()) 2348 2349 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2350 kube.WaitWithDefaultTimeout() 2351 Expect(kube).Should(ExitWithError(125, "pod does not have a name")) 2352 }) 2353 2354 It("support container liveness probe", func() { 2355 err := writeYaml(livenessProbePodYaml, kubeYaml) 2356 Expect(err).ToNot(HaveOccurred()) 2357 2358 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2359 kube.WaitWithDefaultTimeout() 2360 Expect(kube).Should(ExitCleanly()) 2361 2362 inspect := podmanTest.Podman([]string{"inspect", "liveness-probe-pod-testimage", "--format", "'{{ .Config.Healthcheck }}'"}) 2363 inspect.WaitWithDefaultTimeout() 2364 healthcheckcmd := inspect.OutputToString() 2365 // check if CMD-SHELL based equivalent health check is added to container 2366 Expect(healthcheckcmd).To(ContainSubstring("[CMD echo hello]")) 2367 }) 2368 2369 It("liveness probe should fail", func() { 2370 err := writeYaml(livenessProbeUnhealthyPodYaml, kubeYaml) 2371 Expect(err).ToNot(HaveOccurred()) 2372 2373 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2374 kube.WaitWithDefaultTimeout() 2375 Expect(kube).Should(ExitCleanly()) 2376 2377 time.Sleep(2 * time.Second) 2378 hc := podmanTest.Podman([]string{"healthcheck", "run", "liveness-unhealthy-probe-pod-testimage"}) 2379 hc.WaitWithDefaultTimeout() 2380 hcoutput := hc.OutputToString() 2381 Expect(hcoutput).To(ContainSubstring(define.HealthCheckUnhealthy)) 2382 }) 2383 2384 It("support container startup probe", func() { 2385 ctrName := "startup-healthy-probe-pod-testimage" 2386 err := writeYaml(startupProbePodYaml, kubeYaml) 2387 Expect(err).ToNot(HaveOccurred()) 2388 2389 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2390 kube.WaitWithDefaultTimeout() 2391 Expect(kube).Should(ExitCleanly()) 2392 2393 time.Sleep(2 * time.Second) 2394 inspect := podmanTest.InspectContainer(ctrName) 2395 Expect(inspect[0].State.Health).To(HaveField("Status", "starting")) 2396 2397 hc := podmanTest.Podman([]string{"healthcheck", "run", ctrName}) 2398 hc.WaitWithDefaultTimeout() 2399 Expect(hc).Should(ExitWithError(1, "")) 2400 2401 exec := podmanTest.Podman([]string{"exec", ctrName, "sh", "-c", "echo 'startup probe success' > /testfile"}) 2402 exec.WaitWithDefaultTimeout() 2403 Expect(exec).Should(ExitCleanly()) 2404 2405 hc = podmanTest.Podman([]string{"healthcheck", "run", ctrName}) 2406 hc.WaitWithDefaultTimeout() 2407 Expect(hc).Should(ExitCleanly()) 2408 2409 inspect = podmanTest.InspectContainer(ctrName) 2410 Expect(inspect[0].State.Health).To(HaveField("Status", define.HealthCheckHealthy)) 2411 }) 2412 2413 It("fail with nonexistent authfile", func() { 2414 err := generateKubeYaml("pod", getPod(), kubeYaml) 2415 Expect(err).ToNot(HaveOccurred()) 2416 2417 kube := podmanTest.Podman([]string{"kube", "play", "--authfile", "/tmp/nonexistent", kubeYaml}) 2418 kube.WaitWithDefaultTimeout() 2419 Expect(kube).To(ExitWithError(125, "credential file is not accessible: faccessat /tmp/nonexistent: no such file or directory")) 2420 }) 2421 2422 It("test correct command", func() { 2423 pod := getPod() 2424 err := generateKubeYaml("pod", pod, kubeYaml) 2425 Expect(err).ToNot(HaveOccurred()) 2426 2427 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2428 kube.WaitWithDefaultTimeout() 2429 Expect(kube).Should(ExitCleanly()) 2430 2431 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 2432 inspect.WaitWithDefaultTimeout() 2433 Expect(inspect).Should(ExitCleanly()) 2434 cmd := inspect.OutputToString() 2435 2436 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 2437 inspect.WaitWithDefaultTimeout() 2438 Expect(inspect).Should(ExitCleanly()) 2439 ep := inspect.OutputToString() 2440 2441 // Use the defined command to override the image's command 2442 Expect(ep).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 2443 Expect(cmd).To(ContainSubstring(strings.Join(defaultCtrArg, " "))) 2444 }) 2445 2446 // If you do not supply command or args for a Container, the defaults defined in the Docker image are used. 2447 It("test correct args and cmd when not specified", func() { 2448 pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil)))) 2449 err := generateKubeYaml("pod", pod, kubeYaml) 2450 Expect(err).ToNot(HaveOccurred()) 2451 2452 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2453 kube.WaitWithDefaultTimeout() 2454 Expect(kube).Should(ExitCleanly()) 2455 2456 // this image's ENTRYPOINT is `/entrypoint.sh` 2457 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 2458 inspect.WaitWithDefaultTimeout() 2459 Expect(inspect).Should(ExitCleanly()) 2460 Expect(inspect.OutputToString()).To(ContainSubstring(`/entrypoint.sh`)) 2461 2462 // and its COMMAND is `/etc/docker/registry/config.yml` 2463 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 2464 inspect.WaitWithDefaultTimeout() 2465 Expect(inspect).Should(ExitCleanly()) 2466 Expect(inspect.OutputToString()).To(ContainSubstring(`[/etc/docker/registry/config.yml]`)) 2467 }) 2468 2469 // If you supply a command but no args for a Container, only the supplied command is used. 2470 // The default EntryPoint and the default Cmd defined in the Docker image are ignored. 2471 It("test correct command with only set command in yaml file", func() { 2472 pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd([]string{"echo", "hello"}), withArg(nil)))) 2473 err := generateKubeYaml("pod", pod, kubeYaml) 2474 Expect(err).ToNot(HaveOccurred()) 2475 2476 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2477 kube.WaitWithDefaultTimeout() 2478 Expect(kube).Should(ExitCleanly()) 2479 2480 // Use the defined command to override the image's command, and don't set the args 2481 // so the full command in result should not contains the image's command 2482 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 2483 inspect.WaitWithDefaultTimeout() 2484 Expect(inspect).Should(ExitCleanly()) 2485 Expect(inspect.OutputToString()).To(ContainSubstring(`echo hello`)) 2486 2487 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 2488 inspect.WaitWithDefaultTimeout() 2489 Expect(inspect).Should(ExitCleanly()) 2490 // an empty command is reported as '[]' 2491 Expect(inspect.OutputToString()).To(ContainSubstring(`[]`)) 2492 }) 2493 2494 // If you have an init container in the pod yaml, podman should create and run the init container with kube play 2495 // With annotation set to always 2496 It("test with init containers and annotation set", func() { 2497 // With the init container type annotation set to always 2498 pod := getPod(withAnnotation("io.podman.annotations.init.container.type", "always"), withPodInitCtr(getCtr(withImage(CITEST_IMAGE), withCmd([]string{"printenv", "container"}), withInitCtr(), withName("init-test"))), withCtr(getCtr(withImage(CITEST_IMAGE), withCmd([]string{"top"})))) 2499 err := generateKubeYaml("pod", pod, kubeYaml) 2500 Expect(err).ToNot(HaveOccurred()) 2501 2502 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2503 kube.WaitWithDefaultTimeout() 2504 Expect(kube).Should(ExitCleanly()) 2505 2506 // Expect the number of containers created to be 3, one init, infra, and regular container 2507 numOfCtrs := podmanTest.NumberOfContainers() 2508 Expect(numOfCtrs).To(Equal(3)) 2509 2510 // Init container should have exited after running 2511 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-init-test"}) 2512 inspect.WaitWithDefaultTimeout() 2513 Expect(inspect).Should(ExitCleanly()) 2514 Expect(inspect.OutputToString()).To(ContainSubstring("exited")) 2515 2516 // Regular container should be in running state 2517 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 2518 inspect.WaitWithDefaultTimeout() 2519 Expect(inspect).Should(ExitCleanly()) 2520 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 2521 2522 // Init containers should not be restarted 2523 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.RestartPolicy.Name }}", "testPod-" + defaultCtrName}) 2524 inspect.WaitWithDefaultTimeout() 2525 Expect(inspect).Should(ExitCleanly()) 2526 Expect(inspect.OutputToString()).To(ContainSubstring(define.RestartPolicyNo)) 2527 2528 // Init containers need environment too! #18384 2529 logs := podmanTest.Podman([]string{"logs", "testPod-init-test"}) 2530 logs.WaitWithDefaultTimeout() 2531 Expect(logs).Should(ExitCleanly()) 2532 Expect(logs.OutputToString()).To(Equal("podman")) 2533 }) 2534 2535 // If you have an init container in the pod yaml, podman should create and run the init container with kube play 2536 // Using default init container type (once) 2537 It("test with init container type set to default value", func() { 2538 // Using the default init container type (once) 2539 pod := getPod(withPodInitCtr(getCtr(withImage(CITEST_IMAGE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("init-test"))), withCtr(getCtr(withImage(CITEST_IMAGE), withCmd([]string{"top"})))) 2540 err := generateKubeYaml("pod", pod, kubeYaml) 2541 Expect(err).ToNot(HaveOccurred()) 2542 2543 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2544 kube.WaitWithDefaultTimeout() 2545 Expect(kube).Should(ExitCleanly()) 2546 2547 // Expect the number of containers created to be 2, infra and regular container 2548 numOfCtrs := podmanTest.NumberOfContainers() 2549 Expect(numOfCtrs).To(Equal(2)) 2550 2551 // Regular container should be in running state 2552 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 2553 inspect.WaitWithDefaultTimeout() 2554 Expect(inspect).Should(ExitCleanly()) 2555 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 2556 }) 2557 2558 // If you supply only args for a Container, the default Entrypoint defined in the Docker image is run with the args that you supplied. 2559 It("test correct command with only set args in yaml file", func() { 2560 pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg([]string{"echo", "hello"})))) 2561 err := generateKubeYaml("pod", pod, kubeYaml) 2562 Expect(err).ToNot(HaveOccurred()) 2563 2564 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2565 kube.WaitWithDefaultTimeout() 2566 Expect(kube).Should(ExitCleanly()) 2567 2568 // this image's ENTRYPOINT is `/entrypoint.sh` 2569 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 2570 inspect.WaitWithDefaultTimeout() 2571 Expect(inspect).Should(ExitCleanly()) 2572 Expect(inspect.OutputToString()).To(ContainSubstring(`/entrypoint.sh`)) 2573 2574 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 2575 inspect.WaitWithDefaultTimeout() 2576 Expect(inspect).Should(ExitCleanly()) 2577 Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`)) 2578 }) 2579 2580 // If you supply a command and args, 2581 // the default Entrypoint and the default Cmd defined in the Docker image are ignored. 2582 // Your command is run with your args. 2583 It("test correct command with both set args and cmd in yaml file", func() { 2584 pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd([]string{"echo"}), withArg([]string{"hello"})))) 2585 err := generateKubeYaml("pod", pod, kubeYaml) 2586 Expect(err).ToNot(HaveOccurred()) 2587 2588 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2589 kube.WaitWithDefaultTimeout() 2590 Expect(kube).Should(ExitCleanly()) 2591 2592 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"}) 2593 inspect.WaitWithDefaultTimeout() 2594 Expect(inspect).Should(ExitCleanly()) 2595 Expect(inspect.OutputToString()).To(ContainSubstring(`echo`)) 2596 2597 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"}) 2598 inspect.WaitWithDefaultTimeout() 2599 Expect(inspect).Should(ExitCleanly()) 2600 Expect(inspect.OutputToString()).To(ContainSubstring(`[hello]`)) 2601 }) 2602 2603 It("test correct output", func() { 2604 p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"})))) 2605 2606 err := generateKubeYaml("pod", p, kubeYaml) 2607 Expect(err).ToNot(HaveOccurred()) 2608 2609 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2610 kube.WaitWithDefaultTimeout() 2611 Expect(kube).Should(ExitCleanly()) 2612 2613 wait := podmanTest.Podman([]string{"wait", getCtrNameInPod(p)}) 2614 wait.WaitWithDefaultTimeout() 2615 Expect(wait).Should(ExitCleanly()) 2616 2617 // Flake prevention: journalctl makes no timeliness guarantees. 2618 time.Sleep(1 * time.Second) 2619 logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(p)}) 2620 logs.WaitWithDefaultTimeout() 2621 Expect(logs).Should(ExitCleanly()) 2622 Expect(logs.OutputToString()).To(ContainSubstring("hello world")) 2623 }) 2624 2625 It("podman pod logs test", func() { 2626 SkipIfRemote("podman-remote pod logs -c is mandatory for remote machine") 2627 p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"})))) 2628 2629 err := generateKubeYaml("pod", p, kubeYaml) 2630 Expect(err).ToNot(HaveOccurred()) 2631 2632 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2633 kube.WaitWithDefaultTimeout() 2634 Expect(kube).Should(ExitCleanly()) 2635 2636 wait := podmanTest.Podman([]string{"wait", getCtrNameInPod(p)}) 2637 wait.WaitWithDefaultTimeout() 2638 Expect(wait).Should(ExitCleanly()) 2639 2640 logs := podmanTest.Podman([]string{"pod", "logs", p.Name}) 2641 logs.WaitWithDefaultTimeout() 2642 Expect(logs).Should(ExitCleanly()) 2643 Expect(logs.OutputToString()).To(ContainSubstring("hello world")) 2644 }) 2645 2646 It("podman-remote pod logs test", func() { 2647 // -c or --container is required in podman-remote due to api limitation. 2648 p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"})))) 2649 2650 err := generateKubeYaml("pod", p, kubeYaml) 2651 Expect(err).ToNot(HaveOccurred()) 2652 2653 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2654 kube.WaitWithDefaultTimeout() 2655 Expect(kube).Should(ExitCleanly()) 2656 2657 wait := podmanTest.Podman([]string{"wait", getCtrNameInPod(p)}) 2658 wait.WaitWithDefaultTimeout() 2659 Expect(wait).Should(ExitCleanly()) 2660 2661 logs := podmanTest.Podman([]string{"pod", "logs", "-c", getCtrNameInPod(p), p.Name}) 2662 logs.WaitWithDefaultTimeout() 2663 Expect(logs).Should(ExitCleanly()) 2664 Expect(logs.OutputToString()).To(ContainSubstring("hello world")) 2665 }) 2666 2667 It("test restartPolicy", func() { 2668 // podName, set, expect 2669 testSli := [][]string{ 2670 {"testPod1", "", "always"}, // Default equal to always 2671 {"testPod2", "Always", "always"}, 2672 {"testPod3", "OnFailure", "on-failure"}, 2673 {"testPod4", "Never", "no"}, 2674 } 2675 for _, v := range testSli { 2676 pod := getPod(withPodName(v[0]), withRestartPolicy(v[1])) 2677 err := generateKubeYaml("pod", pod, kubeYaml) 2678 Expect(err).ToNot(HaveOccurred()) 2679 2680 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2681 kube.WaitWithDefaultTimeout() 2682 Expect(kube).Should(ExitCleanly()) 2683 2684 inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{.RestartPolicy}}"}) 2685 inspect.WaitWithDefaultTimeout() 2686 Expect(inspect).Should(ExitCleanly()) 2687 Expect(inspect.OutputToString()).To(Equal(v[2])) 2688 } 2689 }) 2690 2691 It("test env value from configmap", func() { 2692 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 2693 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 2694 err := generateKubeYaml("configmap", cm, cmYamlPathname) 2695 Expect(err).ToNot(HaveOccurred()) 2696 2697 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 2698 err = generateKubeYaml("pod", pod, kubeYaml) 2699 Expect(err).ToNot(HaveOccurred()) 2700 2701 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", cmYamlPathname}) 2702 kube.WaitWithDefaultTimeout() 2703 Expect(kube).Should(ExitCleanly()) 2704 2705 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 2706 inspect.WaitWithDefaultTimeout() 2707 Expect(inspect).Should(ExitCleanly()) 2708 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 2709 }) 2710 2711 It("test env value from configmap and --replace should reuse the configmap volume", func() { 2712 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 2713 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 2714 err := generateKubeYaml("configmap", cm, cmYamlPathname) 2715 Expect(err).ToNot(HaveOccurred()) 2716 2717 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 2718 err = generateKubeYaml("pod", pod, kubeYaml) 2719 Expect(err).ToNot(HaveOccurred()) 2720 2721 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", cmYamlPathname}) 2722 kube.WaitWithDefaultTimeout() 2723 Expect(kube).Should(ExitCleanly()) 2724 2725 // create pod again with --replace 2726 kube = podmanTest.Podman([]string{"kube", "play", "--replace", kubeYaml, "--configmap", cmYamlPathname}) 2727 kube.WaitWithDefaultTimeout() 2728 Expect(kube).Should(ExitCleanly()) 2729 2730 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 2731 inspect.WaitWithDefaultTimeout() 2732 Expect(inspect).Should(ExitCleanly()) 2733 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 2734 }) 2735 2736 It("test required env value from configmap with missing key", func() { 2737 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 2738 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 2739 err := generateKubeYaml("configmap", cm, cmYamlPathname) 2740 Expect(err).ToNot(HaveOccurred()) 2741 2742 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", false)))) 2743 err = generateKubeYaml("pod", pod, kubeYaml) 2744 Expect(err).ToNot(HaveOccurred()) 2745 2746 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", cmYamlPathname}) 2747 kube.WaitWithDefaultTimeout() 2748 Expect(kube).To(ExitWithError(125, "cannot set env FOO: key MISSING_KEY not found in configmap foo")) 2749 }) 2750 2751 It("test required env value from missing configmap", func() { 2752 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "missing_cm", "FOO", false)))) 2753 err = generateKubeYaml("pod", pod, kubeYaml) 2754 Expect(err).ToNot(HaveOccurred()) 2755 2756 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2757 kube.WaitWithDefaultTimeout() 2758 Expect(kube).To(ExitWithError(125, "cannot set env FOO: configmap missing_cm not found")) 2759 }) 2760 2761 It("test optional env value from configmap with missing key", func() { 2762 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 2763 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 2764 err := generateKubeYaml("configmap", cm, cmYamlPathname) 2765 Expect(err).ToNot(HaveOccurred()) 2766 2767 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", true)))) 2768 err = generateKubeYaml("pod", pod, kubeYaml) 2769 Expect(err).ToNot(HaveOccurred()) 2770 2771 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", cmYamlPathname}) 2772 kube.WaitWithDefaultTimeout() 2773 Expect(kube).Should(ExitCleanly()) 2774 2775 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 2776 inspect.WaitWithDefaultTimeout() 2777 Expect(inspect).Should(ExitCleanly()) 2778 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 2779 }) 2780 2781 It("test optional env value from missing configmap", func() { 2782 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "missing_cm", "FOO", true)))) 2783 err = generateKubeYaml("pod", pod, kubeYaml) 2784 Expect(err).ToNot(HaveOccurred()) 2785 2786 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2787 kube.WaitWithDefaultTimeout() 2788 Expect(kube).Should(ExitCleanly()) 2789 2790 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 2791 inspect.WaitWithDefaultTimeout() 2792 Expect(inspect).Should(ExitCleanly()) 2793 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 2794 }) 2795 2796 It("test get all key-value pairs from configmap as envs", func() { 2797 cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 2798 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2")) 2799 err := generateKubeYaml("configmap", cm, cmYamlPathname) 2800 Expect(err).ToNot(HaveOccurred()) 2801 2802 pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap", false)))) 2803 err = generateKubeYaml("pod", pod, kubeYaml) 2804 Expect(err).ToNot(HaveOccurred()) 2805 2806 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", cmYamlPathname}) 2807 kube.WaitWithDefaultTimeout() 2808 Expect(kube).Should(ExitCleanly()) 2809 2810 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 2811 inspect.WaitWithDefaultTimeout() 2812 Expect(inspect).Should(ExitCleanly()) 2813 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`)) 2814 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`)) 2815 }) 2816 2817 It("test get all key-value pairs from required configmap as envs", func() { 2818 pod := getPod(withCtr(getCtr(withEnvFrom("missing_cm", "configmap", false)))) 2819 err = generateKubeYaml("pod", pod, kubeYaml) 2820 Expect(err).ToNot(HaveOccurred()) 2821 2822 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2823 kube.WaitWithDefaultTimeout() 2824 Expect(kube).To(ExitWithError(125, "configmap missing_cm not found")) 2825 }) 2826 2827 It("test get all key-value pairs from optional configmap as envs", func() { 2828 pod := getPod(withCtr(getCtr(withEnvFrom("missing_cm", "configmap", true)))) 2829 err = generateKubeYaml("pod", pod, kubeYaml) 2830 Expect(err).ToNot(HaveOccurred()) 2831 2832 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2833 kube.WaitWithDefaultTimeout() 2834 Expect(kube).Should(ExitCleanly()) 2835 }) 2836 2837 It("test env value from secret", func() { 2838 createSecret(podmanTest, "foo", defaultSecret) 2839 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "FOO", false)))) 2840 err = generateKubeYaml("pod", pod, kubeYaml) 2841 Expect(err).ToNot(HaveOccurred()) 2842 2843 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2844 kube.WaitWithDefaultTimeout() 2845 Expect(kube).Should(ExitCleanly()) 2846 2847 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 2848 inspect.WaitWithDefaultTimeout() 2849 Expect(inspect).Should(ExitCleanly()) 2850 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 2851 }) 2852 2853 It("test required env value from missing secret", func() { 2854 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "FOO", false)))) 2855 err = generateKubeYaml("pod", pod, kubeYaml) 2856 Expect(err).ToNot(HaveOccurred()) 2857 2858 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2859 kube.WaitWithDefaultTimeout() 2860 Expect(kube).To(ExitWithError(125, `cannot set env FOO: no secret with name or id "foo": no such secret`)) 2861 }) 2862 2863 It("test required env value from secret with missing key", func() { 2864 createSecret(podmanTest, "foo", defaultSecret) 2865 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "MISSING", false)))) 2866 err = generateKubeYaml("pod", pod, kubeYaml) 2867 Expect(err).ToNot(HaveOccurred()) 2868 2869 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2870 kube.WaitWithDefaultTimeout() 2871 Expect(kube).To(ExitWithError(125, "cannot set env FOO: secret foo has not MISSING key")) 2872 }) 2873 2874 It("test optional env value from missing secret", func() { 2875 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "FOO", true)))) 2876 err = generateKubeYaml("pod", pod, kubeYaml) 2877 Expect(err).ToNot(HaveOccurred()) 2878 2879 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2880 kube.WaitWithDefaultTimeout() 2881 Expect(kube).Should(ExitCleanly()) 2882 2883 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 2884 inspect.WaitWithDefaultTimeout() 2885 Expect(inspect).Should(ExitCleanly()) 2886 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 2887 }) 2888 2889 It("test optional env value from secret with missing key", func() { 2890 createSecret(podmanTest, "foo", defaultSecret) 2891 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "secret", "foo", "MISSING", true)))) 2892 err = generateKubeYaml("pod", pod, kubeYaml) 2893 Expect(err).ToNot(HaveOccurred()) 2894 2895 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2896 kube.WaitWithDefaultTimeout() 2897 Expect(kube).Should(ExitCleanly()) 2898 2899 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 2900 inspect.WaitWithDefaultTimeout() 2901 Expect(inspect).Should(ExitCleanly()) 2902 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 2903 }) 2904 2905 It("test get all key-value pairs from secret as envs", func() { 2906 createSecret(podmanTest, "foo", defaultSecret) 2907 pod := getPod(withCtr(getCtr(withEnvFrom("foo", "secret", false)))) 2908 err = generateKubeYaml("pod", pod, kubeYaml) 2909 Expect(err).ToNot(HaveOccurred()) 2910 2911 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2912 kube.WaitWithDefaultTimeout() 2913 Expect(kube).Should(ExitCleanly()) 2914 2915 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 2916 inspect.WaitWithDefaultTimeout() 2917 Expect(inspect).Should(ExitCleanly()) 2918 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 2919 Expect(inspect.OutputToString()).To(ContainSubstring(`BAR=bar`)) 2920 }) 2921 2922 It("test get all key-value pairs from required secret as envs", func() { 2923 pod := getPod(withCtr(getCtr(withEnvFrom("missing_secret", "secret", false)))) 2924 err = generateKubeYaml("pod", pod, kubeYaml) 2925 Expect(err).ToNot(HaveOccurred()) 2926 2927 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2928 kube.WaitWithDefaultTimeout() 2929 Expect(kube).To(ExitWithError(125, `no secret with name or id "missing_secret": no such secret`)) 2930 }) 2931 2932 It("test get all key-value pairs from optional secret as envs", func() { 2933 pod := getPod(withCtr(getCtr(withEnvFrom("missing_secret", "secret", true)))) 2934 err = generateKubeYaml("pod", pod, kubeYaml) 2935 Expect(err).ToNot(HaveOccurred()) 2936 2937 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2938 kube.WaitWithDefaultTimeout() 2939 Expect(kube).Should(ExitCleanly()) 2940 }) 2941 2942 It("test duplicate container name", func() { 2943 p := getPod(withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "hello"}))), withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "world"})))) 2944 2945 err := generateKubeYaml("pod", p, kubeYaml) 2946 Expect(err).ToNot(HaveOccurred()) 2947 2948 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2949 kube.WaitWithDefaultTimeout() 2950 Expect(kube).To(ExitWithError(125, `the pod "testPod" is invalid; duplicate container name "testctr" detected`)) 2951 2952 p = getPod(withPodInitCtr(getCtr(withImage(CITEST_IMAGE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("initctr"))), withCtr(getCtr(withImage(CITEST_IMAGE), withName("initctr"), withCmd([]string{"top"})))) 2953 2954 err = generateKubeYaml("pod", p, kubeYaml) 2955 Expect(err).ToNot(HaveOccurred()) 2956 2957 kube = podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2958 kube.WaitWithDefaultTimeout() 2959 Expect(kube).To(ExitWithError(125, `adding pod to state: name "testPod" is in use: pod already exists`)) 2960 }) 2961 2962 It("test hostname", func() { 2963 pod := getPod() 2964 err := generateKubeYaml("pod", pod, kubeYaml) 2965 Expect(err).ToNot(HaveOccurred()) 2966 2967 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2968 kube.WaitWithDefaultTimeout() 2969 Expect(kube).Should(ExitCleanly()) 2970 2971 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"}) 2972 inspect.WaitWithDefaultTimeout() 2973 Expect(inspect).Should(ExitCleanly()) 2974 Expect(inspect.OutputToString()).To(Equal(defaultPodName)) 2975 }) 2976 2977 It("test with customized hostname", func() { 2978 hostname := "myhostname" 2979 pod := getPod(withHostname(hostname)) 2980 err := generateKubeYaml("pod", getPod(withHostname(hostname)), kubeYaml) 2981 Expect(err).ToNot(HaveOccurred()) 2982 2983 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 2984 kube.WaitWithDefaultTimeout() 2985 Expect(kube).Should(ExitCleanly()) 2986 2987 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"}) 2988 inspect.WaitWithDefaultTimeout() 2989 Expect(inspect).Should(ExitCleanly()) 2990 Expect(inspect.OutputToString()).To(Equal(hostname)) 2991 2992 hostnameInCtr := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "hostname"}) 2993 hostnameInCtr.WaitWithDefaultTimeout() 2994 Expect(hostnameInCtr).Should(ExitCleanly()) 2995 Expect(hostnameInCtr.OutputToString()).To(Equal(hostname)) 2996 }) 2997 2998 It("test HostAliases", func() { 2999 pod := getPod(withHostAliases("192.168.1.2", []string{ 3000 "test1.podman.io", 3001 "test2.podman.io", 3002 }), 3003 withHostAliases("192.168.1.3", []string{ 3004 "test3.podman.io", 3005 "test4.podman.io", 3006 }), 3007 ) 3008 err := generateKubeYaml("pod", pod, kubeYaml) 3009 Expect(err).ToNot(HaveOccurred()) 3010 3011 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3012 kube.WaitWithDefaultTimeout() 3013 Expect(kube).Should(ExitCleanly()) 3014 3015 inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.HostAdd}}"}) 3016 inspect.WaitWithDefaultTimeout() 3017 Expect(inspect).Should(ExitCleanly()) 3018 Expect(inspect.OutputToString()). 3019 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]")) 3020 }) 3021 3022 It("cap add", func() { 3023 capAdd := "CAP_SYS_ADMIN" 3024 ctr := getCtr(withCapAdd([]string{capAdd}), withCmd([]string{"cat", "/proc/self/status"}), withArg(nil)) 3025 3026 pod := getPod(withCtr(ctr)) 3027 err := generateKubeYaml("pod", pod, kubeYaml) 3028 Expect(err).ToNot(HaveOccurred()) 3029 3030 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3031 kube.WaitWithDefaultTimeout() 3032 Expect(kube).Should(ExitCleanly()) 3033 3034 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 3035 inspect.WaitWithDefaultTimeout() 3036 Expect(inspect).Should(ExitCleanly()) 3037 Expect(inspect.OutputToString()).To(ContainSubstring(capAdd)) 3038 }) 3039 3040 It("cap drop", func() { 3041 capDrop := "CAP_CHOWN" 3042 ctr := getCtr(withCapDrop([]string{capDrop})) 3043 3044 pod := getPod(withCtr(ctr)) 3045 err := generateKubeYaml("pod", pod, kubeYaml) 3046 Expect(err).ToNot(HaveOccurred()) 3047 3048 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3049 kube.WaitWithDefaultTimeout() 3050 Expect(kube).Should(ExitCleanly()) 3051 3052 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 3053 inspect.WaitWithDefaultTimeout() 3054 Expect(inspect).Should(ExitCleanly()) 3055 Expect(inspect.OutputToString()).To(ContainSubstring(capDrop)) 3056 }) 3057 3058 It("no security context", func() { 3059 // expect kube play to not fail if no security context is specified 3060 pod := getPod(withCtr(getCtr(withSecurityContext(false)))) 3061 err := generateKubeYaml("pod", pod, kubeYaml) 3062 Expect(err).ToNot(HaveOccurred()) 3063 3064 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3065 kube.WaitWithDefaultTimeout() 3066 Expect(kube).Should(ExitCleanly()) 3067 3068 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 3069 inspect.WaitWithDefaultTimeout() 3070 Expect(inspect).Should(ExitCleanly()) 3071 }) 3072 3073 It("seccomp container level", func() { 3074 SkipIfRemote("podman-remote does not support --seccomp-profile-root flag") 3075 // expect kube play is expected to set a seccomp label if it's applied as an annotation 3076 jsonFile, err := podmanTest.CreateSeccompJSON(seccompLinkEPERM) 3077 if err != nil { 3078 GinkgoWriter.Println(err) 3079 Skip("Failed to prepare seccomp.json for test.") 3080 } 3081 3082 ctrAnnotation := "container.seccomp.security.alpha.kubernetes.io/" + defaultCtrName 3083 ctr := getCtr(withCmd([]string{"ln"}), withArg([]string{"/etc/motd", "/noneShallPass"})) 3084 3085 pod := getPod(withCtr(ctr), withAnnotation(ctrAnnotation, "localhost/"+filepath.Base(jsonFile))) 3086 err = generateKubeYaml("pod", pod, kubeYaml) 3087 Expect(err).ToNot(HaveOccurred()) 3088 3089 // CreateSeccompJSON will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell kube play where to look 3090 kube := podmanTest.Podman([]string{"kube", "play", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml}) 3091 kube.WaitWithDefaultTimeout() 3092 Expect(kube).Should(ExitCleanly()) 3093 3094 ctrName := getCtrNameInPod(pod) 3095 wait := podmanTest.Podman([]string{"wait", ctrName}) 3096 wait.WaitWithDefaultTimeout() 3097 Expect(wait).Should(Exit(0), "podman wait %s", ctrName) 3098 3099 logs := podmanTest.Podman([]string{"logs", ctrName}) 3100 logs.WaitWithDefaultTimeout() 3101 Expect(logs).Should(Exit(0), "podman logs %s", ctrName) 3102 Expect(logs.ErrorToString()).To(ContainSubstring("ln: /noneShallPass: Operation not permitted")) 3103 }) 3104 3105 It("seccomp pod level", func() { 3106 SkipIfRemote("podman-remote does not support --seccomp-profile-root flag") 3107 // expect kube play is expected to set a seccomp label if it's applied as an annotation 3108 jsonFile, err := podmanTest.CreateSeccompJSON(seccompLinkEPERM) 3109 if err != nil { 3110 GinkgoWriter.Println(err) 3111 Skip("Failed to prepare seccomp.json for test.") 3112 } 3113 defer os.Remove(jsonFile) 3114 3115 ctr := getCtr(withCmd([]string{"ln"}), withArg([]string{"/etc/motd", "/noPodsShallPass"})) 3116 3117 pod := getPod(withCtr(ctr), withAnnotation("seccomp.security.alpha.kubernetes.io/pod", "localhost/"+filepath.Base(jsonFile))) 3118 err = generateKubeYaml("pod", pod, kubeYaml) 3119 Expect(err).ToNot(HaveOccurred()) 3120 3121 // CreateSeccompJSON will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell kube play where to look 3122 kube := podmanTest.Podman([]string{"kube", "play", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml}) 3123 kube.WaitWithDefaultTimeout() 3124 Expect(kube).Should(ExitCleanly()) 3125 3126 podName := getCtrNameInPod(pod) 3127 wait := podmanTest.Podman([]string{"wait", podName}) 3128 wait.WaitWithDefaultTimeout() 3129 Expect(wait).Should(ExitCleanly()) 3130 3131 logs := podmanTest.Podman([]string{"logs", podName}) 3132 logs.WaitWithDefaultTimeout() 3133 Expect(logs).Should(Exit(0)) 3134 Expect(logs.ErrorToString()).To(ContainSubstring("ln: /noPodsShallPass: Operation not permitted")) 3135 }) 3136 3137 It("with pull policy of never should be 125", func() { 3138 ctr := getCtr(withPullPolicy("never"), withImage(BB_GLIBC)) 3139 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 3140 Expect(err).ToNot(HaveOccurred()) 3141 3142 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3143 kube.WaitWithDefaultTimeout() 3144 Expect(kube).Should(ExitWithError(125, BB_GLIBC+": image not known")) 3145 }) 3146 3147 It("with pull policy of missing", func() { 3148 ctr := getCtr(withPullPolicy("Missing"), withImage(CITEST_IMAGE)) 3149 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 3150 Expect(err).ToNot(HaveOccurred()) 3151 3152 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3153 kube.WaitWithDefaultTimeout() 3154 Expect(kube).Should(ExitCleanly()) 3155 }) 3156 3157 It("with pull always", func() { 3158 oldBB := "quay.io/libpod/busybox:1.30.1" 3159 pull := podmanTest.Podman([]string{"pull", oldBB}) 3160 pull.WaitWithDefaultTimeout() 3161 3162 tag := podmanTest.Podman([]string{"tag", oldBB, BB}) 3163 tag.WaitWithDefaultTimeout() 3164 Expect(tag).Should(ExitCleanly()) 3165 3166 rmi := podmanTest.Podman([]string{"rmi", oldBB}) 3167 rmi.WaitWithDefaultTimeout() 3168 Expect(rmi).Should(ExitCleanly()) 3169 3170 inspect := podmanTest.Podman([]string{"inspect", BB}) 3171 inspect.WaitWithDefaultTimeout() 3172 oldBBinspect := inspect.InspectImageJSON() 3173 3174 ctr := getCtr(withPullPolicy("always"), withImage(BB)) 3175 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 3176 Expect(err).ToNot(HaveOccurred()) 3177 3178 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3179 kube.WaitWithDefaultTimeout() 3180 // Cannot ExitCleanly() because pull output goes to stderr 3181 Expect(kube).Should(Exit(0)) 3182 3183 inspect = podmanTest.Podman([]string{"inspect", BB}) 3184 inspect.WaitWithDefaultTimeout() 3185 newBBinspect := inspect.InspectImageJSON() 3186 Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest))) 3187 }) 3188 3189 It("with latest image should always pull", func() { 3190 oldBB := "quay.io/libpod/busybox:1.30.1" 3191 pull := podmanTest.Podman([]string{"pull", oldBB}) 3192 pull.WaitWithDefaultTimeout() 3193 Expect(pull).Should(Exit(0)) 3194 3195 tag := podmanTest.Podman([]string{"tag", oldBB, BB}) 3196 tag.WaitWithDefaultTimeout() 3197 Expect(tag).Should(ExitCleanly()) 3198 3199 rmi := podmanTest.Podman([]string{"rmi", oldBB}) 3200 rmi.WaitWithDefaultTimeout() 3201 Expect(rmi).Should(ExitCleanly()) 3202 3203 inspect := podmanTest.Podman([]string{"inspect", BB}) 3204 inspect.WaitWithDefaultTimeout() 3205 oldBBinspect := inspect.InspectImageJSON() 3206 3207 ctr := getCtr(withImage(BB), withPullPolicy("")) 3208 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 3209 Expect(err).ToNot(HaveOccurred()) 3210 3211 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3212 kube.WaitWithDefaultTimeout() 3213 // Cannot ExitCleanly() because pull output goes to stderr 3214 Expect(kube).Should(Exit(0)) 3215 3216 inspect = podmanTest.Podman([]string{"inspect", BB}) 3217 inspect.WaitWithDefaultTimeout() 3218 newBBinspect := inspect.InspectImageJSON() 3219 Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest))) 3220 }) 3221 3222 It("with no tag and no pull policy should always pull", func() { 3223 oldBB := "quay.io/libpod/busybox:1.30.1" 3224 pull := podmanTest.Podman([]string{"pull", oldBB}) 3225 pull.WaitWithDefaultTimeout() 3226 Expect(pull).Should(Exit(0)) 3227 3228 tag := podmanTest.Podman([]string{"tag", oldBB, BB}) 3229 tag.WaitWithDefaultTimeout() 3230 Expect(tag).Should(ExitCleanly()) 3231 3232 rmi := podmanTest.Podman([]string{"rmi", oldBB}) 3233 rmi.WaitWithDefaultTimeout() 3234 Expect(rmi).Should(ExitCleanly()) 3235 3236 inspect := podmanTest.Podman([]string{"inspect", BB}) 3237 inspect.WaitWithDefaultTimeout() 3238 Expect(inspect).Should(ExitCleanly()) 3239 oldBBinspect := inspect.InspectImageJSON() 3240 3241 noTagBB := "quay.io/libpod/busybox" 3242 ctr := getCtr(withImage(noTagBB), withPullPolicy("")) 3243 err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml) 3244 Expect(err).ToNot(HaveOccurred()) 3245 3246 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3247 kube.WaitWithDefaultTimeout() 3248 Expect(kube).Should(Exit(0)) 3249 if IsRemote() { 3250 Expect(kube.ErrorToString()).To(BeEmpty()) 3251 } else { 3252 Expect(kube.ErrorToString()).To(ContainSubstring("Copying blob ")) 3253 } 3254 3255 inspect = podmanTest.Podman([]string{"inspect", noTagBB}) 3256 inspect.WaitWithDefaultTimeout() 3257 Expect(inspect).Should(ExitCleanly()) 3258 newBBinspect := inspect.InspectImageJSON() 3259 Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest))) 3260 }) 3261 3262 It("with image data", func() { 3263 testyaml := ` 3264 apiVersion: v1 3265 kind: Pod 3266 metadata: 3267 name: demo_pod 3268 spec: 3269 containers: 3270 - image: demo 3271 name: demo_kube 3272 ` 3273 pull := podmanTest.Podman([]string{"create", "--workdir", "/etc", "--name", "newBB", "--label", "key1=value1", CITEST_IMAGE}) 3274 3275 pull.WaitWithDefaultTimeout() 3276 Expect(pull).Should(ExitCleanly()) 3277 3278 c := podmanTest.Podman([]string{"commit", "-q", "-c", "STOPSIGNAL=51", "newBB", "demo"}) 3279 c.WaitWithDefaultTimeout() 3280 Expect(c).Should(ExitCleanly()) 3281 3282 conffile := filepath.Join(podmanTest.TempDir, "kube.yaml") 3283 3284 err := os.WriteFile(conffile, []byte(testyaml), 0755) 3285 Expect(err).ToNot(HaveOccurred()) 3286 3287 kube := podmanTest.Podman([]string{"kube", "play", conffile}) 3288 kube.WaitWithDefaultTimeout() 3289 Expect(kube).Should(ExitCleanly()) 3290 3291 inspect := podmanTest.Podman([]string{"inspect", "demo_pod-demo_kube"}) 3292 inspect.WaitWithDefaultTimeout() 3293 Expect(inspect).Should(ExitCleanly()) 3294 3295 ctr := inspect.InspectContainerToJSON() 3296 Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc")) 3297 Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1"))) 3298 Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1"))) 3299 Expect(ctr[0].Config).To(HaveField("StopSignal", "SIGRTMAX-13")) 3300 }) 3301 3302 It("daemonset sanity", func() { 3303 daemonset := getDaemonSet() 3304 err := generateKubeYaml("daemonset", daemonset, kubeYaml) 3305 Expect(err).ToNot(HaveOccurred()) 3306 3307 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3308 kube.WaitWithDefaultTimeout() 3309 Expect(kube).Should(ExitCleanly()) 3310 3311 podName := getPodNameInDaemonSet(daemonset) 3312 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podName), "--format", "'{{ .Config.Entrypoint }}'"}) 3313 inspect.WaitWithDefaultTimeout() 3314 Expect(inspect).Should(ExitCleanly()) 3315 // yaml's command should override the image's Entrypoint 3316 Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 3317 }) 3318 3319 // Deployment related tests 3320 It("deployment 1 replica test correct command", func() { 3321 deployment := getDeployment() 3322 err := generateKubeYaml("deployment", deployment, kubeYaml) 3323 Expect(err).ToNot(HaveOccurred()) 3324 3325 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3326 kube.WaitWithDefaultTimeout() 3327 Expect(kube).Should(ExitCleanly()) 3328 3329 podName := getPodNameInDeployment(deployment) 3330 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podName), "--format", "'{{ .Config.Entrypoint }}'"}) 3331 inspect.WaitWithDefaultTimeout() 3332 Expect(inspect).Should(ExitCleanly()) 3333 // yaml's command should override the image's Entrypoint 3334 Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 3335 }) 3336 3337 It("deployment more than 1 replica test correct command", func() { 3338 var numReplicas int32 = 5 3339 deployment := getDeployment(withReplicas(numReplicas)) 3340 err := generateKubeYaml("deployment", deployment, kubeYaml) 3341 Expect(err).ToNot(HaveOccurred()) 3342 3343 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3344 kube.WaitWithDefaultTimeout() 3345 Expect(kube).Should(Exit(0)) 3346 if IsRemote() { 3347 Expect(kube.ErrorToString()).To(BeEmpty()) 3348 } else { 3349 Expect(kube.ErrorToString()).To(ContainSubstring("Limiting replica count to 1, more than one replica is not supported by Podman")) 3350 } 3351 3352 podName := getPodNameInDeployment(deployment) 3353 3354 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podName), "--format", "'{{ .Config.Entrypoint }}'"}) 3355 inspect.WaitWithDefaultTimeout() 3356 Expect(inspect).Should(ExitCleanly()) 3357 Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " "))) 3358 3359 }) 3360 3361 It("--ip and --mac-address", func() { 3362 var i, numReplicas int32 3363 numReplicas = 3 3364 deployment := getDeployment(withReplicas(numReplicas)) 3365 err := generateKubeYaml("deployment", deployment, kubeYaml) 3366 Expect(err).ToNot(HaveOccurred()) 3367 3368 net := "playkube" + stringid.GenerateRandomID() 3369 session := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.31.0/24", net}) 3370 session.WaitWithDefaultTimeout() 3371 defer podmanTest.removeNetwork(net) 3372 Expect(session).Should(ExitCleanly()) 3373 3374 ips := []string{"10.25.31.5", "10.25.31.10", "10.25.31.15"} 3375 playArgs := []string{"kube", "play", "--network", net} 3376 for _, ip := range ips { 3377 playArgs = append(playArgs, "--ip", ip) 3378 } 3379 macs := []string{"e8:d8:82:c9:80:40", "e8:d8:82:c9:80:50", "e8:d8:82:c9:80:60"} 3380 for _, mac := range macs { 3381 playArgs = append(playArgs, "--mac-address", mac) 3382 } 3383 3384 kube := podmanTest.Podman(append(playArgs, kubeYaml)) 3385 kube.WaitWithDefaultTimeout() 3386 Expect(kube).Should(Exit(0)) 3387 if IsRemote() { 3388 Expect(kube.ErrorToString()).To(BeEmpty()) 3389 } else { 3390 Expect(kube.ErrorToString()).To(ContainSubstring("Limiting replica count to 1, more than one replica is not supported by Podman")) 3391 } 3392 3393 podName := getPodNameInDeployment(deployment) 3394 3395 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podName), "--format", "{{ .NetworkSettings.Networks." + net + ".IPAddress }}"}) 3396 inspect.WaitWithDefaultTimeout() 3397 Expect(inspect).Should(ExitCleanly()) 3398 Expect(inspect.OutputToString()).To(Equal(ips[i])) 3399 3400 inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podName), "--format", "{{ .NetworkSettings.Networks." + net + ".MacAddress }}"}) 3401 inspect.WaitWithDefaultTimeout() 3402 Expect(inspect).Should(ExitCleanly()) 3403 Expect(inspect.OutputToString()).To(Equal(macs[i])) 3404 3405 }) 3406 3407 It("with multiple networks", func() { 3408 ctr := getCtr(withImage(CITEST_IMAGE)) 3409 pod := getPod(withCtr(ctr)) 3410 err := generateKubeYaml("pod", pod, kubeYaml) 3411 Expect(err).ToNot(HaveOccurred()) 3412 3413 net1 := "net1" + stringid.GenerateRandomID() 3414 net2 := "net2" + stringid.GenerateRandomID() 3415 3416 net := podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.11.0/24", net1}) 3417 net.WaitWithDefaultTimeout() 3418 defer podmanTest.removeNetwork(net1) 3419 Expect(net).Should(ExitCleanly()) 3420 3421 net = podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.12.0/24", net2}) 3422 net.WaitWithDefaultTimeout() 3423 defer podmanTest.removeNetwork(net2) 3424 Expect(net).Should(ExitCleanly()) 3425 3426 ip1 := "10.0.11.5" 3427 ip2 := "10.0.12.10" 3428 3429 kube := podmanTest.Podman([]string{"kube", "play", "--network", net1 + ":ip=" + ip1, "--network", net2 + ":ip=" + ip2, kubeYaml}) 3430 kube.WaitWithDefaultTimeout() 3431 Expect(kube).Should(ExitCleanly()) 3432 3433 inspect := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "ip", "addr"}) 3434 inspect.WaitWithDefaultTimeout() 3435 Expect(inspect).Should(ExitCleanly()) 3436 Expect(inspect.OutputToString()).To(ContainSubstring(ip1)) 3437 Expect(inspect.OutputToString()).To(ContainSubstring(ip2)) 3438 Expect(inspect.OutputToString()).To(ContainSubstring("eth0")) 3439 Expect(inspect.OutputToString()).To(ContainSubstring("eth1")) 3440 }) 3441 3442 It("test with network portbindings", func() { 3443 ip := "127.0.0.100" 3444 port := "8087" 3445 ctr := getCtr(withHostIP(ip, port), withImage(CITEST_IMAGE)) 3446 3447 pod := getPod(withCtr(ctr)) 3448 err := generateKubeYaml("pod", pod, kubeYaml) 3449 Expect(err).ToNot(HaveOccurred()) 3450 3451 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3452 kube.WaitWithDefaultTimeout() 3453 Expect(kube).Should(ExitCleanly()) 3454 3455 inspect := podmanTest.Podman([]string{"port", getCtrNameInPod(pod)}) 3456 inspect.WaitWithDefaultTimeout() 3457 Expect(inspect).Should(ExitCleanly()) 3458 Expect(inspect.OutputToString()).To(Equal("8087/tcp -> 127.0.0.100:8087")) 3459 }) 3460 3461 It("test with nonexistent empty HostPath type volume", func() { 3462 hostPathLocation := filepath.Join(tempdir, "file") 3463 3464 pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation))) 3465 err := generateKubeYaml("pod", pod, kubeYaml) 3466 Expect(err).ToNot(HaveOccurred()) 3467 3468 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3469 kube.WaitWithDefaultTimeout() 3470 Expect(kube).To(ExitWithError(125, fmt.Sprintf(`failed to create volume "testVol": in parsing HostPath in YAML: faccessat %s: no such file or directory`, hostPathLocation))) 3471 Expect(kube.ErrorToString()).To(ContainSubstring(defaultVolName)) 3472 }) 3473 3474 It("test with empty HostPath type volume", func() { 3475 hostPathLocation := filepath.Join(tempdir, "file") 3476 f, err := os.Create(hostPathLocation) 3477 Expect(err).ToNot(HaveOccurred()) 3478 f.Close() 3479 3480 pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation))) 3481 err = generateKubeYaml("pod", pod, kubeYaml) 3482 Expect(err).ToNot(HaveOccurred()) 3483 3484 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3485 kube.WaitWithDefaultTimeout() 3486 Expect(kube).Should(ExitCleanly()) 3487 }) 3488 3489 It("test with nonexistent File HostPath type volume", func() { 3490 hostPathLocation := filepath.Join(tempdir, "file") 3491 3492 pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation))) 3493 err := generateKubeYaml("pod", pod, kubeYaml) 3494 Expect(err).ToNot(HaveOccurred()) 3495 3496 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3497 kube.WaitWithDefaultTimeout() 3498 Expect(kube).To(ExitWithError(125, fmt.Sprintf(`failed to create volume "testVol": in parsing HostPath in YAML: faccessat %s: no such file or directory`, hostPathLocation))) 3499 }) 3500 3501 It("test with File HostPath type volume", func() { 3502 hostPathLocation := filepath.Join(tempdir, "file") 3503 f, err := os.Create(hostPathLocation) 3504 Expect(err).ToNot(HaveOccurred()) 3505 f.Close() 3506 3507 pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation))) 3508 err = generateKubeYaml("pod", pod, kubeYaml) 3509 Expect(err).ToNot(HaveOccurred()) 3510 3511 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3512 kube.WaitWithDefaultTimeout() 3513 Expect(kube).Should(ExitCleanly()) 3514 }) 3515 3516 It("test with FileOrCreate HostPath type volume", func() { 3517 hostPathLocation := filepath.Join(tempdir, "file") 3518 3519 pod := getPod(withVolume(getHostPathVolume("FileOrCreate", hostPathLocation))) 3520 err := generateKubeYaml("pod", pod, kubeYaml) 3521 Expect(err).ToNot(HaveOccurred()) 3522 3523 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3524 kube.WaitWithDefaultTimeout() 3525 Expect(kube).Should(ExitCleanly()) 3526 3527 // the file should have been created 3528 _, err = os.Stat(hostPathLocation) 3529 Expect(err).ToNot(HaveOccurred()) 3530 }) 3531 3532 It("test with DirectoryOrCreate HostPath type volume", func() { 3533 hostPathLocation := filepath.Join(tempdir, "file") 3534 3535 pod := getPod(withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation))) 3536 err := generateKubeYaml("pod", pod, kubeYaml) 3537 Expect(err).ToNot(HaveOccurred()) 3538 3539 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3540 kube.WaitWithDefaultTimeout() 3541 Expect(kube).Should(ExitCleanly()) 3542 3543 // the file should have been created 3544 st, err := os.Stat(hostPathLocation) 3545 Expect(err).ToNot(HaveOccurred()) 3546 Expect(st.Mode().IsDir()).To(BeTrue(), "hostPathLocation is a directory") 3547 }) 3548 3549 It("test with DirectoryOrCreate HostPath type volume and non-existent directory path", func() { 3550 hostPathLocation := filepath.Join(filepath.Join(tempdir, "dir1"), "dir2") 3551 3552 pod := getPod(withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation))) 3553 err := generateKubeYaml("pod", pod, kubeYaml) 3554 Expect(err).ToNot(HaveOccurred()) 3555 3556 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3557 kube.WaitWithDefaultTimeout() 3558 Expect(kube).Should(ExitCleanly()) 3559 3560 // the full path should have been created 3561 st, err := os.Stat(hostPathLocation) 3562 Expect(err).ToNot(HaveOccurred()) 3563 Expect(st.Mode().IsDir()).To(BeTrue(), "hostPathLocation is a directory") 3564 }) 3565 3566 It("test with DirectoryOrCreate HostPath type volume and existent directory path", func() { 3567 hostPathLocation := filepath.Join(filepath.Join(tempdir, "dir1"), "dir2") 3568 Expect(os.MkdirAll(hostPathLocation, os.ModePerm)).To(Succeed()) 3569 3570 pod := getPod(withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation))) 3571 err := generateKubeYaml("pod", pod, kubeYaml) 3572 Expect(err).ToNot(HaveOccurred()) 3573 3574 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3575 kube.WaitWithDefaultTimeout() 3576 Expect(kube).Should(ExitCleanly()) 3577 }) 3578 3579 It("test with Socket HostPath type volume should fail if not socket", func() { 3580 hostPathLocation := filepath.Join(tempdir, "file") 3581 f, err := os.Create(hostPathLocation) 3582 Expect(err).ToNot(HaveOccurred()) 3583 f.Close() 3584 3585 pod := getPod(withVolume(getHostPathVolume("Socket", hostPathLocation))) 3586 err = generateKubeYaml("pod", pod, kubeYaml) 3587 Expect(err).ToNot(HaveOccurred()) 3588 3589 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3590 kube.WaitWithDefaultTimeout() 3591 Expect(kube).To(ExitWithError(125, fmt.Sprintf(`failed to create volume "testVol": checking HostPathSocket: path %s is not a socket`, hostPathLocation))) 3592 }) 3593 3594 It("test with read-only HostPath volume", func() { 3595 hostPathLocation := filepath.Join(tempdir, "file") 3596 f, err := os.Create(hostPathLocation) 3597 Expect(err).ToNot(HaveOccurred()) 3598 f.Close() 3599 3600 ctr := getCtr(withVolumeMount(hostPathLocation, "", true), withImage(CITEST_IMAGE)) 3601 pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)), withCtr(ctr)) 3602 err = generateKubeYaml("pod", pod, kubeYaml) 3603 Expect(err).ToNot(HaveOccurred()) 3604 3605 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3606 kube.WaitWithDefaultTimeout() 3607 Expect(kube).Should(ExitCleanly()) 3608 3609 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{.HostConfig.Binds}}'"}) 3610 inspect.WaitWithDefaultTimeout() 3611 Expect(inspect).Should(ExitCleanly()) 3612 3613 correct := fmt.Sprintf("%s:%s:%s", hostPathLocation, hostPathLocation, "ro") 3614 Expect(inspect.OutputToString()).To(ContainSubstring(correct)) 3615 }) 3616 3617 It("test duplicate volume destination between host path and image volumes", func() { 3618 // Create host test directory and file 3619 testdir := "testdir" 3620 testfile := "testfile" 3621 3622 hostPathDir := filepath.Join(tempdir, testdir) 3623 err := os.Mkdir(hostPathDir, 0755) 3624 Expect(err).ToNot(HaveOccurred()) 3625 defer os.RemoveAll(hostPathDir) 3626 3627 hostPathDirFile := filepath.Join(hostPathDir, testfile) 3628 f, err := os.Create(hostPathDirFile) 3629 Expect(err).ToNot(HaveOccurred()) 3630 f.Close() 3631 3632 if selinux.GetEnabled() { 3633 label := SystemExec("chcon", []string{"-t", "container_file_t", hostPathDirFile}) 3634 Expect(label).Should(ExitCleanly()) 3635 } 3636 3637 // Create container image with named volume 3638 containerfile := fmt.Sprintf(` 3639 FROM %s 3640 VOLUME %s`, CITEST_IMAGE, hostPathDir+"/") 3641 3642 image := "podman-kube-test:podman" 3643 podmanTest.BuildImage(containerfile, image, "false") 3644 3645 // Create and kube play pod 3646 ctr := getCtr(withVolumeMount(hostPathDir+"/", "", false), withImage(image)) 3647 pod := getPod(withCtr(ctr), withVolume(getHostPathVolume("Directory", hostPathDir+"/"))) 3648 err = generateKubeYaml("pod", pod, kubeYaml) 3649 Expect(err).ToNot(HaveOccurred()) 3650 3651 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3652 kube.WaitWithDefaultTimeout() 3653 Expect(kube).Should(ExitCleanly()) 3654 3655 result := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "ls", filepath.Join(hostPathDir, testfile)}) 3656 result.WaitWithDefaultTimeout() 3657 Expect(result).Should(ExitCleanly()) 3658 3659 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 3660 inspect.WaitWithDefaultTimeout() 3661 Expect(inspect).Should(ExitCleanly()) 3662 3663 // If two volumes are specified and share the same destination, 3664 // only one will be mounted. Host path volumes take precedence. 3665 ctrJSON := inspect.InspectContainerToJSON() 3666 Expect(ctrJSON[0].Mounts).To(HaveLen(1)) 3667 Expect(ctrJSON[0].Mounts[0]).To(HaveField("Type", define.TypeBind)) 3668 3669 }) 3670 3671 It("test with PersistentVolumeClaim volume", func() { 3672 volumeName := "namedVolume" 3673 3674 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 3675 pod := getPod(withVolume(getPersistentVolumeClaimVolume(volumeName)), withCtr(ctr)) 3676 err = generateKubeYaml("pod", pod, kubeYaml) 3677 Expect(err).ToNot(HaveOccurred()) 3678 3679 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3680 kube.WaitWithDefaultTimeout() 3681 Expect(kube).Should(ExitCleanly()) 3682 3683 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"}) 3684 inspect.WaitWithDefaultTimeout() 3685 Expect(inspect).Should(ExitCleanly()) 3686 3687 correct := fmt.Sprintf("volume:%s", volumeName) 3688 Expect(inspect.OutputToString()).To(Equal(correct)) 3689 }) 3690 3691 It("ConfigMap volume with no items", func() { 3692 volumeName := "cmVol" 3693 cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar")) 3694 cmYaml, err := getKubeYaml("configmap", cm) 3695 Expect(err).ToNot(HaveOccurred()) 3696 3697 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 3698 pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, false, nil)), withCtr(ctr)) 3699 podYaml, err := getKubeYaml("pod", pod) 3700 Expect(err).ToNot(HaveOccurred()) 3701 yamls := []string{cmYaml, podYaml} 3702 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3703 Expect(err).ToNot(HaveOccurred()) 3704 3705 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3706 kube.WaitWithDefaultTimeout() 3707 Expect(kube).Should(ExitCleanly()) 3708 3709 cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 3710 cmData.WaitWithDefaultTimeout() 3711 Expect(cmData).Should(ExitCleanly()) 3712 Expect(cmData.OutputToString()).To(Equal("foobar")) 3713 }) 3714 3715 It("ConfigMap volume with items", func() { 3716 volumeName := "cmVol" 3717 cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar")) 3718 cmYaml, err := getKubeYaml("configmap", cm) 3719 Expect(err).ToNot(HaveOccurred()) 3720 volumeContents := []map[string]string{{ 3721 "key": "FOO", 3722 "path": "BAR", 3723 }} 3724 3725 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 3726 pod := getPod(withVolume(getConfigMapVolume(volumeName, volumeContents, false, nil)), withCtr(ctr)) 3727 podYaml, err := getKubeYaml("pod", pod) 3728 Expect(err).ToNot(HaveOccurred()) 3729 yamls := []string{cmYaml, podYaml} 3730 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3731 Expect(err).ToNot(HaveOccurred()) 3732 3733 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3734 kube.WaitWithDefaultTimeout() 3735 Expect(kube).Should(ExitCleanly()) 3736 3737 cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/BAR"}) 3738 cmData.WaitWithDefaultTimeout() 3739 Expect(cmData).Should(ExitCleanly()) 3740 Expect(cmData.OutputToString()).To(Equal("foobar")) 3741 3742 cmData = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 3743 cmData.WaitWithDefaultTimeout() 3744 Expect(cmData).Should(Not(ExitCleanly())) 3745 }) 3746 3747 It("with a missing optional ConfigMap volume", func() { 3748 volumeName := "cmVol" 3749 3750 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 3751 pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, true, nil)), withCtr(ctr)) 3752 err = generateKubeYaml("pod", pod, kubeYaml) 3753 Expect(err).ToNot(HaveOccurred()) 3754 3755 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3756 kube.WaitWithDefaultTimeout() 3757 Expect(kube).Should(ExitCleanly()) 3758 }) 3759 3760 It("ConfigMap volume with defaultMode set", func() { 3761 volumeName := "cmVol" 3762 cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar")) 3763 cmYaml, err := getKubeYaml("configmap", cm) 3764 Expect(err).ToNot(HaveOccurred()) 3765 3766 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 3767 defaultMode := int32(0777) 3768 pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, false, &defaultMode)), withCtr(ctr)) 3769 podYaml, err := getKubeYaml("pod", pod) 3770 Expect(err).ToNot(HaveOccurred()) 3771 yamls := []string{cmYaml, podYaml} 3772 err = generateMultiDocKubeYaml(yamls, kubeYaml) 3773 Expect(err).ToNot(HaveOccurred()) 3774 3775 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3776 kube.WaitWithDefaultTimeout() 3777 Expect(kube).Should(ExitCleanly()) 3778 3779 cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 3780 cmData.WaitWithDefaultTimeout() 3781 Expect(cmData).Should(ExitCleanly()) 3782 Expect(cmData.OutputToString()).To(Equal("foobar")) 3783 3784 inspect := podmanTest.Podman([]string{"volume", "inspect", volumeName, "--format", "{{.Mountpoint}}"}) 3785 inspect.WaitWithDefaultTimeout() 3786 Expect(inspect).Should(ExitCleanly()) 3787 Expect(inspect.OutputToStringArray()).To(HaveLen(1)) 3788 path := inspect.OutputToString() 3789 3790 permData := SystemExec("stat", []string{"-c", "%a", path + "/FOO"}) 3791 permData.WaitWithDefaultTimeout() 3792 Expect(permData).Should(ExitCleanly()) 3793 Expect(permData.OutputToString()).To(Equal("777")) 3794 }) 3795 3796 It("configMap as volume with no defaultMode set", func() { 3797 cmYaml := ` 3798 kind: ConfigMap 3799 apiVersion: v1 3800 metadata: 3801 name: example-configmap 3802 data: 3803 foo: bar 3804 --- 3805 apiVersion: v1 3806 kind: Pod 3807 metadata: 3808 name: youthfulshaw-pod 3809 spec: 3810 containers: 3811 - command: 3812 - sleep 3813 - "1000" 3814 image: alpine 3815 name: youthfulshaw 3816 volumeMounts: 3817 - name: cm-volume 3818 mountPath: /test 3819 volumes: 3820 - name: cm-volume 3821 configMap: 3822 name: example-configmap 3823 ` 3824 3825 err := writeYaml(cmYaml, kubeYaml) 3826 Expect(err).ToNot(HaveOccurred()) 3827 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3828 kube.WaitWithDefaultTimeout() 3829 Expect(kube).Should(ExitCleanly()) 3830 3831 cmData := podmanTest.Podman([]string{"exec", "youthfulshaw-pod-youthfulshaw", "cat", "/test/foo"}) 3832 cmData.WaitWithDefaultTimeout() 3833 Expect(cmData).Should(ExitCleanly()) 3834 Expect(cmData.OutputToString()).To(Equal("bar")) 3835 3836 inspect := podmanTest.Podman([]string{"volume", "inspect", "example-configmap", "--format", "{{.Mountpoint}}"}) 3837 inspect.WaitWithDefaultTimeout() 3838 Expect(inspect).Should(ExitCleanly()) 3839 Expect(inspect.OutputToStringArray()).To(HaveLen(1)) 3840 path := inspect.OutputToString() 3841 3842 permData := SystemExec("stat", []string{"-c", "%a", path + "/foo"}) 3843 permData.WaitWithDefaultTimeout() 3844 Expect(permData).Should(ExitCleanly()) 3845 Expect(permData.OutputToString()).To(Equal("644")) 3846 }) 3847 3848 It("with emptyDir volume", func() { 3849 podName := "test-pod" 3850 ctrName1 := "vol-test-ctr" 3851 ctrName2 := "vol-test-ctr-2" 3852 ctr1 := getCtr(withVolumeMount("/test-emptydir", "", false), withImage(CITEST_IMAGE), withName(ctrName1)) 3853 ctr2 := getCtr(withVolumeMount("/test-emptydir-2", "", false), withImage(CITEST_IMAGE), withName(ctrName2)) 3854 pod := getPod(withPodName(podName), withVolume(getEmptyDirVolume()), withCtr(ctr1), withCtr(ctr2)) 3855 err = generateKubeYaml("pod", pod, kubeYaml) 3856 Expect(err).ToNot(HaveOccurred()) 3857 3858 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3859 kube.WaitWithDefaultTimeout() 3860 Expect(kube).Should(ExitCleanly()) 3861 3862 emptyDirCheck1 := podmanTest.Podman([]string{"exec", podName + "-" + ctrName1, "ls", "/test-emptydir"}) 3863 emptyDirCheck1.WaitWithDefaultTimeout() 3864 Expect(emptyDirCheck1).Should(ExitCleanly()) 3865 3866 emptyDirCheck2 := podmanTest.Podman([]string{"exec", podName + "-" + ctrName2, "ls", "/test-emptydir-2"}) 3867 emptyDirCheck2.WaitWithDefaultTimeout() 3868 Expect(emptyDirCheck2).Should(ExitCleanly()) 3869 3870 volList1 := podmanTest.Podman([]string{"volume", "ls", "-q"}) 3871 volList1.WaitWithDefaultTimeout() 3872 Expect(volList1).Should(ExitCleanly()) 3873 Expect(volList1.OutputToString()).To(Equal(defaultVolName)) 3874 3875 remove := podmanTest.Podman([]string{"pod", "rm", "-f", podName}) 3876 remove.WaitWithDefaultTimeout() 3877 Expect(remove).Should(ExitCleanly()) 3878 3879 volList2 := podmanTest.Podman([]string{"volume", "ls", "-q"}) 3880 volList2.WaitWithDefaultTimeout() 3881 Expect(volList2).Should(ExitCleanly()) 3882 Expect(volList2.OutputToString()).To(Equal("")) 3883 }) 3884 3885 It("applies labels to pods", func() { 3886 var numReplicas int32 = 5 3887 expectedLabelKey := "key1" 3888 expectedLabelValue := "value1" 3889 deployment := getDeployment( 3890 withReplicas(numReplicas), 3891 withPod(getPod(withLabel(expectedLabelKey, expectedLabelValue))), 3892 ) 3893 err := generateKubeYaml("deployment", deployment, kubeYaml) 3894 Expect(err).ToNot(HaveOccurred()) 3895 3896 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3897 kube.WaitWithDefaultTimeout() 3898 Expect(kube).Should(Exit(0)) 3899 if IsRemote() { 3900 Expect(kube.ErrorToString()).To(BeEmpty()) 3901 } else { 3902 Expect(kube.ErrorToString()).To(ContainSubstring("Limiting replica count to 1, more than one replica is not supported by Podman")) 3903 } 3904 3905 correctLabels := expectedLabelKey + ":" + expectedLabelValue 3906 pod := getPodNameInDeployment(deployment) 3907 inspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{ .Labels }}'"}) 3908 inspect.WaitWithDefaultTimeout() 3909 Expect(inspect).Should(ExitCleanly()) 3910 Expect(inspect.OutputToString()).To(ContainSubstring(correctLabels)) 3911 }) 3912 3913 It("allows setting resource limits", func() { 3914 SkipIfContainerized("Resource limits require a running systemd") 3915 SkipIfRootless("CPU limits require root") 3916 podmanTest.CgroupManager = "systemd" 3917 3918 var ( 3919 numReplicas int32 = 3 3920 expectedCPURequest = "100m" 3921 expectedCPULimit = "200m" 3922 expectedMemoryRequest = "10000000" 3923 expectedMemoryLimit = "20000000" 3924 ) 3925 3926 expectedCPUQuota := milliCPUToQuota(expectedCPULimit) 3927 3928 deployment := getDeployment( 3929 withReplicas(numReplicas), 3930 withPod(getPod(withCtr(getCtr( 3931 withCPURequest(expectedCPURequest), 3932 withCPULimit(expectedCPULimit), 3933 withMemoryRequest(expectedMemoryRequest), 3934 withMemoryLimit(expectedMemoryLimit), 3935 ))))) 3936 err := generateKubeYaml("deployment", deployment, kubeYaml) 3937 Expect(err).ToNot(HaveOccurred()) 3938 3939 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3940 kube.WaitWithDefaultTimeout() 3941 Expect(kube).Should(Exit(0)) 3942 if IsRemote() { 3943 Expect(kube.ErrorToString()).To(BeEmpty()) 3944 } else { 3945 Expect(kube.ErrorToString()).To(ContainSubstring("Limiting replica count to 1, more than one replica is not supported by Podman")) 3946 } 3947 3948 pod := getPodNameInDeployment(deployment) 3949 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", ` 3950 CpuPeriod: {{ .HostConfig.CpuPeriod }} 3951 CpuQuota: {{ .HostConfig.CpuQuota }} 3952 Memory: {{ .HostConfig.Memory }} 3953 MemoryReservation: {{ .HostConfig.MemoryReservation }}`}) 3954 inspect.WaitWithDefaultTimeout() 3955 Expect(inspect).Should(ExitCleanly()) 3956 Expect(inspect.OutputToString()).To(ContainSubstring(fmt.Sprintf("%s: %d", "CpuQuota", expectedCPUQuota))) 3957 Expect(inspect.OutputToString()).To(ContainSubstring("MemoryReservation: " + expectedMemoryRequest)) 3958 Expect(inspect.OutputToString()).To(ContainSubstring("Memory: " + expectedMemoryLimit)) 3959 3960 }) 3961 3962 It("allows setting resource limits with --cpus 1", func() { 3963 SkipIfContainerized("Resource limits require a running systemd") 3964 SkipIfRootless("CPU limits require root") 3965 podmanTest.CgroupManager = "systemd" 3966 3967 var ( 3968 expectedCPULimit = "1" 3969 ) 3970 3971 deployment := getDeployment( 3972 withPod(getPod(withCtr(getCtr( 3973 withCPULimit(expectedCPULimit), 3974 ))))) 3975 err := generateKubeYaml("deployment", deployment, kubeYaml) 3976 Expect(err).ToNot(HaveOccurred()) 3977 3978 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 3979 kube.WaitWithDefaultTimeout() 3980 Expect(kube).Should(ExitCleanly()) 3981 3982 pod := getPodNameInDeployment(deployment) 3983 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", `{{ .HostConfig.CpuPeriod }}:{{ .HostConfig.CpuQuota }}`}) 3984 3985 inspect.WaitWithDefaultTimeout() 3986 Expect(inspect).Should(ExitCleanly()) 3987 3988 parts := strings.Split(strings.Trim(inspect.OutputToString(), "\n"), ":") 3989 Expect(parts).To(HaveLen(2)) 3990 3991 Expect(parts[0]).To(Equal(parts[1])) 3992 3993 }) 3994 3995 It("reports invalid image name", func() { 3996 invalidImageName := "./myimage" 3997 3998 pod := getPod( 3999 withCtr( 4000 getCtr( 4001 withImage(invalidImageName), 4002 ), 4003 ), 4004 ) 4005 err := generateKubeYaml("pod", pod, kubeYaml) 4006 Expect(err).ToNot(HaveOccurred()) 4007 4008 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4009 kube.WaitWithDefaultTimeout() 4010 Expect(kube).Should(ExitWithError(125, "invalid reference format")) 4011 }) 4012 4013 It("applies log driver to containers", func() { 4014 SkipIfInContainer("journald inside a container doesn't work") 4015 pod := getPod() 4016 err := generateKubeYaml("pod", pod, kubeYaml) 4017 Expect(err).ToNot(HaveOccurred()) 4018 4019 kube := podmanTest.Podman([]string{"kube", "play", "--log-opt=max-size=10k", "--log-driver", "journald", kubeYaml}) 4020 kube.WaitWithDefaultTimeout() 4021 Expect(kube).Should(ExitCleanly()) 4022 4023 cid := getCtrNameInPod(pod) 4024 inspect := podmanTest.Podman([]string{"inspect", cid, "--format", "'{{ .HostConfig.LogConfig.Type }}'"}) 4025 inspect.WaitWithDefaultTimeout() 4026 Expect(inspect).Should(ExitCleanly()) 4027 Expect(inspect.OutputToString()).To(ContainSubstring("journald")) 4028 inspect = podmanTest.Podman([]string{"container", "inspect", "--format", "{{.HostConfig.LogConfig.Size}}", cid}) 4029 inspect.WaitWithDefaultTimeout() 4030 Expect(inspect).To(ExitCleanly()) 4031 Expect(inspect.OutputToString()).To(Equal("10kB")) 4032 }) 4033 4034 It("test only creating the containers", func() { 4035 pod := getPod() 4036 err := generateKubeYaml("pod", pod, kubeYaml) 4037 Expect(err).ToNot(HaveOccurred()) 4038 4039 kube := podmanTest.Podman([]string{"kube", "play", "--start=false", kubeYaml}) 4040 kube.WaitWithDefaultTimeout() 4041 Expect(kube).Should(ExitCleanly()) 4042 4043 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .State.Running }}"}) 4044 inspect.WaitWithDefaultTimeout() 4045 Expect(inspect).Should(ExitCleanly()) 4046 Expect(inspect.OutputToString()).To(Equal("false")) 4047 }) 4048 4049 It("test with HostNetwork", func() { 4050 pod := getPod(withHostNetwork(), withCtr(getCtr(withCmd([]string{"readlink", "/proc/self/ns/net"}), withArg(nil)))) 4051 err := generateKubeYaml("pod", pod, kubeYaml) 4052 Expect(err).ToNot(HaveOccurred()) 4053 4054 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4055 kube.WaitWithDefaultTimeout() 4056 Expect(kube).Should(ExitCleanly()) 4057 4058 inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.HostNetwork }}"}) 4059 inspect.WaitWithDefaultTimeout() 4060 Expect(inspect).Should(ExitCleanly()) 4061 Expect(inspect.OutputToString()).To(Equal("true")) 4062 4063 ns := SystemExec("readlink", []string{"/proc/self/ns/net"}) 4064 ns.WaitWithDefaultTimeout() 4065 Expect(ns).Should(ExitCleanly()) 4066 netns := ns.OutputToString() 4067 Expect(netns).ToNot(BeEmpty()) 4068 4069 logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)}) 4070 logs.WaitWithDefaultTimeout() 4071 Expect(logs).Should(ExitCleanly()) 4072 Expect(logs.OutputToString()).To(Equal(netns)) 4073 }) 4074 4075 It("test with kube default network", func() { 4076 pod := getPod() 4077 err := generateKubeYaml("pod", pod, kubeYaml) 4078 Expect(err).ToNot(HaveOccurred()) 4079 4080 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4081 kube.WaitWithDefaultTimeout() 4082 Expect(kube).Should(ExitCleanly()) 4083 4084 inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.Networks }}"}) 4085 inspect.WaitWithDefaultTimeout() 4086 Expect(inspect).Should(ExitCleanly()) 4087 Expect(inspect.OutputToString()).To(Equal("[podman-default-kube-network]")) 4088 }) 4089 4090 It("persistentVolumeClaim", func() { 4091 volName := "myvol" 4092 volDevice := define.TypeTmpfs 4093 volType := define.TypeTmpfs 4094 volOpts := "nodev,noexec" 4095 4096 pvc := getPVC(withPVCName(volName), 4097 withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice), 4098 withPVCAnnotations(util.VolumeTypeAnnotation, volType), 4099 withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts)) 4100 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 4101 Expect(err).ToNot(HaveOccurred()) 4102 4103 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4104 kube.WaitWithDefaultTimeout() 4105 Expect(kube).Should(ExitCleanly()) 4106 4107 inspect := podmanTest.Podman([]string{"inspect", volName, "--format", ` 4108 Name: {{ .Name }} 4109 Device: {{ .Options.device }} 4110 Type: {{ .Options.type }} 4111 o: {{ .Options.o }}`}) 4112 inspect.WaitWithDefaultTimeout() 4113 Expect(inspect).Should(ExitCleanly()) 4114 Expect(inspect.OutputToString()).To(ContainSubstring("Name: " + volName)) 4115 Expect(inspect.OutputToString()).To(ContainSubstring("Device: " + volDevice)) 4116 Expect(inspect.OutputToString()).To(ContainSubstring("Type: " + volType)) 4117 Expect(inspect.OutputToString()).To(ContainSubstring("o: " + volOpts)) 4118 }) 4119 4120 It("persistentVolumeClaim with source", func() { 4121 fileName := "data" 4122 expectedFileContent := "Test" 4123 tarFilePath := filepath.Join(podmanTest.TempDir, "podmanVolumeSource.tgz") 4124 err := createSourceTarFile(fileName, expectedFileContent, tarFilePath) 4125 Expect(err).ToNot(HaveOccurred()) 4126 4127 volName := "myVolWithStorage" 4128 pvc := getPVC(withPVCName(volName), 4129 withPVCAnnotations(util.VolumeImportSourceAnnotation, tarFilePath), 4130 ) 4131 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 4132 Expect(err).ToNot(HaveOccurred()) 4133 4134 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4135 kube.WaitWithDefaultTimeout() 4136 if IsRemote() { 4137 Expect(kube).Should(ExitWithError(125, "importing volumes is not supported for remote requests")) 4138 return 4139 } 4140 Expect(kube).Should(ExitCleanly()) 4141 4142 inspect := podmanTest.Podman([]string{"inspect", volName, "--format", ` 4143 { 4144 "Name": "{{ .Name }}", 4145 "Mountpoint": "{{ .Mountpoint }}" 4146 }`}) 4147 inspect.WaitWithDefaultTimeout() 4148 Expect(inspect).Should(ExitCleanly()) 4149 mp := make(map[string]string) 4150 err = json.Unmarshal([]byte(inspect.OutputToString()), &mp) 4151 Expect(err).ToNot(HaveOccurred()) 4152 Expect(mp["Name"]).To(Equal(volName)) 4153 files, err := os.ReadDir(mp["Mountpoint"]) 4154 Expect(err).ToNot(HaveOccurred()) 4155 Expect(files).To(HaveLen(1)) 4156 Expect(files[0].Name()).To(Equal(fileName)) 4157 }) 4158 4159 It("persistentVolumeClaim - image based", func() { 4160 volName := "myVolWithStorage" 4161 imageName := "quay.io/libpod/alpine_nginx:latest" 4162 pvc := getPVC(withPVCName(volName), 4163 withPVCAnnotations(util.VolumeDriverAnnotation, "image"), 4164 withPVCAnnotations(util.VolumeImageAnnotation, imageName), 4165 ) 4166 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 4167 Expect(err).ToNot(HaveOccurred()) 4168 4169 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4170 kube.WaitWithDefaultTimeout() 4171 Expect(kube).Should(ExitCleanly()) 4172 4173 inspect := podmanTest.Podman([]string{"inspect", volName, "--format", ` 4174 { 4175 "Name": "{{ .Name }}", 4176 "Driver": "{{ .Driver }}", 4177 "Image": "{{ .Options.image }}" 4178 }`}) 4179 inspect.WaitWithDefaultTimeout() 4180 Expect(inspect).Should(ExitCleanly()) 4181 mp := make(map[string]string) 4182 err = json.Unmarshal([]byte(inspect.OutputToString()), &mp) 4183 Expect(err).ToNot(HaveOccurred()) 4184 Expect(mp["Name"]).To(Equal(volName)) 4185 Expect(mp["Driver"]).To(Equal("image")) 4186 Expect(mp["Image"]).To(Equal(imageName)) 4187 }) 4188 4189 // Multi doc related tests 4190 It("multi doc yaml with persistentVolumeClaim, service and deployment", func() { 4191 yamlDocs := []string{} 4192 4193 serviceTemplate := `apiVersion: v1 4194 kind: Service 4195 metadata: 4196 name: %s 4197 spec: 4198 ports: 4199 - port: 80 4200 protocol: TCP 4201 targetPort: 9376 4202 selector: 4203 app: %s 4204 ` 4205 // generate persistentVolumeClaim 4206 volName := "multiFoo" 4207 pvc := getPVC(withPVCName(volName)) 4208 4209 // generate deployment 4210 deploymentName := "multiFoo" 4211 podName := "multiFoo" 4212 ctrName := "ctr-01" 4213 ctr := getCtr(withVolumeMount("/test", "", false)) 4214 ctr.Name = ctrName 4215 pod := getPod(withPodName(podName), withVolume(getPersistentVolumeClaimVolume(volName)), withCtr(ctr)) 4216 deployment := getDeployment(withPod(pod)) 4217 deployment.Name = deploymentName 4218 4219 // add pvc 4220 k, err := getKubeYaml("persistentVolumeClaim", pvc) 4221 Expect(err).ToNot(HaveOccurred()) 4222 yamlDocs = append(yamlDocs, k) 4223 4224 // add service 4225 yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, deploymentName, deploymentName)) 4226 4227 // add deployment 4228 k, err = getKubeYaml("deployment", deployment) 4229 Expect(err).ToNot(HaveOccurred()) 4230 yamlDocs = append(yamlDocs, k) 4231 4232 // generate multi doc yaml 4233 err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) 4234 Expect(err).ToNot(HaveOccurred()) 4235 4236 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4237 kube.WaitWithDefaultTimeout() 4238 Expect(kube).Should(ExitCleanly()) 4239 4240 inspectVolume := podmanTest.Podman([]string{"inspect", volName, "--format", "'{{ .Name }}'"}) 4241 inspectVolume.WaitWithDefaultTimeout() 4242 Expect(inspectVolume).Should(ExitCleanly()) 4243 Expect(inspectVolume.OutputToString()).To(ContainSubstring(volName)) 4244 4245 inspectPod := podmanTest.Podman([]string{"inspect", podName + "-pod", "--format", "'{{ .State }}'"}) 4246 inspectPod.WaitWithDefaultTimeout() 4247 Expect(inspectPod).Should(ExitCleanly()) 4248 Expect(inspectPod.OutputToString()).To(ContainSubstring(`Running`)) 4249 4250 inspectMounts := podmanTest.Podman([]string{"inspect", podName + "-pod-" + ctrName, "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"}) 4251 inspectMounts.WaitWithDefaultTimeout() 4252 Expect(inspectMounts).Should(ExitCleanly()) 4253 4254 correct := fmt.Sprintf("volume:%s", volName) 4255 Expect(inspectMounts.OutputToString()).To(Equal(correct)) 4256 }) 4257 4258 It("multi doc yaml with multiple services, pods and deployments", func() { 4259 yamlDocs := []string{} 4260 podNames := []string{} 4261 4262 serviceTemplate := `apiVersion: v1 4263 kind: Service 4264 metadata: 4265 name: %s 4266 spec: 4267 ports: 4268 - port: 80 4269 protocol: TCP 4270 targetPort: 9376 4271 selector: 4272 app: %s 4273 ` 4274 // generate services, pods and deployments 4275 for i := 0; i < 2; i++ { 4276 podName := fmt.Sprintf("testPod%d", i) 4277 deploymentName := fmt.Sprintf("testDeploy%d", i) 4278 deploymentPodName := fmt.Sprintf("%s-pod", deploymentName) 4279 4280 podNames = append(podNames, podName) 4281 podNames = append(podNames, deploymentPodName) 4282 4283 pod := getPod(withPodName(podName)) 4284 podDeployment := getPod(withPodName(deploymentName)) 4285 deployment := getDeployment(withPod(podDeployment)) 4286 deployment.Name = deploymentName 4287 4288 // add services 4289 yamlDocs = append([]string{ 4290 fmt.Sprintf(serviceTemplate, podName, podName), 4291 fmt.Sprintf(serviceTemplate, deploymentPodName, deploymentPodName)}, yamlDocs...) 4292 4293 // add pods 4294 k, err := getKubeYaml("pod", pod) 4295 Expect(err).ToNot(HaveOccurred()) 4296 yamlDocs = append(yamlDocs, k) 4297 4298 // add deployments 4299 k, err = getKubeYaml("deployment", deployment) 4300 Expect(err).ToNot(HaveOccurred()) 4301 yamlDocs = append(yamlDocs, k) 4302 } 4303 4304 // generate multi doc yaml 4305 err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) 4306 Expect(err).ToNot(HaveOccurred()) 4307 4308 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4309 kube.WaitWithDefaultTimeout() 4310 Expect(kube).Should(ExitCleanly()) 4311 4312 for _, n := range podNames { 4313 inspect := podmanTest.Podman([]string{"inspect", n, "--format", "'{{ .State }}'"}) 4314 inspect.WaitWithDefaultTimeout() 4315 Expect(inspect).Should(ExitCleanly()) 4316 Expect(inspect.OutputToString()).To(ContainSubstring(`Running`)) 4317 } 4318 }) 4319 4320 It("invalid multi doc yaml", func() { 4321 yamlDocs := []string{} 4322 4323 serviceTemplate := `apiVersion: v1 4324 kind: Service 4325 metadata: 4326 name: %s 4327 spec: 4328 ports: 4329 - port: 80 4330 protocol: TCP 4331 targetPort: 9376 4332 selector: 4333 app: %s 4334 --- 4335 invalid kube kind 4336 ` 4337 // add invalid multi doc yaml 4338 yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, "foo", "foo")) 4339 4340 // add pod 4341 pod := getPod() 4342 k, err := getKubeYaml("pod", pod) 4343 Expect(err).ToNot(HaveOccurred()) 4344 yamlDocs = append(yamlDocs, k) 4345 4346 // generate multi doc yaml 4347 err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) 4348 Expect(err).ToNot(HaveOccurred()) 4349 4350 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4351 kube.WaitWithDefaultTimeout() 4352 Expect(kube).To(ExitWithError(125, "multi doc yaml could not be split: yaml: line 12: found character that cannot start any token")) 4353 }) 4354 4355 It("with auto update annotations for all containers", func() { 4356 ctr01Name := "ctr01" 4357 ctr02Name := "infra" 4358 podName := "foo" 4359 autoUpdateRegistry := "io.containers.autoupdate" 4360 autoUpdateRegistryValue := "registry" 4361 autoUpdateAuthfile := "io.containers.autoupdate.authfile" 4362 autoUpdateAuthfileValue := "/some/authfile.json" 4363 4364 ctr01 := getCtr(withName(ctr01Name)) 4365 ctr02 := getCtr(withName(ctr02Name)) 4366 4367 pod := getPod( 4368 withPodName(podName), 4369 withCtr(ctr01), 4370 withCtr(ctr02), 4371 withAnnotation(autoUpdateRegistry, autoUpdateRegistryValue), 4372 withAnnotation(autoUpdateAuthfile, autoUpdateAuthfileValue)) 4373 4374 err = generateKubeYaml("pod", pod, kubeYaml) 4375 Expect(err).ToNot(HaveOccurred()) 4376 4377 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4378 kube.WaitWithDefaultTimeout() 4379 Expect(kube).Should(ExitCleanly()) 4380 4381 for _, ctr := range []string{podName + "-" + ctr01Name, podName + "-" + ctr02Name} { 4382 inspect := podmanTest.Podman([]string{"inspect", ctr, "--format", "'{{.Config.Labels}}'"}) 4383 inspect.WaitWithDefaultTimeout() 4384 Expect(inspect).Should(ExitCleanly()) 4385 4386 Expect(inspect.OutputToString()).To(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) 4387 Expect(inspect.OutputToString()).To(ContainSubstring(autoUpdateAuthfile + ":" + autoUpdateAuthfileValue)) 4388 } 4389 }) 4390 4391 It("with auto update annotations for first container only", func() { 4392 ctr01Name := "ctr01" 4393 ctr02Name := "ctr02" 4394 autoUpdateRegistry := "io.containers.autoupdate" 4395 autoUpdateRegistryValue := "local" 4396 4397 ctr01 := getCtr(withName(ctr01Name)) 4398 ctr02 := getCtr(withName(ctr02Name)) 4399 4400 pod := getPod( 4401 withCtr(ctr01), 4402 withCtr(ctr02), 4403 ) 4404 4405 deployment := getDeployment( 4406 withPod(pod), 4407 withDeploymentAnnotation(autoUpdateRegistry+"/"+ctr01Name, autoUpdateRegistryValue), 4408 ) 4409 4410 err = generateKubeYaml("deployment", deployment, kubeYaml) 4411 Expect(err).ToNot(HaveOccurred()) 4412 4413 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4414 kube.WaitWithDefaultTimeout() 4415 Expect(kube).Should(ExitCleanly()) 4416 4417 podName := getPodNameInDeployment(deployment).Name 4418 4419 inspect := podmanTest.Podman([]string{"inspect", podName + "-" + ctr01Name, "--format", "'{{.Config.Labels}}'"}) 4420 inspect.WaitWithDefaultTimeout() 4421 Expect(inspect).Should(ExitCleanly()) 4422 Expect(inspect.OutputToString()).To(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) 4423 4424 inspect = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"}) 4425 inspect.WaitWithDefaultTimeout() 4426 Expect(inspect).Should(ExitCleanly()) 4427 Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) 4428 }) 4429 4430 It("teardown", func() { 4431 pod := getPod() 4432 err := generateKubeYaml("pod", pod, kubeYaml) 4433 Expect(err).ToNot(HaveOccurred()) 4434 4435 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4436 kube.WaitWithDefaultTimeout() 4437 Expect(kube).Should(ExitCleanly()) 4438 4439 ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 4440 ls.WaitWithDefaultTimeout() 4441 Expect(ls).Should(ExitCleanly()) 4442 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 4443 4444 teardown := podmanTest.Podman([]string{"kube", "play", "--down", kubeYaml}) 4445 teardown.WaitWithDefaultTimeout() 4446 Expect(teardown).Should(ExitCleanly()) 4447 4448 // Removing a 2nd time to make sure no "no such error" is returned (see #19711) 4449 teardown = podmanTest.Podman([]string{"kube", "play", "--down", kubeYaml}) 4450 teardown.WaitWithDefaultTimeout() 4451 Expect(teardown).Should(ExitCleanly()) 4452 4453 checkls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 4454 checkls.WaitWithDefaultTimeout() 4455 Expect(checkls).Should(ExitCleanly()) 4456 Expect(checkls.OutputToStringArray()).To(BeEmpty()) 4457 }) 4458 4459 It("teardown with secret", func() { 4460 err := writeYaml(secretYaml, kubeYaml) 4461 Expect(err).ToNot(HaveOccurred()) 4462 4463 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4464 kube.WaitWithDefaultTimeout() 4465 Expect(kube).Should(ExitCleanly()) 4466 4467 ls := podmanTest.Podman([]string{"secret", "ls", "--format", "{{.ID}}"}) 4468 ls.WaitWithDefaultTimeout() 4469 Expect(ls).Should(ExitCleanly()) 4470 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 4471 4472 teardown := podmanTest.Podman([]string{"kube", "down", kubeYaml}) 4473 teardown.WaitWithDefaultTimeout() 4474 Expect(teardown).Should(ExitCleanly()) 4475 Expect(teardown.OutputToString()).Should(ContainSubstring(ls.OutputToString())) 4476 4477 // Removing a 2nd time to make sure no "no such error" is returned (see #19711) 4478 teardown = podmanTest.Podman([]string{"kube", "down", kubeYaml}) 4479 teardown.WaitWithDefaultTimeout() 4480 Expect(teardown).Should(ExitCleanly()) 4481 4482 checkls := podmanTest.Podman([]string{"secret", "ls", "--format", "'{{.ID}}'"}) 4483 checkls.WaitWithDefaultTimeout() 4484 Expect(checkls).Should(ExitCleanly()) 4485 Expect(checkls.OutputToStringArray()).To(BeEmpty()) 4486 }) 4487 4488 It("teardown pod does not exist", func() { 4489 err := writeYaml(simplePodYaml, kubeYaml) 4490 Expect(err).ToNot(HaveOccurred()) 4491 4492 teardown := podmanTest.Podman([]string{"kube", "play", "--down", kubeYaml}) 4493 teardown.WaitWithDefaultTimeout() 4494 Expect(teardown).Should(ExitCleanly()) 4495 }) 4496 4497 It("teardown volume --force", func() { 4498 4499 volName := RandomString(12) 4500 volDevice := define.TypeTmpfs 4501 volType := define.TypeTmpfs 4502 volOpts := "nodev,noexec" 4503 4504 pvc := getPVC(withPVCName(volName), 4505 withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice), 4506 withPVCAnnotations(util.VolumeTypeAnnotation, volType), 4507 withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts)) 4508 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 4509 Expect(err).ToNot(HaveOccurred()) 4510 4511 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4512 kube.WaitWithDefaultTimeout() 4513 Expect(kube).Should(ExitCleanly()) 4514 4515 exists := podmanTest.Podman([]string{"volume", "exists", volName}) 4516 exists.WaitWithDefaultTimeout() 4517 Expect(exists).To(ExitCleanly()) 4518 4519 teardown := podmanTest.Podman([]string{"kube", "play", "--down", kubeYaml}) 4520 teardown.WaitWithDefaultTimeout() 4521 Expect(teardown).To(ExitCleanly()) 4522 4523 // volume should not be deleted on teardown without --force 4524 exists = podmanTest.Podman([]string{"volume", "exists", volName}) 4525 exists.WaitWithDefaultTimeout() 4526 Expect(exists).To(ExitCleanly()) 4527 4528 // volume gets deleted with --force 4529 teardown = podmanTest.Podman([]string{"kube", "play", "--down", "--force", kubeYaml}) 4530 teardown.WaitWithDefaultTimeout() 4531 Expect(teardown).To(ExitCleanly()) 4532 4533 // Removing a 2nd should succeed as well even if no volume matches 4534 teardown = podmanTest.Podman([]string{"kube", "play", "--down", "--force", kubeYaml}) 4535 teardown.WaitWithDefaultTimeout() 4536 Expect(teardown).To(ExitCleanly()) 4537 4538 // volume should not be deleted on teardown 4539 exists = podmanTest.Podman([]string{"volume", "exists", volName}) 4540 exists.WaitWithDefaultTimeout() 4541 Expect(exists).To(Exit(1)) 4542 }) 4543 4544 It("after teardown with volume reuse", func() { 4545 4546 volName := RandomString(12) 4547 volDevice := define.TypeTmpfs 4548 volType := define.TypeTmpfs 4549 volOpts := "nodev,noexec" 4550 4551 pvc := getPVC(withPVCName(volName), 4552 withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice), 4553 withPVCAnnotations(util.VolumeTypeAnnotation, volType), 4554 withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts)) 4555 err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) 4556 Expect(err).ToNot(HaveOccurred()) 4557 4558 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4559 kube.WaitWithDefaultTimeout() 4560 Expect(kube).Should(ExitCleanly()) 4561 4562 exists := podmanTest.Podman([]string{"volume", "exists", volName}) 4563 exists.WaitWithDefaultTimeout() 4564 Expect(exists).To(ExitCleanly()) 4565 4566 teardown := podmanTest.Podman([]string{"kube", "play", "--down", kubeYaml}) 4567 teardown.WaitWithDefaultTimeout() 4568 Expect(teardown).To(ExitCleanly()) 4569 4570 // volume should not be deleted on teardown 4571 exists = podmanTest.Podman([]string{"volume", "exists", volName}) 4572 exists.WaitWithDefaultTimeout() 4573 Expect(exists).To(ExitCleanly()) 4574 4575 restart := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4576 restart.WaitWithDefaultTimeout() 4577 Expect(restart).To(ExitCleanly()) 4578 }) 4579 4580 It("use network mode from config", func() { 4581 confPath, err := filepath.Abs("config/containers-netns2.conf") 4582 Expect(err).ToNot(HaveOccurred()) 4583 os.Setenv("CONTAINERS_CONF", confPath) 4584 if IsRemote() { 4585 podmanTest.RestartRemoteService() 4586 } 4587 4588 pod := getPod() 4589 err = generateKubeYaml("pod", pod, kubeYaml) 4590 Expect(err).ToNot(HaveOccurred()) 4591 4592 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4593 kube.WaitWithDefaultTimeout() 4594 Expect(kube).Should(ExitCleanly()) 4595 4596 podInspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "{{.InfraContainerID}}"}) 4597 podInspect.WaitWithDefaultTimeout() 4598 Expect(podInspect).To(ExitCleanly()) 4599 infraID := podInspect.OutputToString() 4600 4601 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.NetworkMode}}", infraID}) 4602 inspect.WaitWithDefaultTimeout() 4603 Expect(inspect).To(ExitCleanly()) 4604 Expect(inspect.OutputToString()).To(Equal("bridge")) 4605 }) 4606 4607 It("replace", func() { 4608 pod := getPod() 4609 err := generateKubeYaml("pod", pod, kubeYaml) 4610 Expect(err).ToNot(HaveOccurred()) 4611 4612 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4613 kube.WaitWithDefaultTimeout() 4614 Expect(kube).Should(ExitCleanly()) 4615 4616 ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 4617 ls.WaitWithDefaultTimeout() 4618 Expect(ls).Should(ExitCleanly()) 4619 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 4620 4621 containerLen := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "{{len .Containers}}"}) 4622 containerLen.WaitWithDefaultTimeout() 4623 Expect(containerLen).Should(ExitCleanly()) 4624 Expect(containerLen.OutputToString()).To(Equal("2")) 4625 ctr01Name := "ctr01" 4626 ctr02Name := "ctr02" 4627 4628 ctr01 := getCtr(withName(ctr01Name)) 4629 ctr02 := getCtr(withName(ctr02Name)) 4630 4631 newPod := getPod( 4632 withCtr(ctr01), 4633 withCtr(ctr02), 4634 ) 4635 err = generateKubeYaml("pod", newPod, kubeYaml) 4636 Expect(err).ToNot(HaveOccurred()) 4637 4638 replace := podmanTest.Podman([]string{"kube", "play", "--replace", kubeYaml}) 4639 replace.WaitWithDefaultTimeout() 4640 Expect(replace).Should(ExitCleanly()) 4641 4642 newContainerLen := podmanTest.Podman([]string{"pod", "inspect", newPod.Name, "--format", "{{len .Containers}}"}) 4643 newContainerLen.WaitWithDefaultTimeout() 4644 Expect(newContainerLen).Should(ExitCleanly()) 4645 Expect(newContainerLen.OutputToString()).NotTo(Equal(containerLen.OutputToString())) 4646 }) 4647 4648 It("replace non-existing pod", func() { 4649 pod := getPod() 4650 err := generateKubeYaml("pod", pod, kubeYaml) 4651 Expect(err).ToNot(HaveOccurred()) 4652 4653 replace := podmanTest.Podman([]string{"kube", "play", "--replace", kubeYaml}) 4654 replace.WaitWithDefaultTimeout() 4655 Expect(replace).Should(ExitCleanly()) 4656 4657 ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"}) 4658 ls.WaitWithDefaultTimeout() 4659 Expect(ls).Should(ExitCleanly()) 4660 Expect(ls.OutputToStringArray()).To(HaveLen(1)) 4661 }) 4662 4663 It("RunAsUser", func() { 4664 ctr1Name := "ctr1" 4665 ctr2Name := "ctr2" 4666 ctr1 := getCtr(withName(ctr1Name), withSecurityContext(true), withRunAsUser("101"), withRunAsGroup("102")) 4667 ctr2 := getCtr(withName(ctr2Name), withSecurityContext(true)) 4668 4669 pod := getPod( 4670 withCtr(ctr1), 4671 withCtr(ctr2), 4672 withPodSecurityContext(true), 4673 withPodRunAsUser("103"), 4674 withPodRunAsGroup("104"), 4675 ) 4676 4677 err := generateKubeYaml("pod", pod, kubeYaml) 4678 Expect(err).ToNot(HaveOccurred()) 4679 4680 cmd := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4681 cmd.WaitWithDefaultTimeout() 4682 Expect(cmd).Should(ExitCleanly()) 4683 4684 // we expect the user:group as configured for the container 4685 inspect := podmanTest.Podman([]string{"container", "inspect", "--format", "'{{.Config.User}}'", makeCtrNameInPod(pod, ctr1Name)}) 4686 inspect.WaitWithDefaultTimeout() 4687 Expect(inspect.OutputToString()).To(Equal("'101:102'")) 4688 4689 // we expect the user:group as configured for the pod 4690 inspect = podmanTest.Podman([]string{"container", "inspect", "--format", "'{{.Config.User}}'", makeCtrNameInPod(pod, ctr2Name)}) 4691 inspect.WaitWithDefaultTimeout() 4692 Expect(inspect.OutputToString()).To(Equal("'103:104'")) 4693 }) 4694 4695 Describe("verify environment variables", func() { 4696 var maxLength int 4697 BeforeEach(func() { 4698 maxLength = format.MaxLength 4699 format.MaxLength = 0 4700 }) 4701 AfterEach(func() { 4702 format.MaxLength = maxLength 4703 }) 4704 4705 It("values containing equal sign", func() { 4706 javaToolOptions := `-XX:+IgnoreUnrecognizedVMOptions -XX:+IdleTuningGcOnIdle -Xshareclasses:name=openj9_system_scc,cacheDir=/opt/java/.scc,readonly,nonFatal` 4707 openj9JavaOptions := `-XX:+IgnoreUnrecognizedVMOptions -XX:+IdleTuningGcOnIdle -Xshareclasses:name=openj9_system_scc,cacheDir=/opt/java/.scc,readonly,nonFatal -Dosgi.checkConfiguration=false` 4708 4709 containerfile := fmt.Sprintf(`FROM %s 4710 ENV JAVA_TOOL_OPTIONS=%q 4711 ENV OPENJ9_JAVA_OPTIONS=%q 4712 `, 4713 CITEST_IMAGE, javaToolOptions, openj9JavaOptions) 4714 4715 image := "podman-kube-test:env" 4716 podmanTest.BuildImage(containerfile, image, "false") 4717 ctnr := getCtr(withImage(image)) 4718 pod := getPod(withCtr(ctnr)) 4719 Expect(generateKubeYaml("pod", pod, kubeYaml)).Should(Succeed()) 4720 4721 play := podmanTest.Podman([]string{"kube", "play", "--start", kubeYaml}) 4722 play.WaitWithDefaultTimeout() 4723 Expect(play).Should(ExitCleanly()) 4724 4725 inspect := podmanTest.Podman([]string{"container", "inspect", "--format=json", getCtrNameInPod(pod)}) 4726 inspect.WaitWithDefaultTimeout() 4727 Expect(inspect).Should(ExitCleanly()) 4728 4729 contents := string(inspect.Out.Contents()) 4730 Expect(contents).To(ContainSubstring(javaToolOptions)) 4731 Expect(contents).To(ContainSubstring(openj9JavaOptions)) 4732 }) 4733 }) 4734 4735 Context("with configmap in multi-doc yaml", func() { 4736 It("uses env value", func() { 4737 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4738 4739 cmYaml, err := getKubeYaml("configmap", cm) 4740 Expect(err).ToNot(HaveOccurred()) 4741 4742 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 4743 4744 podYaml, err := getKubeYaml("pod", pod) 4745 Expect(err).ToNot(HaveOccurred()) 4746 4747 yamls := []string{cmYaml, podYaml} 4748 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4749 Expect(err).ToNot(HaveOccurred()) 4750 4751 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4752 kube.WaitWithDefaultTimeout() 4753 Expect(kube).Should(ExitCleanly()) 4754 4755 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 4756 inspect.WaitWithDefaultTimeout() 4757 Expect(inspect).Should(ExitCleanly()) 4758 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 4759 }) 4760 4761 It("fails for required env value with missing key", func() { 4762 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4763 4764 cmYaml, err := getKubeYaml("configmap", cm) 4765 Expect(err).ToNot(HaveOccurred()) 4766 4767 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", false)))) 4768 4769 podYaml, err := getKubeYaml("pod", pod) 4770 Expect(err).ToNot(HaveOccurred()) 4771 4772 yamls := []string{cmYaml, podYaml} 4773 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4774 Expect(err).ToNot(HaveOccurred()) 4775 4776 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4777 kube.WaitWithDefaultTimeout() 4778 Expect(kube).To(ExitWithError(125, "cannot set env FOO: key MISSING_KEY not found in configmap foo")) 4779 }) 4780 4781 It("succeeds for optional env value with missing key", func() { 4782 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4783 4784 cmYaml, err := getKubeYaml("configmap", cm) 4785 Expect(err).ToNot(HaveOccurred()) 4786 4787 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "MISSING_KEY", true)))) 4788 4789 podYaml, err := getKubeYaml("pod", pod) 4790 Expect(err).ToNot(HaveOccurred()) 4791 4792 yamls := []string{cmYaml, podYaml} 4793 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4794 Expect(err).ToNot(HaveOccurred()) 4795 4796 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4797 kube.WaitWithDefaultTimeout() 4798 Expect(kube).Should(ExitCleanly()) 4799 4800 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ range .Config.Env }}[{{ . }}]{{end}}'"}) 4801 inspect.WaitWithDefaultTimeout() 4802 Expect(inspect).Should(ExitCleanly()) 4803 Expect(inspect.OutputToString()).To(Not(ContainSubstring(`[FOO=]`))) 4804 }) 4805 4806 It("uses all key-value pairs as envs", func() { 4807 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2")) 4808 cmYaml, err := getKubeYaml("configmap", cm) 4809 Expect(err).ToNot(HaveOccurred()) 4810 4811 pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap", false)))) 4812 4813 podYaml, err := getKubeYaml("pod", pod) 4814 Expect(err).ToNot(HaveOccurred()) 4815 4816 yamls := []string{cmYaml, podYaml} 4817 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4818 Expect(err).ToNot(HaveOccurred()) 4819 4820 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4821 kube.WaitWithDefaultTimeout() 4822 Expect(kube).Should(ExitCleanly()) 4823 4824 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 4825 inspect.WaitWithDefaultTimeout() 4826 Expect(inspect).Should(ExitCleanly()) 4827 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`)) 4828 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`)) 4829 }) 4830 4831 It("deployment uses variable from config map", func() { 4832 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4833 4834 cmYaml, err := getKubeYaml("configmap", cm) 4835 Expect(err).ToNot(HaveOccurred()) 4836 4837 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 4838 4839 deployment := getDeployment(withPod(pod)) 4840 deploymentYaml, err := getKubeYaml("deployment", deployment) 4841 Expect(err).ToNot(HaveOccurred(), "getKubeYaml(deployment)") 4842 yamls := []string{cmYaml, deploymentYaml} 4843 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4844 Expect(err).ToNot(HaveOccurred()) 4845 4846 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 4847 kube.WaitWithDefaultTimeout() 4848 Expect(kube).Should(ExitCleanly()) 4849 4850 inspect := podmanTest.Podman([]string{"inspect", fmt.Sprintf("%s-%s-%s", deployment.Name, "pod", defaultCtrName), "--format", "'{{ .Config }}'"}) 4851 inspect.WaitWithDefaultTimeout() 4852 Expect(inspect).Should(ExitCleanly()) 4853 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 4854 4855 }) 4856 4857 It("uses env value from configmap for HTTP API client", func() { 4858 SkipIfRemote("cannot run in a remote setup") 4859 address := url.URL{ 4860 Scheme: "tcp", 4861 Host: net.JoinHostPort("localhost", "8080"), 4862 } 4863 4864 session := podmanTest.Podman([]string{ 4865 "system", "service", "--log-level=debug", "--time=0", address.String(), 4866 }) 4867 defer session.Kill() 4868 4869 WaitForService(address) 4870 4871 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4872 cmYaml, err := getKubeYaml("configmap", cm) 4873 Expect(err).ToNot(HaveOccurred()) 4874 4875 pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO", false)))) 4876 podYaml, err := getKubeYaml("pod", pod) 4877 Expect(err).ToNot(HaveOccurred()) 4878 yamls := []string{cmYaml, podYaml} 4879 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4880 Expect(err).ToNot(HaveOccurred()) 4881 4882 podmanConnection, err := bindings.NewConnection(context.Background(), address.String()) 4883 Expect(err).ToNot(HaveOccurred()) 4884 4885 _, err = play.Kube(podmanConnection, kubeYaml, nil) 4886 Expect(err).ToNot(HaveOccurred()) 4887 4888 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 4889 inspect.WaitWithDefaultTimeout() 4890 Expect(inspect).Should(ExitCleanly()) 4891 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`)) 4892 }) 4893 }) 4894 4895 Context("with configmap in multi-doc yaml and files", func() { 4896 It("uses env values from both sources", func() { 4897 fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 4898 fsCm := getConfigMap(withConfigMapName("fooFs"), withConfigMapData("FOO_FS", "fooFS")) 4899 err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname) 4900 Expect(err).ToNot(HaveOccurred()) 4901 4902 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4903 4904 cmYaml, err := getKubeYaml("configmap", cm) 4905 Expect(err).ToNot(HaveOccurred()) 4906 4907 pod := getPod(withCtr(getCtr( 4908 withEnv("FOO_FS", "", "configmap", "fooFs", "FOO_FS", false), 4909 withEnv("FOO", "", "configmap", "foo", "FOO", false), 4910 ))) 4911 4912 podYaml, err := getKubeYaml("pod", pod) 4913 Expect(err).ToNot(HaveOccurred()) 4914 4915 yamls := []string{cmYaml, podYaml} 4916 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4917 Expect(err).ToNot(HaveOccurred()) 4918 4919 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", fsCmYamlPathname}) 4920 kube.WaitWithDefaultTimeout() 4921 Expect(kube).Should(ExitCleanly()) 4922 4923 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 4924 inspect.WaitWithDefaultTimeout() 4925 Expect(inspect).Should(ExitCleanly()) 4926 Expect(inspect.OutputToString()).To(And( 4927 ContainSubstring(`FOO=foo`), 4928 ContainSubstring(`FOO_FS=fooFS`), 4929 )) 4930 }) 4931 4932 It("uses all env values from both sources", func() { 4933 fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 4934 fsCm := getConfigMap(withConfigMapName("fooFs"), 4935 withConfigMapData("FOO_FS_1", "fooFS1"), 4936 withConfigMapData("FOO_FS_2", "fooFS2")) 4937 err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname) 4938 Expect(err).ToNot(HaveOccurred()) 4939 4940 cm := getConfigMap(withConfigMapName("foo"), 4941 withConfigMapData("FOO_1", "foo1"), 4942 withConfigMapData("FOO_2", "foo2"), 4943 ) 4944 4945 cmYaml, err := getKubeYaml("configmap", cm) 4946 Expect(err).ToNot(HaveOccurred()) 4947 4948 pod := getPod(withCtr(getCtr( 4949 withEnvFrom("foo", "configmap", false), 4950 withEnvFrom("fooFs", "configmap", false), 4951 ))) 4952 4953 podYaml, err := getKubeYaml("pod", pod) 4954 Expect(err).ToNot(HaveOccurred()) 4955 4956 yamls := []string{cmYaml, podYaml} 4957 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4958 Expect(err).ToNot(HaveOccurred()) 4959 4960 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", fsCmYamlPathname}) 4961 kube.WaitWithDefaultTimeout() 4962 Expect(kube).Should(ExitCleanly()) 4963 4964 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"}) 4965 inspect.WaitWithDefaultTimeout() 4966 Expect(inspect).Should(ExitCleanly()) 4967 Expect(inspect.OutputToString()).To(And( 4968 ContainSubstring(`FOO_1=foo1`), 4969 ContainSubstring(`FOO_2=foo2`), 4970 ContainSubstring(`FOO_FS_1=fooFS1`), 4971 ContainSubstring(`FOO_FS_2=fooFS2`), 4972 )) 4973 }) 4974 4975 It("reports error when the same configmap name is present in both sources", func() { 4976 // We will never hit this error in the remote case as the configmap content is appended to the main yaml content 4977 SkipIfRemote("--configmaps is appended to the main yaml for the remote case") 4978 4979 fsCmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml") 4980 fsCm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "fooFS")) 4981 err := generateKubeYaml("configmap", fsCm, fsCmYamlPathname) 4982 Expect(err).ToNot(HaveOccurred()) 4983 4984 cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo")) 4985 4986 cmYaml, err := getKubeYaml("configmap", cm) 4987 Expect(err).ToNot(HaveOccurred()) 4988 4989 pod := getPod(withCtr(getCtr( 4990 withEnv("FOO", "", "configmap", "foo", "FOO", false), 4991 ))) 4992 4993 podYaml, err := getKubeYaml("pod", pod) 4994 Expect(err).ToNot(HaveOccurred()) 4995 4996 yamls := []string{cmYaml, podYaml} 4997 err = generateMultiDocKubeYaml(yamls, kubeYaml) 4998 Expect(err).ToNot(HaveOccurred()) 4999 5000 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--configmap", fsCmYamlPathname}) 5001 kube.WaitWithDefaultTimeout() 5002 Expect(kube).Should(ExitWithError(125, "ambiguous configuration: the same config map foo is present in YAML and in --configmaps")) 5003 }) 5004 }) 5005 5006 It("--log-opt = tag test", func() { 5007 SkipIfContainerized("journald does not work inside the container") 5008 pod := getPod() 5009 err := generateKubeYaml("pod", pod, kubeYaml) 5010 Expect(err).ToNot(HaveOccurred()) 5011 5012 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml, "--log-driver", "journald", "--log-opt", "tag={{.ImageName}},withcomma"}) 5013 kube.WaitWithDefaultTimeout() 5014 Expect(kube).Should(ExitCleanly()) 5015 5016 start := podmanTest.Podman([]string{"start", getCtrNameInPod(pod)}) 5017 start.WaitWithDefaultTimeout() 5018 Expect(start).Should(ExitCleanly()) 5019 5020 inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)}) 5021 inspect.WaitWithDefaultTimeout() 5022 Expect(start).Should(ExitCleanly()) 5023 Expect((inspect.InspectContainerToJSON()[0]).HostConfig.LogConfig.Tag).To(Equal("{{.ImageName}},withcomma")) 5024 }) 5025 5026 It("using a user namespace", func() { 5027 u, err := user.Current() 5028 Expect(err).ToNot(HaveOccurred()) 5029 name := u.Username 5030 if name == "root" { 5031 name = "containers" 5032 } 5033 content, err := os.ReadFile("/etc/subuid") 5034 if err != nil { 5035 Skip("cannot read /etc/subuid") 5036 } 5037 if !strings.Contains(string(content), name) { 5038 Skip("cannot find mappings for the current user") 5039 } 5040 5041 initialUsernsConfig, err := os.ReadFile("/proc/self/uid_map") 5042 Expect(err).ToNot(HaveOccurred()) 5043 if isRootless() { 5044 // Use podmanTest.PodmanBinary because podman-remote unshare cannot be used 5045 cmd := exec.Command(podmanTest.PodmanBinary, "unshare", "cat", "/proc/self/uid_map") 5046 session, err := Start(cmd, GinkgoWriter, GinkgoWriter) 5047 Expect(err).ToNot(HaveOccurred()) 5048 Eventually(session, DefaultWaitTimeout).Should(Exit(0)) 5049 initialUsernsConfig = session.Out.Contents() 5050 } 5051 5052 pod := getPod() 5053 err = generateKubeYaml("pod", pod, kubeYaml) 5054 Expect(err).ToNot(HaveOccurred()) 5055 5056 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5057 kube.WaitWithDefaultTimeout() 5058 Expect(kube).Should(ExitCleanly()) 5059 5060 usernsInCtr := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/proc/self/uid_map"}) 5061 usernsInCtr.WaitWithDefaultTimeout() 5062 Expect(usernsInCtr).Should(ExitCleanly()) 5063 // the conversion to string is needed for better error messages 5064 Expect(string(usernsInCtr.Out.Contents())).To(Equal(string(initialUsernsConfig))) 5065 5066 // -q necessary for ExitCleanly() because --replace pulls image 5067 kube = podmanTest.Podman([]string{"kube", "play", "-q", "--replace", "--userns=auto", kubeYaml}) 5068 kube.WaitWithDefaultTimeout() 5069 Expect(kube).Should(ExitCleanly()) 5070 5071 usernsInCtr = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/proc/self/uid_map"}) 5072 usernsInCtr.WaitWithDefaultTimeout() 5073 Expect(usernsInCtr).Should(ExitCleanly()) 5074 Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig)))) 5075 5076 kube = podmanTest.PodmanNoCache([]string{"kube", "play", "-q", "--replace", "--userns=keep-id", kubeYaml}) 5077 kube.WaitWithDefaultTimeout() 5078 Expect(kube).Should(ExitCleanly()) 5079 5080 usernsInCtr = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "id", "-u"}) 5081 usernsInCtr.WaitWithDefaultTimeout() 5082 Expect(usernsInCtr).Should(ExitCleanly()) 5083 uid := strconv.Itoa(os.Geteuid()) 5084 Expect(string(usernsInCtr.Out.Contents())).To(ContainSubstring(uid)) 5085 5086 kube = podmanTest.PodmanNoCache([]string{"kube", "play", "--replace", "--userns=keep-id:uid=10,gid=12", kubeYaml}) 5087 kube.WaitWithDefaultTimeout() 5088 Expect(kube).Should(ExitCleanly()) 5089 5090 usernsInCtr = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "sh", "-c", "echo $(id -u):$(id -g)"}) 5091 usernsInCtr.WaitWithDefaultTimeout() 5092 Expect(usernsInCtr).Should(ExitCleanly()) 5093 Expect(string(usernsInCtr.Out.Contents())).To(ContainSubstring("10:12")) 5094 5095 // Now try with hostUsers in the pod spec 5096 for _, hostUsers := range []bool{true, false} { 5097 pod = getPod(withHostUsers(hostUsers)) 5098 err = generateKubeYaml("pod", pod, kubeYaml) 5099 Expect(err).ToNot(HaveOccurred()) 5100 5101 kube = podmanTest.PodmanNoCache([]string{"kube", "play", "--replace", kubeYaml}) 5102 kube.WaitWithDefaultTimeout() 5103 Expect(kube).Should(ExitCleanly()) 5104 5105 usernsInCtr = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/proc/self/uid_map"}) 5106 usernsInCtr.WaitWithDefaultTimeout() 5107 Expect(usernsInCtr).Should(ExitCleanly()) 5108 if hostUsers { 5109 Expect(string(usernsInCtr.Out.Contents())).To(Equal(string(initialUsernsConfig))) 5110 } else { 5111 Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig)))) 5112 } 5113 } 5114 }) 5115 5116 // Check the block devices are exposed inside container 5117 It("expose block device inside container", func() { 5118 SkipIfRootless("It needs root access to create devices") 5119 5120 // randomize the folder name to avoid error when running tests with multiple nodes 5121 uuid, err := uuid.NewUUID() 5122 Expect(err).ToNot(HaveOccurred()) 5123 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 5124 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(Succeed()) 5125 defer os.RemoveAll(devFolder) 5126 5127 devicePath := fmt.Sprintf("%s/blockdevice", devFolder) 5128 mknod := SystemExec("mknod", []string{devicePath, "b", "7", "0"}) 5129 mknod.WaitWithDefaultTimeout() 5130 Expect(mknod).Should(ExitCleanly()) 5131 5132 blockVolume := getHostPathVolume("BlockDevice", devicePath) 5133 5134 pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, "", false)))) 5135 err = generateKubeYaml("pod", pod, kubeYaml) 5136 Expect(err).ToNot(HaveOccurred()) 5137 5138 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5139 kube.WaitWithDefaultTimeout() 5140 Expect(kube).Should(ExitCleanly()) 5141 5142 // Container should be in running state 5143 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 5144 inspect.WaitWithDefaultTimeout() 5145 Expect(inspect).Should(ExitCleanly()) 5146 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 5147 5148 // Container should have a block device /dev/loop1 5149 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.Devices}}", "testPod-" + defaultCtrName}) 5150 inspect.WaitWithDefaultTimeout() 5151 Expect(inspect).Should(ExitCleanly()) 5152 Expect(inspect.OutputToString()).To(ContainSubstring(devicePath)) 5153 }) 5154 5155 // Check the char devices are exposed inside container 5156 It("expose character device inside container", func() { 5157 SkipIfRootless("It needs root access to create devices") 5158 5159 // randomize the folder name to avoid error when running tests with multiple nodes 5160 uuid, err := uuid.NewUUID() 5161 Expect(err).ToNot(HaveOccurred()) 5162 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 5163 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(Succeed()) 5164 defer os.RemoveAll(devFolder) 5165 5166 devicePath := fmt.Sprintf("%s/chardevice", devFolder) 5167 mknod := SystemExec("mknod", []string{devicePath, "c", "3", "1"}) 5168 mknod.WaitWithDefaultTimeout() 5169 Expect(mknod).Should(ExitCleanly()) 5170 5171 charVolume := getHostPathVolume("CharDevice", devicePath) 5172 5173 pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, "", false)))) 5174 err = generateKubeYaml("pod", pod, kubeYaml) 5175 Expect(err).ToNot(HaveOccurred()) 5176 5177 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5178 kube.WaitWithDefaultTimeout() 5179 Expect(kube).Should(ExitCleanly()) 5180 5181 // Container should be in running state 5182 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName}) 5183 inspect.WaitWithDefaultTimeout() 5184 Expect(inspect).Should(ExitCleanly()) 5185 Expect(inspect.OutputToString()).To(ContainSubstring("running")) 5186 5187 // Container should have a block device /dev/loop1 5188 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.Devices}}", "testPod-" + defaultCtrName}) 5189 inspect.WaitWithDefaultTimeout() 5190 Expect(inspect).Should(ExitCleanly()) 5191 Expect(inspect.OutputToString()).To(ContainSubstring(devicePath)) 5192 }) 5193 5194 It("reports error when the device does not exist", func() { 5195 SkipIfRootless("It needs root access to create devices") 5196 5197 devicePath := "/dev/foodevdir/baddevice" 5198 5199 blockVolume := getHostPathVolume("BlockDevice", devicePath) 5200 5201 pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, "", false)))) 5202 err = generateKubeYaml("pod", pod, kubeYaml) 5203 Expect(err).ToNot(HaveOccurred()) 5204 5205 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5206 kube.WaitWithDefaultTimeout() 5207 Expect(kube).Should(ExitWithError(125, fmt.Sprintf(`failed to create volume "testVol": checking HostPathBlockDevice: stat %s: no such file or directory`, devicePath))) 5208 }) 5209 5210 It("reports error when we try to expose char device as block device", func() { 5211 SkipIfRootless("It needs root access to create devices") 5212 5213 // randomize the folder name to avoid error when running tests with multiple nodes 5214 uuid, err := uuid.NewUUID() 5215 Expect(err).ToNot(HaveOccurred()) 5216 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 5217 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(Succeed()) 5218 defer os.RemoveAll(devFolder) 5219 5220 devicePath := fmt.Sprintf("%s/chardevice", devFolder) 5221 mknod := SystemExec("mknod", []string{devicePath, "c", "3", "1"}) 5222 mknod.WaitWithDefaultTimeout() 5223 Expect(mknod).Should(ExitCleanly()) 5224 5225 charVolume := getHostPathVolume("BlockDevice", devicePath) 5226 5227 pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, "", false)))) 5228 err = generateKubeYaml("pod", pod, kubeYaml) 5229 Expect(err).ToNot(HaveOccurred()) 5230 5231 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5232 kube.WaitWithDefaultTimeout() 5233 Expect(kube).Should(ExitWithError(125, fmt.Sprintf(`failed to create volume "testVol": checking HostPathDevice: path %s is not a block device`, devicePath))) 5234 }) 5235 5236 It("reports error when we try to expose block device as char device", func() { 5237 SkipIfRootless("It needs root access to create devices") 5238 5239 // randomize the folder name to avoid error when running tests with multiple nodes 5240 uuid, err := uuid.NewUUID() 5241 Expect(err).ToNot(HaveOccurred()) 5242 devFolder := fmt.Sprintf("/dev/foodev%x", uuid[:6]) 5243 Expect(os.MkdirAll(devFolder, os.ModePerm)).To(Succeed()) 5244 5245 devicePath := fmt.Sprintf("%s/blockdevice", devFolder) 5246 mknod := SystemExec("mknod", []string{devicePath, "b", "7", "0"}) 5247 mknod.WaitWithDefaultTimeout() 5248 Expect(mknod).Should(ExitCleanly()) 5249 5250 charVolume := getHostPathVolume("CharDevice", devicePath) 5251 5252 pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, "", false)))) 5253 err = generateKubeYaml("pod", pod, kubeYaml) 5254 Expect(err).ToNot(HaveOccurred()) 5255 5256 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5257 kube.WaitWithDefaultTimeout() 5258 Expect(kube).Should(ExitWithError(125, fmt.Sprintf(`failed to create volume "testVol": checking HostPathCharDevice: path %s is not a character device`, devicePath))) 5259 }) 5260 5261 It("secret as volume support - simple", func() { 5262 createAndTestSecret(podmanTest, secretYaml, "newsecret", kubeYaml) 5263 testPodWithSecret(podmanTest, secretPodYaml, kubeYaml, true, true) 5264 deleteAndTestSecret(podmanTest, "newsecret") 5265 }) 5266 5267 It("secret as volume support - multiple volumes", func() { 5268 yamls := []string{secretYaml, secretPodYaml} 5269 err = generateMultiDocKubeYaml(yamls, kubeYaml) 5270 Expect(err).ToNot(HaveOccurred()) 5271 5272 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5273 kube.WaitWithDefaultTimeout() 5274 Expect(kube).Should(ExitCleanly()) 5275 5276 // do not remove newsecret to test that we auto remove on collision 5277 5278 yamls = []string{secretYaml, complexSecretYaml} 5279 err = generateMultiDocKubeYaml(yamls, kubeYaml) 5280 Expect(err).ToNot(HaveOccurred()) 5281 5282 kube = podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5283 kube.WaitWithDefaultTimeout() 5284 Expect(kube).Should(ExitCleanly()) 5285 5286 err = writeYaml(secretPodYamlTwo, kubeYaml) 5287 Expect(err).ToNot(HaveOccurred()) 5288 5289 kube = podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5290 kube.WaitWithDefaultTimeout() 5291 Expect(kube).Should(ExitCleanly()) 5292 5293 exec := podmanTest.Podman([]string{"exec", "mypod2-myctr", "cat", "/etc/foo/username"}) 5294 exec.WaitWithDefaultTimeout() 5295 Expect(exec).Should(ExitCleanly()) 5296 username, _ := base64.StdEncoding.DecodeString("dXNlcg==") 5297 Expect(exec.OutputToString()).Should(ContainSubstring(string(username))) 5298 5299 exec = podmanTest.Podman([]string{"exec", "mypod2-myctr", "cat", "/etc/bar/username"}) 5300 exec.WaitWithDefaultTimeout() 5301 Expect(exec).Should(ExitCleanly()) 5302 username, _ = base64.StdEncoding.DecodeString("Y2RvZXJu") 5303 Expect(exec.OutputToString()).Should(ContainSubstring(string(username))) 5304 5305 exec = podmanTest.Podman([]string{"exec", "mypod2-myctr", "cat", "/etc/baz/plain_note"}) 5306 exec.WaitWithDefaultTimeout() 5307 Expect(exec).Should(ExitCleanly()) 5308 Expect(exec.OutputToString()).Should(ContainSubstring("This is a test")) 5309 5310 }) 5311 5312 It("secret as volume support - optional field", func() { 5313 createAndTestSecret(podmanTest, secretYaml, "newsecret", kubeYaml) 5314 5315 testPodWithSecret(podmanTest, optionalExistingSecretPodYaml, kubeYaml, true, true) 5316 testPodWithSecret(podmanTest, optionalNonExistingSecretPodYaml, kubeYaml, true, false) 5317 testPodWithSecret(podmanTest, noOptionalExistingSecretPodYaml, kubeYaml, true, true) 5318 testPodWithSecret(podmanTest, noOptionalNonExistingSecretPodYaml, kubeYaml, false, false) 5319 5320 deleteAndTestSecret(podmanTest, "newsecret") 5321 }) 5322 5323 It("secret as volume with no items", func() { 5324 volumeName := "secretVol" 5325 secret := getSecret(withSecretName(volumeName), withSecretData("FOO", "testuser")) 5326 secretYaml, err := getKubeYaml("secret", secret) 5327 Expect(err).ToNot(HaveOccurred()) 5328 5329 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 5330 pod := getPod(withVolume(getSecretVolume(volumeName, []map[string]string{}, false, nil)), withCtr(ctr)) 5331 podYaml, err := getKubeYaml("pod", pod) 5332 Expect(err).ToNot(HaveOccurred()) 5333 yamls := []string{secretYaml, podYaml} 5334 err = generateMultiDocKubeYaml(yamls, kubeYaml) 5335 Expect(err).ToNot(HaveOccurred()) 5336 5337 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5338 kube.WaitWithDefaultTimeout() 5339 Expect(kube).Should(ExitCleanly()) 5340 5341 secretData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 5342 secretData.WaitWithDefaultTimeout() 5343 Expect(secretData).Should(ExitCleanly()) 5344 Expect(secretData.OutputToString()).To(Equal("testuser")) 5345 }) 5346 5347 It("secret as volume with items", func() { 5348 volumeName := "secretVol" 5349 secret := getSecret(withSecretName(volumeName), withSecretData("FOO", "foobar")) 5350 secretYaml, err := getKubeYaml("secret", secret) 5351 Expect(err).ToNot(HaveOccurred()) 5352 volumeContents := []map[string]string{{ 5353 "key": "FOO", 5354 "path": "BAR", 5355 }} 5356 5357 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 5358 pod := getPod(withVolume(getSecretVolume(volumeName, volumeContents, false, nil)), withCtr(ctr)) 5359 podYaml, err := getKubeYaml("pod", pod) 5360 Expect(err).ToNot(HaveOccurred()) 5361 yamls := []string{secretYaml, podYaml} 5362 err = generateMultiDocKubeYaml(yamls, kubeYaml) 5363 Expect(err).ToNot(HaveOccurred()) 5364 5365 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5366 kube.WaitWithDefaultTimeout() 5367 Expect(kube).Should(ExitCleanly()) 5368 5369 secretData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/BAR"}) 5370 secretData.WaitWithDefaultTimeout() 5371 Expect(secretData).Should(ExitCleanly()) 5372 Expect(secretData.OutputToString()).To(Equal("foobar")) 5373 5374 secretData = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 5375 secretData.WaitWithDefaultTimeout() 5376 Expect(secretData).Should(Not(ExitCleanly())) 5377 5378 }) 5379 5380 It("secret as volume with defaultMode set", func() { 5381 volumeName := "secretVol" 5382 secret := getSecret(withSecretName(volumeName), withSecretData("FOO", "testuser")) 5383 secretYaml, err := getKubeYaml("secret", secret) 5384 Expect(err).ToNot(HaveOccurred()) 5385 5386 ctr := getCtr(withVolumeMount("/test", "", false), withImage(CITEST_IMAGE)) 5387 defaultMode := int32(0777) 5388 pod := getPod(withVolume(getSecretVolume(volumeName, []map[string]string{}, false, &defaultMode)), withCtr(ctr)) 5389 podYaml, err := getKubeYaml("pod", pod) 5390 Expect(err).ToNot(HaveOccurred()) 5391 yamls := []string{secretYaml, podYaml} 5392 err = generateMultiDocKubeYaml(yamls, kubeYaml) 5393 Expect(err).ToNot(HaveOccurred()) 5394 5395 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5396 kube.WaitWithDefaultTimeout() 5397 Expect(kube).Should(ExitCleanly()) 5398 5399 secretData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"}) 5400 secretData.WaitWithDefaultTimeout() 5401 Expect(secretData).Should(ExitCleanly()) 5402 Expect(secretData.OutputToString()).To(Equal("testuser")) 5403 5404 inspect := podmanTest.Podman([]string{"volume", "inspect", volumeName, "--format", "{{.Mountpoint}}"}) 5405 inspect.WaitWithDefaultTimeout() 5406 Expect(inspect).Should(ExitCleanly()) 5407 Expect(inspect.OutputToStringArray()).To(HaveLen(1)) 5408 path := inspect.OutputToString() 5409 5410 permData := SystemExec("stat", []string{"-c", "%a", path + "/FOO"}) 5411 permData.WaitWithDefaultTimeout() 5412 Expect(permData).Should(ExitCleanly()) 5413 Expect(permData.OutputToString()).To(Equal("777")) 5414 }) 5415 5416 It("secret as volume with no defaultMode set", func() { 5417 secretYaml := ` 5418 apiVersion: v1 5419 kind: Secret 5420 metadata: 5421 name: newsecret 5422 type: Opaque 5423 data: 5424 foo: dXNlcg== 5425 --- 5426 apiVersion: v1 5427 kind: Pod 5428 metadata: 5429 name: test-pod 5430 spec: 5431 containers: 5432 - command: 5433 - sleep 5434 - "1000" 5435 image: alpine 5436 name: test 5437 volumeMounts: 5438 - name: secret-volume 5439 mountPath: /test 5440 volumes: 5441 - name: secret-volume 5442 secret: 5443 secretName: newsecret 5444 ` 5445 5446 err := writeYaml(secretYaml, kubeYaml) 5447 Expect(err).ToNot(HaveOccurred()) 5448 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5449 kube.WaitWithDefaultTimeout() 5450 Expect(kube).Should(ExitCleanly()) 5451 5452 inspect := podmanTest.Podman([]string{"volume", "inspect", "newsecret", "--format", "{{.Mountpoint}}"}) 5453 inspect.WaitWithDefaultTimeout() 5454 Expect(inspect).Should(ExitCleanly()) 5455 Expect(inspect.OutputToStringArray()).To(HaveLen(1)) 5456 path := inspect.OutputToString() 5457 5458 permData := SystemExec("stat", []string{"-c", "%a", path + "/foo"}) 5459 permData.WaitWithDefaultTimeout() 5460 Expect(permData).Should(ExitCleanly()) 5461 Expect(permData.OutputToString()).To(Equal("644")) 5462 }) 5463 5464 It("with disabled cgroup", func() { 5465 SkipIfRunc(podmanTest, "Test not supported with runc (issue 17436, wontfix)") 5466 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 5467 // Disabled ipcns and cgroupfs in the config file 5468 // Since shmsize (Inherit from infra container) cannot be set if ipcns is "host", we should remove the default value. 5469 // Also, cgroupfs config should be loaded into SpecGenerator when playing kube. 5470 err := os.WriteFile(conffile, []byte(` 5471 [containers] 5472 ipcns="host" 5473 cgroups="disabled"`), 0644) 5474 Expect(err).ToNot(HaveOccurred()) 5475 os.Setenv("CONTAINERS_CONF", conffile) 5476 err = writeYaml(simplePodYaml, kubeYaml) 5477 Expect(err).ToNot(HaveOccurred()) 5478 5479 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5480 kube.WaitWithDefaultTimeout() 5481 Expect(kube).Should(ExitCleanly()) 5482 }) 5483 5484 It("podman kube --quiet with error", func() { 5485 SkipIfNotRootless("We need to create an error trying to bind to port 80") 5486 yaml := ` 5487 apiVersion: apps/v1 5488 kind: Deployment 5489 metadata: 5490 name: frontend 5491 spec: 5492 replicas: 2 5493 template: 5494 metadata: 5495 labels: 5496 app: guestbook 5497 tier: frontend 5498 spec: 5499 containers: 5500 - name: php-redis 5501 image: quay.io/libpod/alpine_nginx:latest 5502 ports: 5503 - containerPort: 1234 5504 hostPort: 80 5505 ` 5506 5507 err = writeYaml(yaml, kubeYaml) 5508 Expect(err).ToNot(HaveOccurred()) 5509 5510 kube := podmanTest.Podman([]string{"kube", "play", "--quiet", kubeYaml}) 5511 kube.WaitWithDefaultTimeout() 5512 Expect(kube).To(ExitWithError(125, "rootlessport cannot expose privileged port 80,")) 5513 // The ugly format-error exited once in Podman. The test makes 5514 // sure it's not coming back. 5515 Expect(kube.ErrorToString()).To(Not(ContainSubstring("Error: %!s(<nil>)"))) 5516 }) 5517 5518 It("invalid yaml should clean up pod that was created before failure", func() { 5519 podTemplate := `--- 5520 apiVersion: v1 5521 kind: Pod 5522 metadata: 5523 creationTimestamp: "2022-08-02T04:05:53Z" 5524 labels: 5525 app: vol-test-3-pod 5526 name: vol-test-3 5527 spec: 5528 containers: 5529 - command: 5530 - sleep 5531 - "1000" 5532 image: non-existing-image 5533 name: vol-test-3 5534 ` 5535 5536 err = writeYaml(podTemplate, kubeYaml) 5537 Expect(err).ToNot(HaveOccurred()) 5538 5539 // the image is incorrect so the kube play will fail, but it will clean up the pod that was created for it before the failure happened 5540 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5541 kube.WaitWithDefaultTimeout() 5542 Expect(kube).To(ExitWithError(125, "multi doc yaml could not be split: yaml: line 5: found character that cannot start any token")) 5543 5544 ps := podmanTest.Podman([]string{"pod", "ps", "-q"}) 5545 ps.WaitWithDefaultTimeout() 5546 Expect(ps).Should(ExitCleanly()) 5547 Expect(ps.OutputToStringArray()).To(BeEmpty()) 5548 }) 5549 5550 It("with named volume subpaths", func() { 5551 SkipIfRemote("volume export does not exist on remote") 5552 volumeCreate := podmanTest.Podman([]string{"volume", "create", "testvol1"}) 5553 volumeCreate.WaitWithDefaultTimeout() 5554 Expect(volumeCreate).Should(ExitCleanly()) 5555 5556 session := podmanTest.Podman([]string{"run", "--volume", "testvol1:/data", CITEST_IMAGE, "sh", "-c", "mkdir -p /data/testing/onlythis && touch /data/testing/onlythis/123.txt && echo hi >> /data/testing/onlythis/123.txt"}) 5557 session.WaitWithDefaultTimeout() 5558 Expect(session).Should(ExitCleanly()) 5559 5560 tar := filepath.Join(podmanTest.TempDir, "out.tar") 5561 session = podmanTest.Podman([]string{"volume", "export", "--output", tar, "testvol1"}) 5562 session.WaitWithDefaultTimeout() 5563 Expect(session).Should(ExitCleanly()) 5564 5565 volumeCreate = podmanTest.Podman([]string{"volume", "create", "testvol"}) 5566 volumeCreate.WaitWithDefaultTimeout() 5567 Expect(volumeCreate).Should(ExitCleanly()) 5568 5569 volumeImp := podmanTest.Podman([]string{"volume", "import", "testvol", filepath.Join(podmanTest.TempDir, "out.tar")}) 5570 volumeImp.WaitWithDefaultTimeout() 5571 Expect(volumeImp).Should(ExitCleanly()) 5572 5573 err = writeYaml(subpathTestNamedVolume, kubeYaml) 5574 Expect(err).ToNot(HaveOccurred()) 5575 5576 playKube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5577 playKube.WaitWithDefaultTimeout() 5578 Expect(playKube).Should(ExitCleanly()) 5579 5580 exec := podmanTest.Podman([]string{"exec", "testpod-testctr", "cat", "/var/123.txt"}) 5581 exec.WaitWithDefaultTimeout() 5582 Expect(exec).Should(ExitCleanly()) 5583 Expect(exec.OutputToString()).Should(Equal("hi")) 5584 5585 teardown := podmanTest.Podman([]string{"kube", "down", "--force", kubeYaml}) 5586 teardown.WaitWithDefaultTimeout() 5587 Expect(teardown).Should(ExitCleanly()) 5588 Expect(teardown.OutputToString()).Should(ContainSubstring("testvol")) 5589 5590 // kube down --force should remove volumes 5591 // specified in the manifest but not externally 5592 // created volumes, testvol1 in this case 5593 checkVol := podmanTest.Podman([]string{"volume", "ls", "--format", "{{.Name}}"}) 5594 checkVol.WaitWithDefaultTimeout() 5595 Expect(checkVol).Should(ExitCleanly()) 5596 Expect(checkVol.OutputToString()).To(Equal("testvol1")) 5597 }) 5598 5599 It("with graceful shutdown", func() { 5600 5601 volumeCreate := podmanTest.Podman([]string{"volume", "create", "testvol"}) 5602 volumeCreate.WaitWithDefaultTimeout() 5603 Expect(volumeCreate).Should(ExitCleanly()) 5604 5605 err = writeYaml(signalTest, kubeYaml) 5606 Expect(err).ToNot(HaveOccurred()) 5607 5608 playKube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5609 playKube.WaitWithDefaultTimeout() 5610 Expect(playKube).Should(ExitCleanly()) 5611 5612 teardown := podmanTest.Podman([]string{"kube", "down", kubeYaml}) 5613 teardown.WaitWithDefaultTimeout() 5614 Expect(teardown).Should(ExitCleanly()) 5615 5616 session := podmanTest.Podman([]string{"run", "--volume", "testvol:/testvol", CITEST_IMAGE, "sh", "-c", "cat /testvol/termfile"}) 5617 session.WaitWithDefaultTimeout() 5618 Expect(session.OutputToString()).Should(ContainSubstring("TERMINATED")) 5619 }) 5620 5621 It("with hostPath subpaths", func() { 5622 if !Containerized() { 5623 Skip("something is wrong with file permissions in CI or in the yaml creation. cannot ls or cat the fs unless in a container") 5624 } 5625 5626 hostPathLocation := podmanTest.TempDir 5627 Expect(os.MkdirAll(filepath.Join(hostPathLocation, "testing", "onlythis"), 0755)).To(Succeed()) 5628 file, err := os.Create(filepath.Join(hostPathLocation, "testing", "onlythis", "123.txt")) 5629 Expect(err).ToNot(HaveOccurred()) 5630 5631 _, err = file.WriteString("hi") 5632 Expect(err).ToNot(HaveOccurred()) 5633 5634 err = file.Close() 5635 Expect(err).ToNot(HaveOccurred()) 5636 5637 pod := getPod(withPodName("testpod"), withCtr(getCtr(withImage(CITEST_IMAGE), withName("testctr"), withCmd([]string{"top"}), withVolumeMount("/var", "testing/onlythis", false))), withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation))) 5638 5639 err = generateKubeYaml("pod", pod, kubeYaml) 5640 Expect(err).To(Not(HaveOccurred())) 5641 playKube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5642 playKube.WaitWithDefaultTimeout() 5643 Expect(playKube).Should(ExitCleanly()) 5644 exec := podmanTest.Podman([]string{"exec", "testpod-testctr", "ls", "/var"}) 5645 exec.WaitWithDefaultTimeout() 5646 Expect(exec).Should(ExitCleanly()) 5647 Expect(exec.OutputToString()).Should(ContainSubstring("123.txt")) 5648 }) 5649 5650 It("with unsafe subpaths", func() { 5651 SkipIfRemote("volume export does not exist on remote") 5652 volumeCreate := podmanTest.Podman([]string{"volume", "create", "testvol1"}) 5653 volumeCreate.WaitWithDefaultTimeout() 5654 Expect(volumeCreate).Should(ExitCleanly()) 5655 5656 session := podmanTest.Podman([]string{"run", "--volume", "testvol1:/data", CITEST_IMAGE, "sh", "-c", "mkdir -p /data/testing && ln -s /etc /data/testing/onlythis"}) 5657 session.WaitWithDefaultTimeout() 5658 Expect(session).Should(ExitCleanly()) 5659 5660 tar := filepath.Join(podmanTest.TempDir, "out.tar") 5661 session = podmanTest.Podman([]string{"volume", "export", "--output", tar, "testvol1"}) 5662 session.WaitWithDefaultTimeout() 5663 Expect(session).Should(ExitCleanly()) 5664 5665 volumeCreate = podmanTest.Podman([]string{"volume", "create", "testvol"}) 5666 volumeCreate.WaitWithDefaultTimeout() 5667 Expect(volumeCreate).Should(ExitCleanly()) 5668 5669 volumeImp := podmanTest.Podman([]string{"volume", "import", "testvol", filepath.Join(podmanTest.TempDir, "out.tar")}) 5670 volumeImp.WaitWithDefaultTimeout() 5671 Expect(volumeImp).Should(ExitCleanly()) 5672 5673 err = writeYaml(subpathTestNamedVolume, kubeYaml) 5674 Expect(err).ToNot(HaveOccurred()) 5675 5676 playKube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5677 playKube.WaitWithDefaultTimeout() 5678 Expect(playKube).Should(ExitWithError(125, fmt.Sprintf(`subpath "testing/onlythis" is outside of the volume "%s/root/volumes/testvol/_data`, podmanTest.TempDir))) 5679 }) 5680 5681 It("with unsafe hostPath subpaths", func() { 5682 hostPathLocation := podmanTest.TempDir 5683 5684 Expect(os.MkdirAll(filepath.Join(hostPathLocation, "testing"), 0755)).To(Succeed()) 5685 Expect(os.Symlink("/", filepath.Join(hostPathLocation, "testing", "symlink"))).To(Succeed()) 5686 5687 pod := getPod(withPodName("testpod"), withCtr(getCtr(withImage(CITEST_IMAGE), withName("testctr"), withCmd([]string{"top"}), withVolumeMount("/foo", "testing/symlink", false))), withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation))) 5688 5689 err = generateKubeYaml("pod", pod, kubeYaml) 5690 Expect(err).To(Not(HaveOccurred())) 5691 5692 playKube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5693 playKube.WaitWithDefaultTimeout() 5694 Expect(playKube).Should(ExitWithError(125, fmt.Sprintf(`subpath "testing/symlink" is outside of the volume "%s"`, hostPathLocation))) 5695 }) 5696 5697 It("with configMap subpaths", func() { 5698 volumeName := "cmVol" 5699 cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar")) 5700 cmYaml, err := getKubeYaml("configmap", cm) 5701 Expect(err).ToNot(HaveOccurred()) 5702 volumeContents := []map[string]string{{ 5703 "key": "FOO", 5704 "path": "BAR", 5705 }} 5706 5707 ctr := getCtr(withPullPolicy("always"), withName("testctr"), withCmd([]string{"top"}), withVolumeMount("/etc/BAR", "BAR", false), withImage(CITEST_IMAGE)) 5708 pod := getPod(withPodName("testpod"), withVolume(getConfigMapVolume(volumeName, volumeContents, false, nil)), withCtr(ctr)) 5709 5710 podYaml, err := getKubeYaml("pod", pod) 5711 Expect(err).ToNot(HaveOccurred()) 5712 5713 yamls := []string{cmYaml, podYaml} 5714 err = generateMultiDocKubeYaml(yamls, kubeYaml) 5715 Expect(err).ToNot(HaveOccurred()) 5716 5717 out, _ := os.ReadFile(kubeYaml) 5718 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5719 kube.WaitWithDefaultTimeout() 5720 Expect(kube).Should(Exit(0), string(out)) 5721 5722 exec := podmanTest.Podman([]string{"exec", "testpod-testctr", "ls", "/etc/"}) 5723 exec.WaitWithDefaultTimeout() 5724 Expect(exec).Should(ExitCleanly()) 5725 Expect(exec.OutputToString()).ShouldNot(HaveLen(3)) 5726 Expect(exec.OutputToString()).Should(ContainSubstring("BAR")) 5727 // we want to check that we can mount a subpath but not replace the entire dir 5728 }) 5729 5730 It("without Ports - curl should fail", func() { 5731 err := writeYaml(publishPortsPodWithoutPorts, kubeYaml) 5732 Expect(err).ToNot(HaveOccurred()) 5733 5734 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5735 kube.WaitWithDefaultTimeout() 5736 Expect(kube).Should(ExitCleanly()) 5737 5738 curlTest := podmanTest.Podman([]string{"run", "--network", "host", NGINX_IMAGE, "curl", "-s", "localhost:19000"}) 5739 curlTest.WaitWithDefaultTimeout() 5740 Expect(curlTest).Should(ExitWithError(7, "")) 5741 }) 5742 5743 It("without Ports, publish in command line - curl should succeed", func() { 5744 err := writeYaml(publishPortsPodWithoutPorts, kubeYaml) 5745 Expect(err).ToNot(HaveOccurred()) 5746 5747 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19002:80", kubeYaml}) 5748 kube.WaitWithDefaultTimeout() 5749 Expect(kube).Should(ExitCleanly()) 5750 5751 testHTTPServer("19002", false, "podman rulez") 5752 }) 5753 5754 It("with privileged container ports - should fail", func() { 5755 SkipIfNotRootless("rootlessport can expose privileged port 80, no point in checking for failure") 5756 err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) 5757 Expect(err).ToNot(HaveOccurred()) 5758 5759 kube := podmanTest.Podman([]string{"kube", "play", "--publish-all=true", kubeYaml}) 5760 kube.WaitWithDefaultTimeout() 5761 Expect(kube).Should(ExitWithError(125, "rootlessport cannot expose privileged port 80")) 5762 }) 5763 5764 It("podman play kube should not publish containerPort by default", func() { 5765 err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) 5766 Expect(err).ToNot(HaveOccurred()) 5767 5768 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5769 kube.WaitWithDefaultTimeout() 5770 Expect(kube).Should(Exit(0)) 5771 5772 testHTTPServer("80", true, "connection refused") 5773 }) 5774 5775 It("with privileged containers ports and publish in command line - curl should succeed", func() { 5776 err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) 5777 Expect(err).ToNot(HaveOccurred()) 5778 5779 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19003:80", kubeYaml}) 5780 kube.WaitWithDefaultTimeout() 5781 Expect(kube).Should(ExitCleanly()) 5782 5783 testHTTPServer("19003", false, "podman rulez") 5784 }) 5785 5786 It("podman play kube should publish containerPort with --publish-all", func() { 5787 SkipIfRootless("rootlessport can't expose privileged port 80") 5788 err := writeYaml(publishPortsPodWithContainerPort, kubeYaml) 5789 Expect(err).ToNot(HaveOccurred()) 5790 5791 kube := podmanTest.Podman([]string{"kube", "play", "--publish-all=true", kubeYaml}) 5792 kube.WaitWithDefaultTimeout() 5793 Expect(kube).Should(Exit(0)) 5794 5795 testHTTPServer("80", false, "podman rulez") 5796 }) 5797 5798 It("with Host Ports - curl should succeed", func() { 5799 err := writeYaml(publishPortsPodWithContainerHostPort, kubeYaml) 5800 Expect(err).ToNot(HaveOccurred()) 5801 5802 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19004:80", kubeYaml}) 5803 kube.WaitWithDefaultTimeout() 5804 Expect(kube).Should(ExitCleanly()) 5805 5806 testHTTPServer("19004", false, "podman rulez") 5807 }) 5808 5809 It("with Host Ports and publish in command line - curl should succeed only on overriding port", func() { 5810 err := writeYaml(publishPortsPodWithContainerHostPort, kubeYaml) 5811 Expect(err).ToNot(HaveOccurred()) 5812 5813 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19005:80", kubeYaml}) 5814 kube.WaitWithDefaultTimeout() 5815 Expect(kube).Should(ExitCleanly()) 5816 5817 testHTTPServer("19001", true, "connection refused") 5818 testHTTPServer("19005", false, "podman rulez") 5819 }) 5820 5821 It("multiple publish ports", func() { 5822 err := writeYaml(publishPortsPodWithoutPorts, kubeYaml) 5823 Expect(err).ToNot(HaveOccurred()) 5824 5825 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19006:80", "--publish", "19007:80", kubeYaml}) 5826 kube.WaitWithDefaultTimeout() 5827 Expect(kube).Should(ExitCleanly()) 5828 5829 testHTTPServer("19006", false, "podman rulez") 5830 testHTTPServer("19007", false, "podman rulez") 5831 }) 5832 5833 It("override with tcp should keep udp from YAML file", func() { 5834 err := writeYaml(publishPortsEchoWithHostPortUDP, kubeYaml) 5835 Expect(err).ToNot(HaveOccurred()) 5836 5837 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19010:19008/tcp", kubeYaml}) 5838 kube.WaitWithDefaultTimeout() 5839 Expect(kube).Should(ExitCleanly()) 5840 5841 verifyPodPorts(podmanTest, "network-echo", "19008/tcp:[{0.0.0.0 19010}]", "19008/udp:[{0.0.0.0 19009}]") 5842 }) 5843 5844 It("override with udp should keep tcp from YAML file", func() { 5845 err := writeYaml(publishPortsEchoWithHostPortTCP, kubeYaml) 5846 Expect(err).ToNot(HaveOccurred()) 5847 5848 kube := podmanTest.Podman([]string{"kube", "play", "--publish", "19012:19008/udp", kubeYaml}) 5849 kube.WaitWithDefaultTimeout() 5850 Expect(kube).Should(ExitCleanly()) 5851 5852 verifyPodPorts(podmanTest, "network-echo", "19008/tcp:[{0.0.0.0 19011}]", "19008/udp:[{0.0.0.0 19012}]") 5853 }) 5854 5855 It("with replicas limits the count to 1 and emits a warning", func() { 5856 deployment := getDeployment(withReplicas(10)) 5857 err := generateKubeYaml("deployment", deployment, kubeYaml) 5858 Expect(err).ToNot(HaveOccurred()) 5859 5860 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5861 kube.WaitWithDefaultTimeout() 5862 Expect(kube).Should(Exit(0)) 5863 5864 // warnings are only propagated to local clients 5865 if !IsRemote() { 5866 Expect(kube.ErrorToString()).Should(ContainSubstring("Limiting replica count to 1, more than one replica is not supported by Podman")) 5867 } 5868 5869 Expect(strings.Count(kube.OutputToString(), "Pod:")).To(Equal(1)) 5870 Expect(strings.Count(kube.OutputToString(), "Container:")).To(Equal(1)) 5871 }) 5872 5873 It("test with hostPID", func() { 5874 err := writeYaml(podWithHostPIDDefined, kubeYaml) 5875 Expect(err).ToNot(HaveOccurred()) 5876 5877 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5878 kube.WaitWithDefaultTimeout() 5879 Expect(kube).Should(ExitCleanly()) 5880 5881 logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-hostpid-testimage", "test-hostpid"}) 5882 logs.WaitWithDefaultTimeout() 5883 Expect(logs).Should(ExitCleanly()) 5884 Expect(logs.OutputToString()).To(Not(Equal("1")), "PID should never be 1 because of host pidns") 5885 5886 inspect := podmanTest.Podman([]string{"inspect", "test-hostpid-testimage", "--format", "{{ .HostConfig.PidMode }}"}) 5887 inspect.WaitWithDefaultTimeout() 5888 Expect(inspect).Should(ExitCleanly()) 5889 Expect(inspect.OutputToString()).To(Equal("host")) 5890 }) 5891 5892 It("test with hostIPC", func() { 5893 err := writeYaml(podWithHostIPCDefined, kubeYaml) 5894 Expect(err).ToNot(HaveOccurred()) 5895 5896 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5897 kube.WaitWithDefaultTimeout() 5898 Expect(kube).Should(ExitCleanly()) 5899 5900 wait := podmanTest.Podman([]string{"wait", "test-hostipc-testimage"}) 5901 wait.WaitWithDefaultTimeout() 5902 Expect(wait).Should(ExitCleanly()) 5903 5904 inspect := podmanTest.Podman([]string{"inspect", "test-hostipc-testimage", "--format", "{{ .HostConfig.IpcMode }}"}) 5905 inspect.WaitWithDefaultTimeout() 5906 Expect(inspect).Should(ExitCleanly()) 5907 Expect(inspect.OutputToString()).To(Equal("host")) 5908 5909 cmd := exec.Command("ls", "-l", "/proc/self/ns/ipc") 5910 res, err := cmd.Output() 5911 Expect(err).ToNot(HaveOccurred()) 5912 fields := strings.Split(string(res), " ") 5913 hostIpcNS := strings.TrimSuffix(fields[len(fields)-1], "\n") 5914 5915 logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-hostipc-testimage", "test-hostipc"}) 5916 logs.WaitWithDefaultTimeout() 5917 Expect(logs).Should(ExitCleanly()) 5918 fields = strings.Split(logs.OutputToString(), " ") 5919 ctrIpcNS := strings.TrimSuffix(fields[len(fields)-1], "\n") 5920 5921 Expect(ctrIpcNS).To(Equal(hostIpcNS), "container IPC NS == host IPC NS") 5922 }) 5923 5924 It("with ctrName should be in network alias", func() { 5925 ctrName := "test-ctr" 5926 ctrNameInKubePod := ctrName + "-pod-" + ctrName 5927 session1 := podmanTest.Podman([]string{"run", "-d", "--name", ctrName, CITEST_IMAGE, "top"}) 5928 session1.WaitWithDefaultTimeout() 5929 Expect(session1).Should(ExitCleanly()) 5930 5931 outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml") 5932 kube := podmanTest.Podman([]string{"kube", "generate", ctrName, "-f", outputFile}) 5933 kube.WaitWithDefaultTimeout() 5934 Expect(kube).Should(ExitCleanly()) 5935 5936 rm := podmanTest.Podman([]string{"pod", "rm", "-t", "0", "-f", ctrName}) 5937 rm.WaitWithDefaultTimeout() 5938 Expect(rm).Should(ExitCleanly()) 5939 5940 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 5941 play.WaitWithDefaultTimeout() 5942 Expect(play).Should(ExitCleanly()) 5943 5944 inspect := podmanTest.Podman([]string{"inspect", ctrNameInKubePod}) 5945 inspect.WaitWithDefaultTimeout() 5946 Expect(inspect).Should(ExitCleanly()) 5947 Expect(inspect.OutputToString()).To(ContainSubstring("\"Aliases\": [ \"" + ctrName + "\"")) 5948 }) 5949 5950 It("test with sysctl defined", func() { 5951 SkipIfRootless("Network sysctls are not available for rootless") 5952 err := writeYaml(podWithSysctlDefined, kubeYaml) 5953 Expect(err).ToNot(HaveOccurred()) 5954 5955 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5956 kube.WaitWithDefaultTimeout() 5957 Expect(kube).Should(ExitCleanly()) 5958 5959 wait := podmanTest.Podman([]string{"wait", "test-sysctl-testimage"}) 5960 wait.WaitWithDefaultTimeout() 5961 Expect(wait).Should(ExitCleanly()) 5962 5963 logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-sysctl-testimage", "test-sysctl"}) 5964 logs.WaitWithDefaultTimeout() 5965 Expect(logs).Should(ExitCleanly()) 5966 Expect(logs.OutputToString()).To(ContainSubstring("kernel.msgmax = 65535")) 5967 Expect(logs.OutputToString()).To(ContainSubstring("net.core.somaxconn = 65535")) 5968 }) 5969 5970 It("test with sysctl & host network defined", func() { 5971 SkipIfRootless("Network sysctls are not available for rootless") 5972 err := writeYaml(podWithSysctlHostNetDefined, kubeYaml) 5973 Expect(err).ToNot(HaveOccurred()) 5974 5975 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5976 kube.WaitWithDefaultTimeout() 5977 Expect(kube).Should(ExitWithError(125, "since Network Namespace set to host: invalid argument")) 5978 }) 5979 5980 It("test with annotation size beyond limits", func() { 5981 key := "name" 5982 val := RandomString(define.TotalAnnotationSizeLimitB - len(key) + 1) 5983 pod := getPod(withAnnotation(key, val)) 5984 err := generateKubeYaml("pod", pod, kubeYaml) 5985 Expect(err).ToNot(HaveOccurred()) 5986 5987 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 5988 kube.WaitWithDefaultTimeout() 5989 Expect(kube).Should(ExitWithError(125, "annotations size "+strconv.Itoa(len(key+val))+" is larger than limit "+strconv.Itoa(define.TotalAnnotationSizeLimitB))) 5990 }) 5991 5992 It("test with annotation size within limits", func() { 5993 key := "name" 5994 val := RandomString(define.TotalAnnotationSizeLimitB - len(key)) 5995 pod := getPod(withAnnotation(key, val)) 5996 err := generateKubeYaml("pod", pod, kubeYaml) 5997 Expect(err).ToNot(HaveOccurred()) 5998 5999 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 6000 kube.WaitWithDefaultTimeout() 6001 Expect(kube).Should(ExitCleanly()) 6002 }) 6003 6004 It("test pod with volumes-from annotation in yaml", func() { 6005 ctr1 := "ctr1" 6006 ctr2 := "ctr2" 6007 ctrNameInKubePod := ctr2 + "-pod-" + ctr2 6008 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6009 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 6010 6011 err := os.MkdirAll(vol1, 0755) 6012 Expect(err).ToNot(HaveOccurred()) 6013 6014 session := podmanTest.Podman([]string{"create", "--name", ctr1, "-v", vol1, CITEST_IMAGE}) 6015 session.WaitWithDefaultTimeout() 6016 Expect(session).Should(ExitCleanly()) 6017 6018 session = podmanTest.Podman([]string{"create", "--volumes-from", ctr1, "--name", ctr2, CITEST_IMAGE}) 6019 session.WaitWithDefaultTimeout() 6020 Expect(session).Should(ExitCleanly()) 6021 6022 kube := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, ctr2}) 6023 kube.WaitWithDefaultTimeout() 6024 Expect(kube).Should(ExitCleanly()) 6025 6026 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6027 play.WaitWithDefaultTimeout() 6028 Expect(play).Should(ExitCleanly()) 6029 6030 inspectCtr2 := podmanTest.Podman([]string{"inspect", "-f", "'{{ .HostConfig.Binds }}'", ctrNameInKubePod}) 6031 inspectCtr2.WaitWithDefaultTimeout() 6032 Expect(inspectCtr2).Should(ExitCleanly()) 6033 Expect(inspectCtr2.OutputToString()).To(ContainSubstring(":" + vol1 + ":rw")) 6034 6035 inspectCtr1 := podmanTest.Podman([]string{"inspect", "-f", "'{{ .HostConfig.Binds }}'", ctr1}) 6036 inspectCtr1.WaitWithDefaultTimeout() 6037 Expect(inspectCtr1).Should(ExitCleanly()) 6038 6039 Expect(inspectCtr2.OutputToString()).To(Equal(inspectCtr1.OutputToString())) 6040 6041 // see https://github.com/containers/podman/pull/19637, we should not see any warning/errors here 6042 podrm := podmanTest.Podman([]string{"kube", "down", outputFile}) 6043 podrm.WaitWithDefaultTimeout() 6044 Expect(podrm).Should(ExitCleanly()) 6045 }) 6046 6047 It("test volumes-from annotation with source containers external", func() { 6048 // Assert that volumes of multiple source containers, listed in 6049 // volumes-from annotation, running outside the pod are 6050 // getting mounted inside the target container. 6051 6052 srcctr1, srcctr2, tgtctr := "srcctr1", "srcctr2", "tgtctr" 6053 frmopt1, frmopt2 := srcctr1+":ro", srcctr2+":ro" 6054 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 6055 vol2 := filepath.Join(podmanTest.TempDir, "vol-test2") 6056 6057 volsFromAnnotaton := define.VolumesFromAnnotation + "/" + tgtctr 6058 volsFromValue := frmopt1 + ";" + frmopt2 6059 6060 err1 := os.MkdirAll(vol1, 0755) 6061 Expect(err1).ToNot(HaveOccurred()) 6062 6063 err2 := os.MkdirAll(vol2, 0755) 6064 Expect(err2).ToNot(HaveOccurred()) 6065 6066 session := podmanTest.Podman([]string{"create", "--name", srcctr1, "-v", vol1, CITEST_IMAGE}) 6067 session.WaitWithDefaultTimeout() 6068 Expect(session).Should(ExitCleanly()) 6069 6070 session = podmanTest.Podman([]string{"create", "--name", srcctr2, "-v", vol2, CITEST_IMAGE}) 6071 session.WaitWithDefaultTimeout() 6072 Expect(session).Should(ExitCleanly()) 6073 6074 podName := tgtctr 6075 pod := getPod( 6076 withPodName(podName), 6077 withCtr(getCtr(withName(tgtctr))), 6078 withAnnotation(volsFromAnnotaton, volsFromValue)) 6079 6080 err3 := generateKubeYaml("pod", pod, kubeYaml) 6081 Expect(err3).ToNot(HaveOccurred()) 6082 6083 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 6084 kube.WaitWithDefaultTimeout() 6085 Expect(kube).Should(ExitCleanly()) 6086 6087 // Assert volumes are accessible inside the target container 6088 ctrNameInKubePod := podName + "-" + tgtctr 6089 6090 inspect := podmanTest.InspectContainer(ctrNameInKubePod) 6091 Expect(inspect).To(HaveLen(1)) 6092 6093 exec := podmanTest.Podman([]string{"exec", ctrNameInKubePod, "ls", "-d", vol1, vol2}) 6094 exec.WaitWithDefaultTimeout() 6095 Expect(exec).Should(ExitCleanly()) 6096 Expect(exec.OutputToString()).To(ContainSubstring(vol1)) 6097 Expect(exec.OutputToString()).To(ContainSubstring(vol2)) 6098 }) 6099 6100 It("test volumes-from annotation with source container in pod", func() { 6101 // Assert that volume of source container, member of the pod, 6102 // listed in volumes-from annotation is getting mounted inside 6103 // the target container. 6104 6105 srcctr, tgtctr, podName := "srcctr", "tgtctr", "volspod" 6106 vol := "/mnt/vol" 6107 6108 srcctrInKubePod := podName + "-" + srcctr 6109 tgtctrInKubePod := podName + "-" + tgtctr 6110 6111 err := writeYaml(volumesFromPodYaml, kubeYaml) 6112 Expect(err).ToNot(HaveOccurred()) 6113 6114 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 6115 kube.WaitWithDefaultTimeout() 6116 Expect(kube).Should(ExitCleanly()) 6117 6118 inspect := podmanTest.InspectContainer(tgtctrInKubePod) 6119 Expect(inspect).To(HaveLen(1)) 6120 6121 // Assert volume is accessible inside the target container 6122 // by creating contents in the volume and accessing that from 6123 // the target container. 6124 volFile := filepath.Join(vol, RandomString(10)+".txt") 6125 6126 exec := podmanTest.Podman([]string{"exec", srcctrInKubePod, "touch", volFile}) 6127 exec.WaitWithDefaultTimeout() 6128 Expect(exec).Should(ExitCleanly()) 6129 6130 exec = podmanTest.Podman([]string{"exec", srcctrInKubePod, "ls", volFile}) 6131 exec.WaitWithDefaultTimeout() 6132 Expect(exec).Should(ExitCleanly()) 6133 Expect(exec.OutputToString()).To(ContainSubstring(volFile)) 6134 6135 exec = podmanTest.Podman([]string{"exec", tgtctrInKubePod, "ls", volFile}) 6136 exec.WaitWithDefaultTimeout() 6137 Expect(exec).Should(ExitCleanly()) 6138 Expect(exec.OutputToString()).To(ContainSubstring(volFile)) 6139 }) 6140 6141 It("test with reserved volumes-from annotation in yaml", func() { 6142 // Assert that volumes-from annotation without target container 6143 // errors out. 6144 6145 pod := getPod(withAnnotation(define.VolumesFromAnnotation, "reserved")) 6146 err := generateKubeYaml("pod", pod, kubeYaml) 6147 Expect(err).ToNot(HaveOccurred()) 6148 6149 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 6150 kube.WaitWithDefaultTimeout() 6151 Expect(kube).Should(ExitWithError(125, "annotation "+define.VolumesFromAnnotation+" without target volume is reserved for internal use")) 6152 }) 6153 6154 It("test with reserved autoremove annotation in yaml", func() { 6155 ctr := "ctr" 6156 ctrNameInKubePod := ctr + "-pod-" + ctr 6157 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6158 6159 session := podmanTest.Podman([]string{"create", "--rm", "--name", ctr, CITEST_IMAGE}) 6160 session.WaitWithDefaultTimeout() 6161 Expect(session).Should(ExitCleanly()) 6162 6163 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6164 kube.WaitWithDefaultTimeout() 6165 Expect(kube).Should(ExitCleanly()) 6166 6167 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6168 play.WaitWithDefaultTimeout() 6169 Expect(play).Should(ExitCleanly()) 6170 6171 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.AutoRemove }}", ctrNameInKubePod}) 6172 session.WaitWithDefaultTimeout() 6173 Expect(session).Should(ExitCleanly()) 6174 Expect(session.OutputToString()).To(Equal("true")) 6175 }) 6176 6177 It("test with reserved privileged annotation in yaml", func() { 6178 ctr := "ctr" 6179 ctrNameInKubePod := ctr + "-pod-" + ctr 6180 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6181 6182 session := podmanTest.Podman([]string{"create", "--privileged", "--name", ctr, CITEST_IMAGE}) 6183 session.WaitWithDefaultTimeout() 6184 Expect(session).Should(ExitCleanly()) 6185 6186 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6187 kube.WaitWithDefaultTimeout() 6188 Expect(kube).Should(ExitCleanly()) 6189 6190 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6191 play.WaitWithDefaultTimeout() 6192 Expect(play).Should(ExitCleanly()) 6193 6194 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.Privileged }}", ctrNameInKubePod}) 6195 session.WaitWithDefaultTimeout() 6196 Expect(session).Should(ExitCleanly()) 6197 Expect(session.OutputToString()).To(Equal("true")) 6198 }) 6199 6200 It("test with reserved init annotation in yaml", func() { 6201 ctr := "ctr" 6202 ctrNameInKubePod := ctr + "-pod-" + ctr 6203 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6204 6205 session := podmanTest.Podman([]string{"create", "--init", "--name", ctr, CITEST_IMAGE}) 6206 session.WaitWithDefaultTimeout() 6207 Expect(session).Should(ExitCleanly()) 6208 6209 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6210 kube.WaitWithDefaultTimeout() 6211 Expect(kube).Should(ExitCleanly()) 6212 6213 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6214 play.WaitWithDefaultTimeout() 6215 Expect(play).Should(ExitCleanly()) 6216 6217 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .Path }}", ctrNameInKubePod}) 6218 session.WaitWithDefaultTimeout() 6219 Expect(session).Should(ExitCleanly()) 6220 Expect(session.OutputToString()).To(Equal("/run/podman-init")) 6221 }) 6222 6223 It("test with reserved CIDFile annotation in yaml", func() { 6224 ctr := "ctr" 6225 ctrNameInKubePod := ctr + "-pod-" + ctr 6226 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6227 cidFile := filepath.Join(podmanTest.TempDir, RandomString(10)+".txt") 6228 6229 session := podmanTest.Podman([]string{"create", "--cidfile", cidFile, "--name", ctr, CITEST_IMAGE}) 6230 session.WaitWithDefaultTimeout() 6231 Expect(session).Should(ExitCleanly()) 6232 6233 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6234 kube.WaitWithDefaultTimeout() 6235 Expect(kube).Should(ExitCleanly()) 6236 6237 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6238 play.WaitWithDefaultTimeout() 6239 Expect(play).Should(ExitCleanly()) 6240 6241 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.ContainerIDFile }}", ctrNameInKubePod}) 6242 session.WaitWithDefaultTimeout() 6243 Expect(session).Should(ExitCleanly()) 6244 Expect(session.OutputToString()).To(Equal(cidFile)) 6245 6246 }) 6247 6248 It("test with reserved Seccomp annotation in yaml", func() { 6249 ctr := "ctr" 6250 ctrNameInKubePod := ctr + "-pod-" + ctr 6251 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6252 6253 session := podmanTest.Podman([]string{"create", "--security-opt", "seccomp=unconfined", "--name", ctr, CITEST_IMAGE}) 6254 session.WaitWithDefaultTimeout() 6255 Expect(session).Should(ExitCleanly()) 6256 6257 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6258 kube.WaitWithDefaultTimeout() 6259 Expect(kube).Should(ExitCleanly()) 6260 6261 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6262 play.WaitWithDefaultTimeout() 6263 Expect(play).Should(ExitCleanly()) 6264 6265 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.SecurityOpt }}", ctrNameInKubePod}) 6266 session.WaitWithDefaultTimeout() 6267 Expect(session).Should(ExitCleanly()) 6268 Expect(session.OutputToString()).To(Equal("[seccomp=unconfined]")) 6269 }) 6270 6271 It("test with reserved Apparmor annotation in yaml", func() { 6272 ctr := "ctr" 6273 ctrNameInKubePod := ctr + "-pod-" + ctr 6274 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6275 6276 session := podmanTest.Podman([]string{"create", "--security-opt", "apparmor=unconfined", "--name", ctr, CITEST_IMAGE}) 6277 session.WaitWithDefaultTimeout() 6278 Expect(session).Should(ExitCleanly()) 6279 6280 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6281 kube.WaitWithDefaultTimeout() 6282 Expect(kube).Should(ExitCleanly()) 6283 6284 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6285 play.WaitWithDefaultTimeout() 6286 Expect(play).Should(ExitCleanly()) 6287 6288 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.SecurityOpt }}", ctrNameInKubePod}) 6289 session.WaitWithDefaultTimeout() 6290 Expect(session).Should(ExitCleanly()) 6291 Expect(session.OutputToString()).To(Equal("[apparmor=unconfined]")) 6292 }) 6293 6294 It("test with reserved Label annotation in yaml", func() { 6295 ctr := "ctr" 6296 ctrNameInKubePod := ctr + "-pod-" + ctr 6297 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6298 6299 session := podmanTest.Podman([]string{"create", "--security-opt", "label=level:s0", "--name", ctr, CITEST_IMAGE}) 6300 session.WaitWithDefaultTimeout() 6301 Expect(session).Should(ExitCleanly()) 6302 6303 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6304 kube.WaitWithDefaultTimeout() 6305 Expect(kube).Should(ExitCleanly()) 6306 6307 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6308 play.WaitWithDefaultTimeout() 6309 Expect(play).Should(ExitCleanly()) 6310 6311 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.SecurityOpt }}", ctrNameInKubePod}) 6312 session.WaitWithDefaultTimeout() 6313 Expect(session).Should(ExitCleanly()) 6314 Expect(session.OutputToString()).To(Equal("[label=level:s0]")) 6315 }) 6316 6317 It("test with reserved PublishAll annotation in yaml", func() { 6318 podmanTest.AddImageToRWStore(CITEST_IMAGE) 6319 dockerfile := fmt.Sprintf(`FROM %s 6320 EXPOSE 2002 6321 EXPOSE 2001-2003 6322 EXPOSE 2004-2005/tcp`, CITEST_IMAGE) 6323 imageName := "testimg" 6324 podmanTest.BuildImage(dockerfile, imageName, "false") 6325 6326 // Verify that the buildah is just passing through the EXPOSE keys 6327 inspect := podmanTest.Podman([]string{"inspect", imageName}) 6328 inspect.WaitWithDefaultTimeout() 6329 image := inspect.InspectImageJSON() 6330 Expect(image).To(HaveLen(1)) 6331 Expect(image[0].Config.ExposedPorts).To(HaveLen(3)) 6332 Expect(image[0].Config.ExposedPorts).To(HaveKey("2002/tcp")) 6333 Expect(image[0].Config.ExposedPorts).To(HaveKey("2001-2003/tcp")) 6334 Expect(image[0].Config.ExposedPorts).To(HaveKey("2004-2005/tcp")) 6335 6336 ctr := "ctr" 6337 ctrNameInKubePod := ctr + "-pod-" + ctr 6338 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6339 6340 session := podmanTest.Podman([]string{"create", "--publish-all", "--name", ctr, imageName, "true"}) 6341 session.WaitWithDefaultTimeout() 6342 Expect(session).Should(ExitCleanly()) 6343 6344 kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) 6345 kube.WaitWithDefaultTimeout() 6346 Expect(kube).Should(ExitCleanly()) 6347 6348 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6349 play.WaitWithDefaultTimeout() 6350 Expect(play).Should(ExitCleanly()) 6351 6352 session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.PublishAllPorts }}", ctrNameInKubePod}) 6353 session.WaitWithDefaultTimeout() 6354 Expect(session).Should(ExitCleanly()) 6355 Expect(session.OutputToString()).To(Equal("true")) 6356 }) 6357 6358 It("test with valid Umask value", func() { 6359 defaultUmask := "0022" 6360 ctrName := "ctr" 6361 ctrNameInPod := "ctr-pod-ctr" 6362 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6363 6364 create := podmanTest.Podman([]string{"create", "-t", "--restart", "never", "--name", ctrName, CITEST_IMAGE, "top"}) 6365 create.WaitWithDefaultTimeout() 6366 Expect(create).Should(ExitCleanly()) 6367 6368 generate := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, ctrName}) 6369 generate.WaitWithDefaultTimeout() 6370 Expect(generate).Should(ExitCleanly()) 6371 6372 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6373 play.WaitWithDefaultTimeout() 6374 Expect(play).Should(ExitCleanly()) 6375 6376 exec := podmanTest.Podman([]string{"exec", ctrNameInPod, "/bin/sh", "-c", "umask"}) 6377 exec.WaitWithDefaultTimeout() 6378 Expect(exec).Should(ExitCleanly()) 6379 Expect(exec.OutputToString()).To(Equal(defaultUmask)) 6380 6381 inspect := podmanTest.Podman([]string{"inspect", ctrNameInPod, "-f", "{{ .Config.Umask }}"}) 6382 inspect.WaitWithDefaultTimeout() 6383 Expect(inspect).Should(ExitCleanly()) 6384 Expect(inspect.OutputToString()).To(Equal(defaultUmask)) 6385 }) 6386 6387 // podman play with infra name annotation 6388 It("test with infra name annotation set", func() { 6389 infraName := "infra-ctr" 6390 podName := "mypod" 6391 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6392 pod := podmanTest.Podman([]string{"pod", "create", "--infra-name", infraName, podName}) 6393 pod.WaitWithDefaultTimeout() 6394 Expect(pod).Should(ExitCleanly()) 6395 6396 ctr := podmanTest.Podman([]string{"create", "--pod", podName, CITEST_IMAGE, "top"}) 6397 ctr.WaitWithDefaultTimeout() 6398 Expect(ctr).Should(ExitCleanly()) 6399 6400 // Generate kube yaml and it should have the infra name annotation set 6401 gen := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, podName}) 6402 gen.WaitWithDefaultTimeout() 6403 Expect(gen).Should(ExitCleanly()) 6404 // Remove the pod so it can be recreated via kube play 6405 rm := podmanTest.Podman([]string{"pod", "rm", "-f", podName}) 6406 rm.WaitWithDefaultTimeout() 6407 Expect(rm).Should(ExitCleanly()) 6408 6409 kube := podmanTest.Podman([]string{"kube", "play", outputFile}) 6410 kube.WaitWithDefaultTimeout() 6411 Expect(kube).Should(ExitCleanly()) 6412 6413 // Expect the number of containers created to be 2, infra, and regular container 6414 numOfCtrs := podmanTest.NumberOfContainers() 6415 Expect(numOfCtrs).To(Equal(2)) 6416 6417 ps := podmanTest.Podman([]string{"ps", "--format", "{{.Names}}"}) 6418 ps.WaitWithDefaultTimeout() 6419 Expect(ps).Should(ExitCleanly()) 6420 Expect(ps.OutputToString()).To(ContainSubstring(infraName)) 6421 }) 6422 6423 // podman play with default infra name 6424 It("test with default infra name", func() { 6425 podName := "mypod" 6426 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6427 pod := podmanTest.Podman([]string{"pod", "create", podName}) 6428 pod.WaitWithDefaultTimeout() 6429 Expect(pod).Should(ExitCleanly()) 6430 6431 ctr := podmanTest.Podman([]string{"create", "--pod", podName, CITEST_IMAGE, "top"}) 6432 ctr.WaitWithDefaultTimeout() 6433 Expect(ctr).Should(ExitCleanly()) 6434 6435 // Generate kube yaml and it should have the infra name annotation set 6436 gen := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, podName}) 6437 gen.WaitWithDefaultTimeout() 6438 Expect(gen).Should(ExitCleanly()) 6439 // Remove the pod so it can be recreated via kube play 6440 rm := podmanTest.Podman([]string{"pod", "rm", "-f", podName}) 6441 rm.WaitWithDefaultTimeout() 6442 Expect(rm).Should(ExitCleanly()) 6443 6444 kube := podmanTest.Podman([]string{"kube", "play", outputFile}) 6445 kube.WaitWithDefaultTimeout() 6446 Expect(kube).Should(ExitCleanly()) 6447 6448 // Expect the number of containers created to be 2, infra, and regular container 6449 numOfCtrs := podmanTest.NumberOfContainers() 6450 Expect(numOfCtrs).To(Equal(2)) 6451 6452 podPs := podmanTest.Podman([]string{"pod", "ps", "-q"}) 6453 podPs.WaitWithDefaultTimeout() 6454 Expect(podPs).Should(ExitCleanly()) 6455 podID := podPs.OutputToString() 6456 6457 ps := podmanTest.Podman([]string{"ps", "--format", "{{.Names}}"}) 6458 ps.WaitWithDefaultTimeout() 6459 Expect(ps).Should(ExitCleanly()) 6460 Expect(ps.OutputToString()).To(ContainSubstring(podID[:12] + "-infra")) 6461 }) 6462 6463 It("support List kind", func() { 6464 listYamlPathname := filepath.Join(podmanTest.TempDir, "list.yaml") 6465 err = writeYaml(listPodAndConfigMap, listYamlPathname) 6466 Expect(err).ToNot(HaveOccurred()) 6467 6468 kube := podmanTest.Podman([]string{"kube", "play", listYamlPathname}) 6469 kube.WaitWithDefaultTimeout() 6470 Expect(kube).Should(ExitCleanly()) 6471 6472 inspect := podmanTest.Podman([]string{"inspect", "test-list-pod-container", "--format", "'{{ .Config.Env }}'"}) 6473 inspect.WaitWithDefaultTimeout() 6474 Expect(inspect).Should(ExitCleanly()) 6475 Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=bar`)) 6476 }) 6477 6478 It("with TerminationGracePeriodSeconds set", func() { 6479 ctrName := "ctr" 6480 ctrNameInPod := "ctr-pod-ctr" 6481 outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") 6482 6483 create := podmanTest.Podman([]string{"create", "--restart", "never", "--stop-timeout", "20", "--name", ctrName, CITEST_IMAGE}) 6484 create.WaitWithDefaultTimeout() 6485 Expect(create).Should(ExitCleanly()) 6486 6487 generate := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, ctrName}) 6488 generate.WaitWithDefaultTimeout() 6489 Expect(generate).Should(ExitCleanly()) 6490 6491 play := podmanTest.Podman([]string{"kube", "play", outputFile}) 6492 play.WaitWithDefaultTimeout() 6493 Expect(play).Should(ExitCleanly()) 6494 6495 inspect := podmanTest.Podman([]string{"inspect", ctrNameInPod, "-f", "{{ .Config.StopTimeout }}"}) 6496 inspect.WaitWithDefaultTimeout() 6497 Expect(inspect).Should(ExitCleanly()) 6498 Expect(inspect.OutputToString()).To(Equal("20")) 6499 }) 6500 6501 It("hostname should be node name when hostNetwork=true", func() { 6502 netYaml := ` 6503 apiVersion: v1 6504 kind: Pod 6505 metadata: 6506 name: test-pod 6507 spec: 6508 hostNetwork: true 6509 hostname: blah 6510 containers: 6511 - name: alpine 6512 image: alpine 6513 command: 6514 - sleep 6515 - "100" 6516 ` 6517 6518 err := writeYaml(netYaml, kubeYaml) 6519 Expect(err).ToNot(HaveOccurred()) 6520 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 6521 kube.WaitWithDefaultTimeout() 6522 Expect(kube).Should(ExitCleanly()) 6523 6524 // Get the name of the host 6525 hostname, err := os.Hostname() 6526 Expect(err).ToNot(HaveOccurred()) 6527 6528 exec := podmanTest.Podman([]string{"exec", "test-pod-alpine", "hostname"}) 6529 exec.WaitWithDefaultTimeout() 6530 Expect(exec).Should(ExitCleanly()) 6531 Expect(exec.OutputToString()).To(Equal(hostname)) 6532 6533 // Check that the UTS namespace is set to host also 6534 hostUts := SystemExec("ls", []string{"-l", "/proc/self/ns/uts"}) 6535 Expect(hostUts).Should(ExitCleanly()) 6536 arr := strings.Split(hostUts.OutputToString(), " ") 6537 exec = podmanTest.Podman([]string{"exec", "test-pod-alpine", "ls", "-l", "/proc/self/ns/uts"}) 6538 exec.WaitWithDefaultTimeout() 6539 Expect(exec).Should(ExitCleanly()) 6540 execArr := strings.Split(exec.OutputToString(), " ") 6541 Expect(execArr[len(execArr)-1]).To(ContainSubstring(arr[len(arr)-1])) 6542 }) 6543 6544 It("hostname should be pod name when hostNetwork=false", func() { 6545 netYaml := ` 6546 apiVersion: v1 6547 kind: Pod 6548 metadata: 6549 name: test-pod 6550 spec: 6551 containers: 6552 - name: alpine 6553 image: alpine 6554 command: 6555 - sleep 6556 - "100" 6557 ` 6558 6559 err := writeYaml(netYaml, kubeYaml) 6560 Expect(err).ToNot(HaveOccurred()) 6561 kube := podmanTest.Podman([]string{"kube", "play", kubeYaml}) 6562 kube.WaitWithDefaultTimeout() 6563 Expect(kube).Should(ExitCleanly()) 6564 6565 exec := podmanTest.Podman([]string{"exec", "test-pod-alpine", "hostname"}) 6566 exec.WaitWithDefaultTimeout() 6567 Expect(exec).Should(ExitCleanly()) 6568 Expect(exec.OutputToString()).To(Equal("test-pod")) 6569 6570 // Check that the UTS namespace is set to host also 6571 hostUts := SystemExec("ls", []string{"-l", "/proc/self/ns/uts"}) 6572 Expect(hostUts).Should(ExitCleanly()) 6573 arr := strings.Split(hostUts.OutputToString(), " ") 6574 exec = podmanTest.Podman([]string{"exec", "test-pod-alpine", "ls", "-l", "/proc/self/ns/uts"}) 6575 exec.WaitWithDefaultTimeout() 6576 Expect(exec).Should(ExitCleanly()) 6577 execArr := strings.Split(exec.OutputToString(), " ") 6578 Expect(execArr[len(execArr)-1]).To(Not(ContainSubstring(arr[len(arr)-1]))) 6579 }) 6580 6581 })