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