github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/test/e2e/play_kube_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  	"text/template"
    12  
    13  	. "github.com/containers/podman/v2/test/utils"
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  )
    17  
    18  var unknownKindYaml = `
    19  apiVerson: v1
    20  kind: UnknownKind
    21  metadata:
    22    labels:
    23      app: app1
    24    name: unknown
    25  spec:
    26    hostname: unknown
    27  `
    28  
    29  var configMapYamlTemplate = `
    30  apiVersion: v1
    31  kind: ConfigMap
    32  metadata:
    33    name: {{ .Name }}
    34  data:
    35  {{ with .Data }}
    36    {{ range $key, $value := . }}
    37      {{ $key }}: {{ $value }}
    38    {{ end }}
    39  {{ end }}
    40  `
    41  
    42  var podYamlTemplate = `
    43  apiVersion: v1
    44  kind: Pod
    45  metadata:
    46    creationTimestamp: "2019-07-17T14:44:08Z"
    47    name: {{ .Name }}
    48    labels:
    49      app: {{ .Name }}
    50  {{ with .Labels }}
    51    {{ range $key, $value := . }}
    52      {{ $key }}: {{ $value }}
    53    {{ end }}
    54  {{ end }}
    55  {{ with .Annotations }}
    56    annotations:
    57    {{ range $key, $value := . }}
    58      {{ $key }}: {{ $value }}
    59    {{ end }}
    60  {{ end }}
    61  
    62  spec:
    63    restartPolicy: {{ .RestartPolicy }}
    64    hostname: {{ .Hostname }}
    65    hostAliases:
    66  {{ range .HostAliases }}
    67    - hostnames:
    68    {{ range .HostName }}
    69      - {{ . }}
    70    {{ end }}
    71      ip: {{ .IP }}
    72  {{ end }}
    73    containers:
    74  {{ with .Ctrs }}
    75    {{ range . }}
    76    - command:
    77      {{ range .Cmd }}
    78      - {{.}}
    79      {{ end }}
    80      args:
    81      {{ range .Arg }}
    82      - {{.}}
    83      {{ end }}
    84      env:
    85      - name: PATH
    86        value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    87      - name: TERM
    88        value: xterm
    89      - name: HOSTNAME
    90      - name: container
    91        value: podman
    92      {{ range .Env }}
    93      - name: {{ .Name }}
    94      {{ if (eq .ValueFrom "configmap") }}
    95        valueFrom:
    96          configMapKeyRef:
    97            name: {{ .RefName }}
    98            key: {{ .RefKey }}
    99      {{ else }}
   100        value: {{ .Value }}
   101      {{ end }}
   102      {{ end }}
   103      {{ with .EnvFrom}}
   104      envFrom:
   105      {{ range . }}
   106      {{ if (eq .From "configmap") }}
   107      - configMapRef:
   108          name: {{ .Name }}
   109      {{ end }}
   110      {{ end }}
   111      {{ end }}
   112      image: {{ .Image }}
   113      name: {{ .Name }}
   114      imagePullPolicy: {{ .PullPolicy }}
   115      {{- if or .CpuRequest .CpuLimit .MemoryRequest .MemoryLimit }}
   116      resources:
   117        {{- if or .CpuRequest .MemoryRequest }}
   118        requests:
   119          {{if .CpuRequest }}cpu: {{ .CpuRequest }}{{ end }}
   120          {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }}
   121        {{- end }}
   122        {{- if or .CpuLimit .MemoryLimit }}
   123        limits:
   124          {{if .CpuLimit }}cpu: {{ .CpuLimit }}{{ end }}
   125          {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }}
   126        {{- end }}
   127      {{- end }}
   128      {{ if .SecurityContext }}
   129      securityContext:
   130        allowPrivilegeEscalation: true
   131        {{ if .Caps }}
   132        capabilities:
   133          {{ with .CapAdd }}
   134          add:
   135            {{ range . }}
   136            - {{.}}
   137            {{ end }}
   138          {{ end }}
   139          {{ with .CapDrop }}
   140          drop:
   141            {{ range . }}
   142            - {{.}}
   143            {{ end }}
   144          {{ end }}
   145        {{ end }}
   146        privileged: false
   147        readOnlyRootFilesystem: false
   148      ports:
   149      - containerPort: {{ .Port }}
   150        hostIP: {{ .HostIP }}
   151        hostPort: {{ .Port }}
   152        protocol: TCP
   153      workingDir: /
   154      volumeMounts:
   155      {{ if .VolumeMount }}
   156      - name: {{.VolumeName}}
   157        mountPath: {{ .VolumeMountPath }}
   158        readonly: {{.VolumeReadOnly}}
   159        {{ end }}
   160      {{ end }}
   161    {{ end }}
   162  {{ end }}
   163  {{ with .Volumes }}
   164    volumes:
   165    {{ range . }}
   166    - name: {{ .Name }}
   167      {{- if (eq .VolumeType "HostPath") }}
   168      hostPath:
   169        path: {{ .HostPath.Path }}
   170        type: {{ .HostPath.Type }}
   171      {{- end }}
   172      {{- if (eq .VolumeType "PersistentVolumeClaim") }}
   173      persistentVolumeClaim:
   174        claimName: {{ .PersistentVolumeClaim.ClaimName }}
   175      {{- end }}
   176    {{ end }}
   177  {{ end }}
   178  status: {}
   179  `
   180  
   181  var deploymentYamlTemplate = `
   182  apiVersion: v1
   183  kind: Deployment
   184  metadata:
   185    creationTimestamp: "2019-07-17T14:44:08Z"
   186    name: {{ .Name }}
   187    labels:
   188      app: {{ .Name }}
   189  {{ with .Labels }}
   190    {{ range $key, $value := . }}
   191      {{ $key }}: {{ $value }}
   192    {{ end }}
   193  {{ end }}
   194  {{ with .Annotations }}
   195    annotations:
   196    {{ range $key, $value := . }}
   197      {{ $key }}: {{ $value }}
   198    {{ end }}
   199  {{ end }}
   200  
   201  spec:
   202    replicas: {{ .Replicas }}
   203    selector:
   204      matchLabels:
   205        app: {{ .Name }}
   206    template:
   207    {{ with .PodTemplate }}
   208      metadata:
   209        labels:
   210          app: {{ .Name }}
   211          {{- with .Labels }}{{ range $key, $value := . }}
   212          {{ $key }}: {{ $value }}
   213          {{- end }}{{ end }}
   214        {{- with .Annotations }}
   215        annotations:
   216        {{- range $key, $value := . }}
   217          {{ $key }}: {{ $value }}
   218        {{- end }}
   219        {{- end }}
   220      spec:
   221        restartPolicy: {{ .RestartPolicy }}
   222        hostname: {{ .Hostname }}
   223        containers:
   224      {{ with .Ctrs }}
   225        {{ range . }}
   226        - command:
   227          {{ range .Cmd }}
   228          - {{.}}
   229          {{ end }}
   230          args:
   231          {{ range .Arg }}
   232          - {{.}}
   233          {{ end }}
   234          env:
   235          - name: PATH
   236            value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
   237          - name: TERM
   238            value: xterm
   239          - name: HOSTNAME
   240          - name: container
   241            value: podman
   242          image: {{ .Image }}
   243          name: {{ .Name }}
   244          imagePullPolicy: {{ .PullPolicy }}
   245          {{- if or .CpuRequest .CpuLimit .MemoryRequest .MemoryLimit }}
   246          resources:
   247            {{- if or .CpuRequest .MemoryRequest }}
   248            requests:
   249              {{if .CpuRequest }}cpu: {{ .CpuRequest }}{{ end }}
   250              {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }}
   251            {{- end }}
   252            {{- if or .CpuLimit .MemoryLimit }}
   253            limits:
   254              {{if .CpuLimit }}cpu: {{ .CpuLimit }}{{ end }}
   255              {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }}
   256            {{- end }}
   257          {{- end }}
   258          {{ if .SecurityContext }}
   259          securityContext:
   260            allowPrivilegeEscalation: true
   261            {{ if .Caps }}
   262            capabilities:
   263              {{ with .CapAdd }}
   264              add:
   265                {{ range . }}
   266                - {{.}}
   267                {{ end }}
   268              {{ end }}
   269              {{ with .CapDrop }}
   270              drop:
   271                {{ range . }}
   272                - {{.}}
   273                {{ end }}
   274              {{ end }}
   275            {{ end }}
   276            privileged: false
   277            readOnlyRootFilesystem: false
   278          workingDir: /
   279          {{ end }}
   280        {{ end }}
   281      {{ end }}
   282    {{ end }}
   283  `
   284  
   285  var (
   286  	defaultCtrName        = "testCtr"
   287  	defaultCtrCmd         = []string{"top"}
   288  	defaultCtrArg         = []string{"-d", "1.5"}
   289  	defaultCtrImage       = ALPINE
   290  	defaultPodName        = "testPod"
   291  	defaultVolName        = "testVol"
   292  	defaultDeploymentName = "testDeployment"
   293  	defaultConfigMapName  = "testConfigMap"
   294  	seccompPwdEPERM       = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`)
   295  	// CPU Period in ms
   296  	defaultCPUPeriod = 100
   297  )
   298  
   299  func writeYaml(content string, fileName string) error {
   300  	f, err := os.Create(fileName)
   301  	if err != nil {
   302  		return err
   303  	}
   304  	defer f.Close()
   305  
   306  	_, err = f.WriteString(content)
   307  	if err != nil {
   308  		return err
   309  	}
   310  
   311  	return nil
   312  }
   313  
   314  func generateKubeYaml(kind string, object interface{}, pathname string) error {
   315  	var yamlTemplate string
   316  	templateBytes := &bytes.Buffer{}
   317  
   318  	switch kind {
   319  	case "configmap":
   320  		yamlTemplate = configMapYamlTemplate
   321  	case "pod":
   322  		yamlTemplate = podYamlTemplate
   323  	case "deployment":
   324  		yamlTemplate = deploymentYamlTemplate
   325  	default:
   326  		return fmt.Errorf("unsupported kubernetes kind")
   327  	}
   328  
   329  	t, err := template.New(kind).Parse(yamlTemplate)
   330  	if err != nil {
   331  		return err
   332  	}
   333  
   334  	if err := t.Execute(templateBytes, object); err != nil {
   335  		return err
   336  	}
   337  
   338  	return writeYaml(templateBytes.String(), pathname)
   339  }
   340  
   341  // ConfigMap describes the options a kube yaml can be configured at configmap level
   342  type ConfigMap struct {
   343  	Name string
   344  	Data map[string]string
   345  }
   346  
   347  func getConfigMap(options ...configMapOption) *ConfigMap {
   348  	cm := ConfigMap{
   349  		Name: defaultConfigMapName,
   350  		Data: map[string]string{},
   351  	}
   352  
   353  	for _, option := range options {
   354  		option(&cm)
   355  	}
   356  
   357  	return &cm
   358  }
   359  
   360  type configMapOption func(*ConfigMap)
   361  
   362  func withConfigMapName(name string) configMapOption {
   363  	return func(configmap *ConfigMap) {
   364  		configmap.Name = name
   365  	}
   366  }
   367  
   368  func withConfigMapData(k, v string) configMapOption {
   369  	return func(configmap *ConfigMap) {
   370  		configmap.Data[k] = v
   371  	}
   372  }
   373  
   374  // Pod describes the options a kube yaml can be configured at pod level
   375  type Pod struct {
   376  	Name          string
   377  	RestartPolicy string
   378  	Hostname      string
   379  	HostAliases   []HostAlias
   380  	Ctrs          []*Ctr
   381  	Volumes       []*Volume
   382  	Labels        map[string]string
   383  	Annotations   map[string]string
   384  }
   385  
   386  type HostAlias struct {
   387  	IP       string
   388  	HostName []string
   389  }
   390  
   391  // getPod takes a list of podOptions and returns a pod with sane defaults
   392  // and the configured options
   393  // if no containers are added, it will add the default container
   394  func getPod(options ...podOption) *Pod {
   395  	p := Pod{
   396  		Name:          defaultPodName,
   397  		RestartPolicy: "Never",
   398  		Hostname:      "",
   399  		HostAliases:   nil,
   400  		Ctrs:          make([]*Ctr, 0),
   401  		Volumes:       make([]*Volume, 0),
   402  		Labels:        make(map[string]string),
   403  		Annotations:   make(map[string]string),
   404  	}
   405  	for _, option := range options {
   406  		option(&p)
   407  	}
   408  	if len(p.Ctrs) == 0 {
   409  		p.Ctrs = []*Ctr{getCtr()}
   410  	}
   411  	return &p
   412  }
   413  
   414  type podOption func(*Pod)
   415  
   416  func withPodName(name string) podOption {
   417  	return func(pod *Pod) {
   418  		pod.Name = name
   419  	}
   420  }
   421  
   422  func withHostname(h string) podOption {
   423  	return func(pod *Pod) {
   424  		pod.Hostname = h
   425  	}
   426  }
   427  
   428  func withHostAliases(ip string, host []string) podOption {
   429  	return func(pod *Pod) {
   430  		pod.HostAliases = append(pod.HostAliases, HostAlias{
   431  			IP:       ip,
   432  			HostName: host,
   433  		})
   434  	}
   435  }
   436  
   437  func withCtr(c *Ctr) podOption {
   438  	return func(pod *Pod) {
   439  		pod.Ctrs = append(pod.Ctrs, c)
   440  	}
   441  }
   442  
   443  func withRestartPolicy(policy string) podOption {
   444  	return func(pod *Pod) {
   445  		pod.RestartPolicy = policy
   446  	}
   447  }
   448  
   449  func withLabel(k, v string) podOption {
   450  	return func(pod *Pod) {
   451  		pod.Labels[k] = v
   452  	}
   453  }
   454  
   455  func withAnnotation(k, v string) podOption {
   456  	return func(pod *Pod) {
   457  		pod.Annotations[k] = v
   458  	}
   459  }
   460  
   461  func withVolume(v *Volume) podOption {
   462  	return func(pod *Pod) {
   463  		pod.Volumes = append(pod.Volumes, v)
   464  	}
   465  }
   466  
   467  // Deployment describes the options a kube yaml can be configured at deployment level
   468  type Deployment struct {
   469  	Name        string
   470  	Replicas    int32
   471  	Labels      map[string]string
   472  	Annotations map[string]string
   473  	PodTemplate *Pod
   474  }
   475  
   476  func getDeployment(options ...deploymentOption) *Deployment {
   477  	d := Deployment{
   478  		Name:        defaultDeploymentName,
   479  		Replicas:    1,
   480  		Labels:      make(map[string]string),
   481  		Annotations: make(map[string]string),
   482  		PodTemplate: getPod(),
   483  	}
   484  	for _, option := range options {
   485  		option(&d)
   486  	}
   487  
   488  	return &d
   489  }
   490  
   491  type deploymentOption func(*Deployment)
   492  
   493  func withDeploymentLabel(k, v string) deploymentOption {
   494  	return func(deployment *Deployment) {
   495  		deployment.Labels[k] = v
   496  	}
   497  }
   498  
   499  func withDeploymentAnnotation(k, v string) deploymentOption {
   500  	return func(deployment *Deployment) {
   501  		deployment.Annotations[k] = v
   502  	}
   503  }
   504  
   505  func withPod(pod *Pod) deploymentOption {
   506  	return func(d *Deployment) {
   507  		d.PodTemplate = pod
   508  	}
   509  }
   510  
   511  func withReplicas(replicas int32) deploymentOption {
   512  	return func(d *Deployment) {
   513  		d.Replicas = replicas
   514  	}
   515  }
   516  
   517  // getPodNamesInDeployment returns list of Pod objects
   518  // with just their name set, so that it can be passed around
   519  // and into getCtrNameInPod for ease of testing
   520  func getPodNamesInDeployment(d *Deployment) []Pod {
   521  	var pods []Pod
   522  	var i int32
   523  
   524  	for i = 0; i < d.Replicas; i++ {
   525  		p := Pod{}
   526  		p.Name = fmt.Sprintf("%s-pod-%d", d.Name, i)
   527  		pods = append(pods, p)
   528  	}
   529  
   530  	return pods
   531  }
   532  
   533  // Ctr describes the options a kube yaml can be configured at container level
   534  type Ctr struct {
   535  	Name            string
   536  	Image           string
   537  	Cmd             []string
   538  	Arg             []string
   539  	CpuRequest      string
   540  	CpuLimit        string
   541  	MemoryRequest   string
   542  	MemoryLimit     string
   543  	SecurityContext bool
   544  	Caps            bool
   545  	CapAdd          []string
   546  	CapDrop         []string
   547  	PullPolicy      string
   548  	HostIP          string
   549  	Port            string
   550  	VolumeMount     bool
   551  	VolumeMountPath string
   552  	VolumeName      string
   553  	VolumeReadOnly  bool
   554  	Env             []Env
   555  	EnvFrom         []EnvFrom
   556  }
   557  
   558  // getCtr takes a list of ctrOptions and returns a Ctr with sane defaults
   559  // and the configured options
   560  func getCtr(options ...ctrOption) *Ctr {
   561  	c := Ctr{
   562  		Name:            defaultCtrName,
   563  		Image:           defaultCtrImage,
   564  		Cmd:             defaultCtrCmd,
   565  		Arg:             defaultCtrArg,
   566  		SecurityContext: true,
   567  		Caps:            false,
   568  		CapAdd:          nil,
   569  		CapDrop:         nil,
   570  		PullPolicy:      "",
   571  		HostIP:          "",
   572  		Port:            "",
   573  		VolumeMount:     false,
   574  		VolumeMountPath: "",
   575  		VolumeName:      "",
   576  		VolumeReadOnly:  false,
   577  		Env:             []Env{},
   578  		EnvFrom:         []EnvFrom{},
   579  	}
   580  	for _, option := range options {
   581  		option(&c)
   582  	}
   583  	return &c
   584  }
   585  
   586  type ctrOption func(*Ctr)
   587  
   588  func withCmd(cmd []string) ctrOption {
   589  	return func(c *Ctr) {
   590  		c.Cmd = cmd
   591  	}
   592  }
   593  
   594  func withArg(arg []string) ctrOption {
   595  	return func(c *Ctr) {
   596  		c.Arg = arg
   597  	}
   598  }
   599  
   600  func withImage(img string) ctrOption {
   601  	return func(c *Ctr) {
   602  		c.Image = img
   603  	}
   604  }
   605  
   606  func withCpuRequest(request string) ctrOption {
   607  	return func(c *Ctr) {
   608  		c.CpuRequest = request
   609  	}
   610  }
   611  
   612  func withCpuLimit(limit string) ctrOption {
   613  	return func(c *Ctr) {
   614  		c.CpuLimit = limit
   615  	}
   616  }
   617  
   618  func withMemoryRequest(request string) ctrOption {
   619  	return func(c *Ctr) {
   620  		c.MemoryRequest = request
   621  	}
   622  }
   623  
   624  func withMemoryLimit(limit string) ctrOption {
   625  	return func(c *Ctr) {
   626  		c.MemoryLimit = limit
   627  	}
   628  }
   629  
   630  func withSecurityContext(sc bool) ctrOption {
   631  	return func(c *Ctr) {
   632  		c.SecurityContext = sc
   633  	}
   634  }
   635  
   636  func withCapAdd(caps []string) ctrOption {
   637  	return func(c *Ctr) {
   638  		c.CapAdd = caps
   639  		c.Caps = true
   640  	}
   641  }
   642  
   643  func withCapDrop(caps []string) ctrOption {
   644  	return func(c *Ctr) {
   645  		c.CapDrop = caps
   646  		c.Caps = true
   647  	}
   648  }
   649  
   650  func withPullPolicy(policy string) ctrOption {
   651  	return func(c *Ctr) {
   652  		c.PullPolicy = policy
   653  	}
   654  }
   655  
   656  func withHostIP(ip string, port string) ctrOption {
   657  	return func(c *Ctr) {
   658  		c.HostIP = ip
   659  		c.Port = port
   660  	}
   661  }
   662  
   663  func withVolumeMount(mountPath string, readonly bool) ctrOption {
   664  	return func(c *Ctr) {
   665  		c.VolumeMountPath = mountPath
   666  		c.VolumeName = defaultVolName
   667  		c.VolumeReadOnly = readonly
   668  		c.VolumeMount = true
   669  	}
   670  }
   671  
   672  func withEnv(name, value, valueFrom, refName, refKey string) ctrOption {
   673  	return func(c *Ctr) {
   674  		e := Env{
   675  			Name:      name,
   676  			Value:     value,
   677  			ValueFrom: valueFrom,
   678  			RefName:   refName,
   679  			RefKey:    refKey,
   680  		}
   681  
   682  		c.Env = append(c.Env, e)
   683  	}
   684  }
   685  
   686  func withEnvFrom(name, from string) ctrOption {
   687  	return func(c *Ctr) {
   688  		e := EnvFrom{
   689  			Name: name,
   690  			From: from,
   691  		}
   692  
   693  		c.EnvFrom = append(c.EnvFrom, e)
   694  	}
   695  }
   696  
   697  func getCtrNameInPod(pod *Pod) string {
   698  	return fmt.Sprintf("%s-%s", pod.Name, defaultCtrName)
   699  }
   700  
   701  type HostPath struct {
   702  	Path string
   703  	Type string
   704  }
   705  
   706  type PersistentVolumeClaim struct {
   707  	ClaimName string
   708  }
   709  
   710  type Volume struct {
   711  	VolumeType string
   712  	Name       string
   713  	HostPath
   714  	PersistentVolumeClaim
   715  }
   716  
   717  // getHostPathVolume takes a type and a location for a HostPath
   718  // volume giving it a default name of volName
   719  func getHostPathVolume(vType, vPath string) *Volume {
   720  	return &Volume{
   721  		VolumeType: "HostPath",
   722  		Name:       defaultVolName,
   723  		HostPath: HostPath{
   724  			Path: vPath,
   725  			Type: vType,
   726  		},
   727  	}
   728  }
   729  
   730  // getHostPathVolume takes a name for a Persistentvolumeclaim
   731  // volume giving it a default name of volName
   732  func getPersistentVolumeClaimVolume(vName string) *Volume {
   733  	return &Volume{
   734  		VolumeType: "PersistentVolumeClaim",
   735  		Name:       defaultVolName,
   736  		PersistentVolumeClaim: PersistentVolumeClaim{
   737  			ClaimName: vName,
   738  		},
   739  	}
   740  }
   741  
   742  type Env struct {
   743  	Name      string
   744  	Value     string
   745  	ValueFrom string
   746  	RefName   string
   747  	RefKey    string
   748  }
   749  
   750  type EnvFrom struct {
   751  	Name string
   752  	From string
   753  }
   754  
   755  func milliCPUToQuota(milliCPU string) int {
   756  	milli, _ := strconv.Atoi(strings.Trim(milliCPU, "m"))
   757  	return milli * defaultCPUPeriod
   758  }
   759  
   760  var _ = Describe("Podman play kube", func() {
   761  	var (
   762  		tempdir    string
   763  		err        error
   764  		podmanTest *PodmanTestIntegration
   765  		kubeYaml   string
   766  	)
   767  
   768  	BeforeEach(func() {
   769  		tempdir, err = CreateTempDirInTempDir()
   770  		if err != nil {
   771  			os.Exit(1)
   772  		}
   773  		podmanTest = PodmanTestCreate(tempdir)
   774  		podmanTest.Setup()
   775  		podmanTest.SeedImages()
   776  
   777  		kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml")
   778  	})
   779  
   780  	AfterEach(func() {
   781  		podmanTest.Cleanup()
   782  		f := CurrentGinkgoTestDescription()
   783  		processTestResult(f)
   784  	})
   785  
   786  	It("podman play kube fail with yaml of unsupported kind", func() {
   787  		err := writeYaml(unknownKindYaml, kubeYaml)
   788  		Expect(err).To(BeNil())
   789  
   790  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   791  		kube.WaitWithDefaultTimeout()
   792  		Expect(kube.ExitCode()).To(Not(Equal(0)))
   793  
   794  	})
   795  
   796  	It("podman play kube fail with nonexist authfile", func() {
   797  		err := generateKubeYaml("pod", getPod(), kubeYaml)
   798  		Expect(err).To(BeNil())
   799  
   800  		kube := podmanTest.Podman([]string{"play", "kube", "--authfile", "/tmp/nonexist", kubeYaml})
   801  		kube.WaitWithDefaultTimeout()
   802  		Expect(kube.ExitCode()).To(Not(Equal(0)))
   803  
   804  	})
   805  
   806  	It("podman play kube test correct command", func() {
   807  		pod := getPod()
   808  		err := generateKubeYaml("pod", pod, kubeYaml)
   809  		Expect(err).To(BeNil())
   810  
   811  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   812  		kube.WaitWithDefaultTimeout()
   813  		Expect(kube.ExitCode()).To(Equal(0))
   814  
   815  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
   816  		inspect.WaitWithDefaultTimeout()
   817  		Expect(inspect.ExitCode()).To(Equal(0))
   818  		// Use the defined command to override the image's command
   819  		correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
   820  		Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
   821  	})
   822  
   823  	It("podman play kube test correct command with only set command in yaml file", func() {
   824  		pod := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg(nil))))
   825  		err := generateKubeYaml("pod", pod, kubeYaml)
   826  		Expect(err).To(BeNil())
   827  
   828  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   829  		kube.WaitWithDefaultTimeout()
   830  		Expect(kube.ExitCode()).To(Equal(0))
   831  
   832  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
   833  		inspect.WaitWithDefaultTimeout()
   834  		Expect(inspect.ExitCode()).To(Equal(0))
   835  		// Use the defined command to override the image's command, and don't set the args
   836  		// so the full command in result should not contains the image's command
   837  		Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`))
   838  	})
   839  
   840  	It("podman play kube test correct command with only set args in yaml file", func() {
   841  		pod := getPod(withCtr(getCtr(withImage(redis), withCmd(nil), withArg([]string{"echo", "hello"}))))
   842  		err := generateKubeYaml("pod", pod, kubeYaml)
   843  		Expect(err).To(BeNil())
   844  
   845  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   846  		kube.WaitWithDefaultTimeout()
   847  		Expect(kube.ExitCode()).To(Equal(0))
   848  
   849  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
   850  		inspect.WaitWithDefaultTimeout()
   851  		Expect(inspect.ExitCode()).To(Equal(0))
   852  		// this image's ENTRYPOINT is called `docker-entrypoint.sh`
   853  		// so result should be `docker-entrypoint.sh + withArg(...)`
   854  		Expect(inspect.OutputToString()).To(ContainSubstring(`[docker-entrypoint.sh echo hello]`))
   855  	})
   856  
   857  	It("podman play kube test correct output", func() {
   858  		p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"}))))
   859  
   860  		err := generateKubeYaml("pod", p, kubeYaml)
   861  		Expect(err).To(BeNil())
   862  
   863  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   864  		kube.WaitWithDefaultTimeout()
   865  		Expect(kube.ExitCode()).To(Equal(0))
   866  
   867  		logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(p)})
   868  		logs.WaitWithDefaultTimeout()
   869  		Expect(logs.ExitCode()).To(Equal(0))
   870  		Expect(logs.OutputToString()).To(ContainSubstring("hello world"))
   871  
   872  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(p), "--format", "'{{ .Config.Cmd }}'"})
   873  		inspect.WaitWithDefaultTimeout()
   874  		Expect(inspect.ExitCode()).To(Equal(0))
   875  		Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello world]`))
   876  	})
   877  
   878  	It("podman play kube test restartPolicy", func() {
   879  		// podName,  set,  expect
   880  		testSli := [][]string{
   881  			{"testPod1", "", "always"}, // Default equal to always
   882  			{"testPod2", "Always", "always"},
   883  			{"testPod3", "OnFailure", "on-failure"},
   884  			{"testPod4", "Never", "no"},
   885  		}
   886  		for _, v := range testSli {
   887  			pod := getPod(withPodName(v[0]), withRestartPolicy(v[1]))
   888  			err := generateKubeYaml("pod", pod, kubeYaml)
   889  			Expect(err).To(BeNil())
   890  
   891  			kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   892  			kube.WaitWithDefaultTimeout()
   893  			Expect(kube.ExitCode()).To(Equal(0))
   894  
   895  			inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{.HostConfig.RestartPolicy.Name}}"})
   896  			inspect.WaitWithDefaultTimeout()
   897  			Expect(inspect.ExitCode()).To(Equal(0))
   898  			Expect(inspect.OutputToString()).To(Equal(v[2]))
   899  		}
   900  	})
   901  
   902  	It("podman play kube test env value from configmap", func() {
   903  		SkipIfRemote("configmap list is not supported as a param")
   904  		cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
   905  		cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
   906  		err := generateKubeYaml("configmap", cm, cmYamlPathname)
   907  		Expect(err).To(BeNil())
   908  
   909  		pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO"))))
   910  		err = generateKubeYaml("pod", pod, kubeYaml)
   911  		Expect(err).To(BeNil())
   912  
   913  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname})
   914  		kube.WaitWithDefaultTimeout()
   915  		Expect(kube.ExitCode()).To(Equal(0))
   916  
   917  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
   918  		inspect.WaitWithDefaultTimeout()
   919  		Expect(inspect.ExitCode()).To(Equal(0))
   920  		Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
   921  	})
   922  
   923  	It("podman play kube test get all key-value pairs from configmap as envs", func() {
   924  		SkipIfRemote("configmap list is not supported as a param")
   925  		cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
   926  		cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2"))
   927  		err := generateKubeYaml("configmap", cm, cmYamlPathname)
   928  		Expect(err).To(BeNil())
   929  
   930  		pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap"))))
   931  		err = generateKubeYaml("pod", pod, kubeYaml)
   932  		Expect(err).To(BeNil())
   933  
   934  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname})
   935  		kube.WaitWithDefaultTimeout()
   936  		Expect(kube.ExitCode()).To(Equal(0))
   937  
   938  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
   939  		inspect.WaitWithDefaultTimeout()
   940  		Expect(inspect.ExitCode()).To(Equal(0))
   941  		Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`))
   942  		Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`))
   943  	})
   944  
   945  	It("podman play kube test hostname", func() {
   946  		pod := getPod()
   947  		err := generateKubeYaml("pod", pod, kubeYaml)
   948  		Expect(err).To(BeNil())
   949  
   950  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   951  		kube.WaitWithDefaultTimeout()
   952  		Expect(kube.ExitCode()).To(Equal(0))
   953  
   954  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"})
   955  		inspect.WaitWithDefaultTimeout()
   956  		Expect(inspect.ExitCode()).To(Equal(0))
   957  		Expect(inspect.OutputToString()).To(Equal(defaultPodName))
   958  	})
   959  
   960  	It("podman play kube test with customized hostname", func() {
   961  		hostname := "myhostname"
   962  		pod := getPod(withHostname(hostname))
   963  		err := generateKubeYaml("pod", getPod(withHostname(hostname)), kubeYaml)
   964  		Expect(err).To(BeNil())
   965  
   966  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   967  		kube.WaitWithDefaultTimeout()
   968  		Expect(kube.ExitCode()).To(Equal(0))
   969  
   970  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"})
   971  		inspect.WaitWithDefaultTimeout()
   972  		Expect(inspect.ExitCode()).To(Equal(0))
   973  		Expect(inspect.OutputToString()).To(Equal(hostname))
   974  	})
   975  
   976  	It("podman play kube test HostAliases", func() {
   977  		pod := getPod(withHostAliases("192.168.1.2", []string{
   978  			"test1.podman.io",
   979  			"test2.podman.io",
   980  		}),
   981  			withHostAliases("192.168.1.3", []string{
   982  				"test3.podman.io",
   983  				"test4.podman.io",
   984  			}),
   985  		)
   986  		err := generateKubeYaml("pod", pod, kubeYaml)
   987  		Expect(err).To(BeNil())
   988  
   989  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
   990  		kube.WaitWithDefaultTimeout()
   991  		Expect(kube.ExitCode()).To(Equal(0))
   992  
   993  		inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.HostAdd}}"})
   994  		inspect.WaitWithDefaultTimeout()
   995  		Expect(inspect.ExitCode()).To(Equal(0))
   996  		Expect(inspect.OutputToString()).
   997  			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]"))
   998  	})
   999  
  1000  	It("podman play kube cap add", func() {
  1001  		capAdd := "CAP_SYS_ADMIN"
  1002  		ctr := getCtr(withCapAdd([]string{capAdd}), withCmd([]string{"cat", "/proc/self/status"}), withArg(nil))
  1003  
  1004  		pod := getPod(withCtr(ctr))
  1005  		err := generateKubeYaml("pod", pod, kubeYaml)
  1006  		Expect(err).To(BeNil())
  1007  
  1008  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1009  		kube.WaitWithDefaultTimeout()
  1010  		Expect(kube.ExitCode()).To(Equal(0))
  1011  
  1012  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
  1013  		inspect.WaitWithDefaultTimeout()
  1014  		Expect(inspect.ExitCode()).To(Equal(0))
  1015  		Expect(inspect.OutputToString()).To(ContainSubstring(capAdd))
  1016  	})
  1017  
  1018  	It("podman play kube cap drop", func() {
  1019  		capDrop := "CAP_CHOWN"
  1020  		ctr := getCtr(withCapDrop([]string{capDrop}))
  1021  
  1022  		pod := getPod(withCtr(ctr))
  1023  		err := generateKubeYaml("pod", pod, kubeYaml)
  1024  		Expect(err).To(BeNil())
  1025  
  1026  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1027  		kube.WaitWithDefaultTimeout()
  1028  		Expect(kube.ExitCode()).To(Equal(0))
  1029  
  1030  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
  1031  		inspect.WaitWithDefaultTimeout()
  1032  		Expect(inspect.ExitCode()).To(Equal(0))
  1033  		Expect(inspect.OutputToString()).To(ContainSubstring(capDrop))
  1034  	})
  1035  
  1036  	It("podman play kube no security context", func() {
  1037  		// expect play kube to not fail if no security context is specified
  1038  		pod := getPod(withCtr(getCtr(withSecurityContext(false))))
  1039  		err := generateKubeYaml("pod", pod, kubeYaml)
  1040  		Expect(err).To(BeNil())
  1041  
  1042  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1043  		kube.WaitWithDefaultTimeout()
  1044  		Expect(kube.ExitCode()).To(Equal(0))
  1045  
  1046  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
  1047  		inspect.WaitWithDefaultTimeout()
  1048  		Expect(inspect.ExitCode()).To(Equal(0))
  1049  	})
  1050  
  1051  	It("podman play kube seccomp container level", func() {
  1052  		SkipIfRemote("podman-remote does not support --seccomp-profile-root flag")
  1053  		// expect play kube is expected to set a seccomp label if it's applied as an annotation
  1054  		jsonFile, err := podmanTest.CreateSeccompJson(seccompPwdEPERM)
  1055  		if err != nil {
  1056  			fmt.Println(err)
  1057  			Skip("Failed to prepare seccomp.json for test.")
  1058  		}
  1059  
  1060  		ctrAnnotation := "container.seccomp.security.alpha.kubernetes.io/" + defaultCtrName
  1061  		ctr := getCtr(withCmd([]string{"pwd"}), withArg(nil))
  1062  
  1063  		pod := getPod(withCtr(ctr), withAnnotation(ctrAnnotation, "localhost/"+filepath.Base(jsonFile)))
  1064  		err = generateKubeYaml("pod", pod, kubeYaml)
  1065  		Expect(err).To(BeNil())
  1066  
  1067  		// CreateSeccompJson will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look
  1068  		kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml})
  1069  		kube.WaitWithDefaultTimeout()
  1070  		Expect(kube.ExitCode()).To(Equal(0))
  1071  
  1072  		logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)})
  1073  		logs.WaitWithDefaultTimeout()
  1074  		Expect(logs.ExitCode()).To(Equal(0))
  1075  		Expect(logs.OutputToString()).To(ContainSubstring("Operation not permitted"))
  1076  	})
  1077  
  1078  	It("podman play kube seccomp pod level", func() {
  1079  		SkipIfRemote("podman-remote does not support --seccomp-profile-root flag")
  1080  		// expect play kube is expected to set a seccomp label if it's applied as an annotation
  1081  		jsonFile, err := podmanTest.CreateSeccompJson(seccompPwdEPERM)
  1082  		if err != nil {
  1083  			fmt.Println(err)
  1084  			Skip("Failed to prepare seccomp.json for test.")
  1085  		}
  1086  		defer os.Remove(jsonFile)
  1087  
  1088  		ctr := getCtr(withCmd([]string{"pwd"}), withArg(nil))
  1089  
  1090  		pod := getPod(withCtr(ctr), withAnnotation("seccomp.security.alpha.kubernetes.io/pod", "localhost/"+filepath.Base(jsonFile)))
  1091  		err = generateKubeYaml("pod", pod, kubeYaml)
  1092  		Expect(err).To(BeNil())
  1093  
  1094  		// CreateSeccompJson will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look
  1095  		kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml})
  1096  		kube.WaitWithDefaultTimeout()
  1097  		Expect(kube.ExitCode()).To(Equal(0))
  1098  
  1099  		logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)})
  1100  		logs.WaitWithDefaultTimeout()
  1101  		Expect(logs.ExitCode()).To(Equal(0))
  1102  		Expect(logs.OutputToString()).To(ContainSubstring("Operation not permitted"))
  1103  	})
  1104  
  1105  	It("podman play kube with pull policy of never should be 125", func() {
  1106  		ctr := getCtr(withPullPolicy("never"), withImage(BB_GLIBC))
  1107  		err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
  1108  		Expect(err).To(BeNil())
  1109  
  1110  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1111  		kube.WaitWithDefaultTimeout()
  1112  		Expect(kube.ExitCode()).To(Equal(125))
  1113  	})
  1114  
  1115  	It("podman play kube with pull policy of missing", func() {
  1116  		ctr := getCtr(withPullPolicy("missing"), withImage(BB))
  1117  		err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
  1118  		Expect(err).To(BeNil())
  1119  
  1120  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1121  		kube.WaitWithDefaultTimeout()
  1122  		Expect(kube.ExitCode()).To(Equal(0))
  1123  	})
  1124  
  1125  	It("podman play kube with pull always", func() {
  1126  		oldBB := "quay.io/libpod/busybox:1.30.1"
  1127  		pull := podmanTest.Podman([]string{"pull", oldBB})
  1128  		pull.WaitWithDefaultTimeout()
  1129  
  1130  		tag := podmanTest.Podman([]string{"tag", oldBB, BB})
  1131  		tag.WaitWithDefaultTimeout()
  1132  		Expect(tag.ExitCode()).To(BeZero())
  1133  
  1134  		rmi := podmanTest.Podman([]string{"rmi", oldBB})
  1135  		rmi.WaitWithDefaultTimeout()
  1136  		Expect(rmi.ExitCode()).To(BeZero())
  1137  
  1138  		inspect := podmanTest.Podman([]string{"inspect", BB})
  1139  		inspect.WaitWithDefaultTimeout()
  1140  		oldBBinspect := inspect.InspectImageJSON()
  1141  
  1142  		ctr := getCtr(withPullPolicy("always"), withImage(BB))
  1143  		err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
  1144  		Expect(err).To(BeNil())
  1145  
  1146  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1147  		kube.WaitWithDefaultTimeout()
  1148  		Expect(kube.ExitCode()).To(Equal(0))
  1149  
  1150  		inspect = podmanTest.Podman([]string{"inspect", BB})
  1151  		inspect.WaitWithDefaultTimeout()
  1152  		newBBinspect := inspect.InspectImageJSON()
  1153  		Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest)))
  1154  	})
  1155  
  1156  	It("podman play kube with latest image should always pull", func() {
  1157  		oldBB := "quay.io/libpod/busybox:1.30.1"
  1158  		pull := podmanTest.Podman([]string{"pull", oldBB})
  1159  		pull.WaitWithDefaultTimeout()
  1160  
  1161  		tag := podmanTest.Podman([]string{"tag", oldBB, BB})
  1162  		tag.WaitWithDefaultTimeout()
  1163  		Expect(tag.ExitCode()).To(BeZero())
  1164  
  1165  		rmi := podmanTest.Podman([]string{"rmi", oldBB})
  1166  		rmi.WaitWithDefaultTimeout()
  1167  		Expect(rmi.ExitCode()).To(BeZero())
  1168  
  1169  		inspect := podmanTest.Podman([]string{"inspect", BB})
  1170  		inspect.WaitWithDefaultTimeout()
  1171  		oldBBinspect := inspect.InspectImageJSON()
  1172  
  1173  		ctr := getCtr(withImage(BB))
  1174  		err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
  1175  		Expect(err).To(BeNil())
  1176  
  1177  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1178  		kube.WaitWithDefaultTimeout()
  1179  		Expect(kube.ExitCode()).To(Equal(0))
  1180  
  1181  		inspect = podmanTest.Podman([]string{"inspect", BB})
  1182  		inspect.WaitWithDefaultTimeout()
  1183  		newBBinspect := inspect.InspectImageJSON()
  1184  		Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest)))
  1185  	})
  1186  
  1187  	It("podman play kube with image data", func() {
  1188  		testyaml := `
  1189  apiVersion: v1
  1190  kind: Pod
  1191  metadata:
  1192    name: demo_pod
  1193  spec:
  1194    containers:
  1195    - image: demo
  1196      name: demo_kube
  1197  `
  1198  		pull := podmanTest.Podman([]string{"create", "--workdir", "/etc", "--name", "newBB", "--label", "key1=value1", "alpine"})
  1199  
  1200  		pull.WaitWithDefaultTimeout()
  1201  		Expect(pull.ExitCode()).To(BeZero())
  1202  
  1203  		c := podmanTest.Podman([]string{"commit", "-c", "STOPSIGNAL=51", "newBB", "demo"})
  1204  		c.WaitWithDefaultTimeout()
  1205  		Expect(c.ExitCode()).To(Equal(0))
  1206  
  1207  		conffile := filepath.Join(podmanTest.TempDir, "kube.yaml")
  1208  		tempdir, err = CreateTempDirInTempDir()
  1209  		Expect(err).To(BeNil())
  1210  
  1211  		err := ioutil.WriteFile(conffile, []byte(testyaml), 0755)
  1212  		Expect(err).To(BeNil())
  1213  
  1214  		kube := podmanTest.Podman([]string{"play", "kube", conffile})
  1215  		kube.WaitWithDefaultTimeout()
  1216  		Expect(kube.ExitCode()).To(Equal(0))
  1217  
  1218  		inspect := podmanTest.Podman([]string{"inspect", "demo_pod-demo_kube"})
  1219  		inspect.WaitWithDefaultTimeout()
  1220  		Expect(inspect.ExitCode()).To(Equal(0))
  1221  
  1222  		ctr := inspect.InspectContainerToJSON()
  1223  		Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc"))
  1224  		Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
  1225  		Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
  1226  		Expect(ctr[0].Config.StopSignal).To(Equal(uint(51)))
  1227  	})
  1228  
  1229  	// Deployment related tests
  1230  	It("podman play kube deployment 1 replica test correct command", func() {
  1231  		deployment := getDeployment()
  1232  		err := generateKubeYaml("deployment", deployment, kubeYaml)
  1233  		Expect(err).To(BeNil())
  1234  
  1235  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1236  		kube.WaitWithDefaultTimeout()
  1237  		Expect(kube.ExitCode()).To(Equal(0))
  1238  
  1239  		podNames := getPodNamesInDeployment(deployment)
  1240  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[0]), "--format", "'{{ .Config.Cmd }}'"})
  1241  		inspect.WaitWithDefaultTimeout()
  1242  		Expect(inspect.ExitCode()).To(Equal(0))
  1243  		// yaml's command shuold override the image's Entrypoint
  1244  		correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
  1245  		Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
  1246  	})
  1247  
  1248  	It("podman play kube deployment more than 1 replica test correct command", func() {
  1249  		var i, numReplicas int32
  1250  		numReplicas = 5
  1251  		deployment := getDeployment(withReplicas(numReplicas))
  1252  		err := generateKubeYaml("deployment", deployment, kubeYaml)
  1253  		Expect(err).To(BeNil())
  1254  
  1255  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1256  		kube.WaitWithDefaultTimeout()
  1257  		Expect(kube.ExitCode()).To(Equal(0))
  1258  
  1259  		podNames := getPodNamesInDeployment(deployment)
  1260  		correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
  1261  		for i = 0; i < numReplicas; i++ {
  1262  			inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "'{{ .Config.Cmd }}'"})
  1263  			inspect.WaitWithDefaultTimeout()
  1264  			Expect(inspect.ExitCode()).To(Equal(0))
  1265  			Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
  1266  		}
  1267  	})
  1268  
  1269  	It("podman play kube test with network portbindings", func() {
  1270  		ip := "127.0.0.100"
  1271  		port := "5000"
  1272  		ctr := getCtr(withHostIP(ip, port), withImage(BB))
  1273  
  1274  		pod := getPod(withCtr(ctr))
  1275  		err := generateKubeYaml("pod", pod, kubeYaml)
  1276  		Expect(err).To(BeNil())
  1277  
  1278  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1279  		kube.WaitWithDefaultTimeout()
  1280  		Expect(kube.ExitCode()).To(Equal(0))
  1281  
  1282  		inspect := podmanTest.Podman([]string{"port", getCtrNameInPod(pod)})
  1283  		inspect.WaitWithDefaultTimeout()
  1284  		Expect(inspect.ExitCode()).To(Equal(0))
  1285  		Expect(inspect.OutputToString()).To(Equal("5000/tcp -> 127.0.0.100:5000"))
  1286  	})
  1287  
  1288  	It("podman play kube test with non-existent empty HostPath type volume", func() {
  1289  		hostPathLocation := filepath.Join(tempdir, "file")
  1290  
  1291  		pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation)))
  1292  		err := generateKubeYaml("pod", pod, kubeYaml)
  1293  		Expect(err).To(BeNil())
  1294  
  1295  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1296  		kube.WaitWithDefaultTimeout()
  1297  		Expect(kube.ExitCode()).NotTo(Equal(0))
  1298  	})
  1299  
  1300  	It("podman play kube test with empty HostPath type volume", func() {
  1301  		hostPathLocation := filepath.Join(tempdir, "file")
  1302  		f, err := os.Create(hostPathLocation)
  1303  		Expect(err).To(BeNil())
  1304  		f.Close()
  1305  
  1306  		pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation)))
  1307  		err = generateKubeYaml("pod", pod, kubeYaml)
  1308  		Expect(err).To(BeNil())
  1309  
  1310  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1311  		kube.WaitWithDefaultTimeout()
  1312  		Expect(kube.ExitCode()).To(Equal(0))
  1313  	})
  1314  
  1315  	It("podman play kube test with non-existent File HostPath type volume", func() {
  1316  		hostPathLocation := filepath.Join(tempdir, "file")
  1317  
  1318  		pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)))
  1319  		err := generateKubeYaml("pod", pod, kubeYaml)
  1320  		Expect(err).To(BeNil())
  1321  
  1322  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1323  		kube.WaitWithDefaultTimeout()
  1324  		Expect(kube.ExitCode()).NotTo(Equal(0))
  1325  	})
  1326  
  1327  	It("podman play kube test with File HostPath type volume", func() {
  1328  		hostPathLocation := filepath.Join(tempdir, "file")
  1329  		f, err := os.Create(hostPathLocation)
  1330  		Expect(err).To(BeNil())
  1331  		f.Close()
  1332  
  1333  		pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)))
  1334  		err = generateKubeYaml("pod", pod, kubeYaml)
  1335  		Expect(err).To(BeNil())
  1336  
  1337  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1338  		kube.WaitWithDefaultTimeout()
  1339  		Expect(kube.ExitCode()).To(Equal(0))
  1340  	})
  1341  
  1342  	It("podman play kube test with FileOrCreate HostPath type volume", func() {
  1343  		hostPathLocation := filepath.Join(tempdir, "file")
  1344  
  1345  		pod := getPod(withVolume(getHostPathVolume("FileOrCreate", hostPathLocation)))
  1346  		err := generateKubeYaml("pod", pod, kubeYaml)
  1347  		Expect(err).To(BeNil())
  1348  
  1349  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1350  		kube.WaitWithDefaultTimeout()
  1351  		Expect(kube.ExitCode()).To(Equal(0))
  1352  
  1353  		// the file should have been created
  1354  		_, err = os.Stat(hostPathLocation)
  1355  		Expect(err).To(BeNil())
  1356  	})
  1357  
  1358  	It("podman play kube test with DirectoryOrCreate HostPath type volume", func() {
  1359  		hostPathLocation := filepath.Join(tempdir, "file")
  1360  
  1361  		pod := getPod(withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation)))
  1362  		err := generateKubeYaml("pod", pod, kubeYaml)
  1363  		Expect(err).To(BeNil())
  1364  
  1365  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1366  		kube.WaitWithDefaultTimeout()
  1367  		Expect(kube.ExitCode()).To(Equal(0))
  1368  
  1369  		// the file should have been created
  1370  		st, err := os.Stat(hostPathLocation)
  1371  		Expect(err).To(BeNil())
  1372  		Expect(st.Mode().IsDir()).To(Equal(true))
  1373  	})
  1374  
  1375  	It("podman play kube test with Socket HostPath type volume should fail if not socket", func() {
  1376  		hostPathLocation := filepath.Join(tempdir, "file")
  1377  		f, err := os.Create(hostPathLocation)
  1378  		Expect(err).To(BeNil())
  1379  		f.Close()
  1380  
  1381  		pod := getPod(withVolume(getHostPathVolume("Socket", hostPathLocation)))
  1382  		err = generateKubeYaml("pod", pod, kubeYaml)
  1383  		Expect(err).To(BeNil())
  1384  
  1385  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1386  		kube.WaitWithDefaultTimeout()
  1387  		Expect(kube.ExitCode()).NotTo(Equal(0))
  1388  	})
  1389  
  1390  	It("podman play kube test with read only HostPath volume", func() {
  1391  		hostPathLocation := filepath.Join(tempdir, "file")
  1392  		f, err := os.Create(hostPathLocation)
  1393  		Expect(err).To(BeNil())
  1394  		f.Close()
  1395  
  1396  		ctr := getCtr(withVolumeMount(hostPathLocation, true), withImage(BB))
  1397  		pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)), withCtr(ctr))
  1398  		err = generateKubeYaml("pod", pod, kubeYaml)
  1399  		Expect(err).To(BeNil())
  1400  
  1401  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1402  		kube.WaitWithDefaultTimeout()
  1403  		Expect(kube.ExitCode()).To(Equal(0))
  1404  
  1405  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{.HostConfig.Binds}}'"})
  1406  		inspect.WaitWithDefaultTimeout()
  1407  		Expect(inspect.ExitCode()).To(Equal(0))
  1408  
  1409  		correct := fmt.Sprintf("%s:%s:%s", hostPathLocation, hostPathLocation, "ro")
  1410  		Expect(inspect.OutputToString()).To(ContainSubstring(correct))
  1411  	})
  1412  
  1413  	It("podman play kube test with PersistentVolumeClaim volume", func() {
  1414  		volumeName := "namedVolume"
  1415  
  1416  		ctr := getCtr(withVolumeMount("/test", false), withImage(BB))
  1417  		pod := getPod(withVolume(getPersistentVolumeClaimVolume(volumeName)), withCtr(ctr))
  1418  		err = generateKubeYaml("pod", pod, kubeYaml)
  1419  		Expect(err).To(BeNil())
  1420  
  1421  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1422  		kube.WaitWithDefaultTimeout()
  1423  		Expect(kube.ExitCode()).To(Equal(0))
  1424  
  1425  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"})
  1426  		inspect.WaitWithDefaultTimeout()
  1427  		Expect(inspect.ExitCode()).To(Equal(0))
  1428  
  1429  		correct := fmt.Sprintf("volume:%s", volumeName)
  1430  		Expect(inspect.OutputToString()).To(Equal(correct))
  1431  	})
  1432  
  1433  	It("podman play kube applies labels to pods", func() {
  1434  		var numReplicas int32 = 5
  1435  		expectedLabelKey := "key1"
  1436  		expectedLabelValue := "value1"
  1437  		deployment := getDeployment(
  1438  			withReplicas(numReplicas),
  1439  			withPod(getPod(withLabel(expectedLabelKey, expectedLabelValue))),
  1440  		)
  1441  		err := generateKubeYaml("deployment", deployment, kubeYaml)
  1442  		Expect(err).To(BeNil())
  1443  
  1444  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1445  		kube.WaitWithDefaultTimeout()
  1446  		Expect(kube.ExitCode()).To(Equal(0))
  1447  
  1448  		correctLabels := expectedLabelKey + ":" + expectedLabelValue
  1449  		for _, pod := range getPodNamesInDeployment(deployment) {
  1450  			inspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{ .Labels }}'"})
  1451  			inspect.WaitWithDefaultTimeout()
  1452  			Expect(inspect.ExitCode()).To(Equal(0))
  1453  			Expect(inspect.OutputToString()).To(ContainSubstring(correctLabels))
  1454  		}
  1455  	})
  1456  
  1457  	It("podman play kube allows setting resource limits", func() {
  1458  		SkipIfContainerized("Resource limits require a running systemd")
  1459  		SkipIfRootlessCgroupsV1("Limits require root or cgroups v2")
  1460  		SkipIfUnprivilegedCPULimits()
  1461  		podmanTest.CgroupManager = "systemd"
  1462  
  1463  		var (
  1464  			numReplicas           int32  = 3
  1465  			expectedCpuRequest    string = "100m"
  1466  			expectedCpuLimit      string = "200m"
  1467  			expectedMemoryRequest string = "10000000"
  1468  			expectedMemoryLimit   string = "20000000"
  1469  		)
  1470  
  1471  		expectedCpuQuota := milliCPUToQuota(expectedCpuLimit)
  1472  
  1473  		deployment := getDeployment(
  1474  			withReplicas(numReplicas),
  1475  			withPod(getPod(withCtr(getCtr(
  1476  				withCpuRequest(expectedCpuRequest),
  1477  				withCpuLimit(expectedCpuLimit),
  1478  				withMemoryRequest(expectedMemoryRequest),
  1479  				withMemoryLimit(expectedMemoryLimit),
  1480  			)))))
  1481  		err := generateKubeYaml("deployment", deployment, kubeYaml)
  1482  		Expect(err).To(BeNil())
  1483  
  1484  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1485  		kube.WaitWithDefaultTimeout()
  1486  		Expect(kube.ExitCode()).To(Equal(0))
  1487  
  1488  		for _, pod := range getPodNamesInDeployment(deployment) {
  1489  			inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", `
  1490  CpuPeriod: {{ .HostConfig.CpuPeriod }}
  1491  CpuQuota: {{ .HostConfig.CpuQuota }}
  1492  Memory: {{ .HostConfig.Memory }}
  1493  MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
  1494  			inspect.WaitWithDefaultTimeout()
  1495  			Expect(inspect.ExitCode()).To(Equal(0))
  1496  			Expect(inspect.OutputToString()).To(ContainSubstring(fmt.Sprintf("%s: %d", "CpuQuota", expectedCpuQuota)))
  1497  			Expect(inspect.OutputToString()).To(ContainSubstring("MemoryReservation: " + expectedMemoryRequest))
  1498  			Expect(inspect.OutputToString()).To(ContainSubstring("Memory: " + expectedMemoryLimit))
  1499  		}
  1500  	})
  1501  
  1502  	It("podman play kube reports invalid image name", func() {
  1503  		invalidImageName := "./myimage"
  1504  
  1505  		pod := getPod(
  1506  			withCtr(
  1507  				getCtr(
  1508  					withImage(invalidImageName),
  1509  				),
  1510  			),
  1511  		)
  1512  		err := generateKubeYaml("pod", pod, kubeYaml)
  1513  		Expect(err).To(BeNil())
  1514  
  1515  		kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
  1516  		kube.WaitWithDefaultTimeout()
  1517  		Expect(kube.ExitCode()).To(Equal(125))
  1518  		Expect(kube.ErrorToString()).To(ContainSubstring(invalidImageName))
  1519  	})
  1520  
  1521  	It("podman play kube applies log driver to containers", func() {
  1522  		Skip("need to verify images have correct packages for journald")
  1523  		pod := getPod()
  1524  		err := generateKubeYaml("pod", pod, kubeYaml)
  1525  		Expect(err).To(BeNil())
  1526  
  1527  		kube := podmanTest.Podman([]string{"play", "kube", "--log-driver", "journald", kubeYaml})
  1528  		kube.WaitWithDefaultTimeout()
  1529  		Expect(kube.ExitCode()).To(Equal(0))
  1530  
  1531  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .HostConfig.LogConfig.Type }}'"})
  1532  		inspect.WaitWithDefaultTimeout()
  1533  		Expect(inspect.ExitCode()).To(Equal(0))
  1534  		Expect(inspect.OutputToString()).To(ContainSubstring("journald"))
  1535  	})
  1536  
  1537  	It("podman play kube test only creating the containers", func() {
  1538  		pod := getPod()
  1539  		err := generateKubeYaml("pod", pod, kubeYaml)
  1540  		Expect(err).To(BeNil())
  1541  
  1542  		kube := podmanTest.Podman([]string{"play", "kube", "--start=false", kubeYaml})
  1543  		kube.WaitWithDefaultTimeout()
  1544  		Expect(kube.ExitCode()).To(Equal(0))
  1545  
  1546  		inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .State.Running }}"})
  1547  		inspect.WaitWithDefaultTimeout()
  1548  		Expect(inspect.ExitCode()).To(Equal(0))
  1549  		Expect(inspect.OutputToString()).To(Equal("false"))
  1550  	})
  1551  })