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  })