github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/play_kube_test.go (about)

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