From 61cb6d61dd420a000c843171b5917b5595874a67 Mon Sep 17 00:00:00 2001 From: Eduardo Vega Date: Fri, 26 Mar 2021 18:16:41 -0600 Subject: Add support for play/generate kube volumes Signed-off-by: Eduardo Vega --- test/e2e/generate_kube_test.go | 58 ++++++++++++- test/e2e/play_kube_test.go | 182 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 1c53307bd..c3586d9b6 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strconv" + "github.com/containers/podman/v3/pkg/util" . "github.com/containers/podman/v3/test/utils" "github.com/ghodss/yaml" . "github.com/onsi/ginkgo" @@ -554,7 +555,7 @@ var _ = Describe("Podman generate kube", func() { Expect(inspect.OutputToString()).To(ContainSubstring(`"pid"`)) }) - It("podman generate kube with pods and containers should fail", func() { + It("podman generate kube with pods and containers", func() { pod1 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod1", ALPINE, "top"}) pod1.WaitWithDefaultTimeout() Expect(pod1.ExitCode()).To(Equal(0)) @@ -565,7 +566,7 @@ var _ = Describe("Podman generate kube", func() { kube := podmanTest.Podman([]string{"generate", "kube", "pod1", "top"}) kube.WaitWithDefaultTimeout() - Expect(kube.ExitCode()).ToNot(Equal(0)) + Expect(kube.ExitCode()).To(Equal(0)) }) It("podman generate kube with containers in a pod should fail", func() { @@ -630,7 +631,7 @@ var _ = Describe("Podman generate kube", func() { Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue")) }) - It("podman generate kube multiple contianer dns servers and options are cumulative", func() { + It("podman generate kube multiple container dns servers and options are cumulative", func() { top1 := podmanTest.Podman([]string{"run", "-dt", "--name", "top1", "--dns", "8.8.8.8", "--dns-search", "foobar.com", ALPINE, "top"}) top1.WaitWithDefaultTimeout() Expect(top1.ExitCode()).To(BeZero()) @@ -798,4 +799,55 @@ USER test1` Expect(*pod.Spec.Containers[0].SecurityContext.RunAsUser).To(Equal(int64(10001))) }) + It("podman generate kube on named volume", func() { + vol := "simple-named-volume" + + session := podmanTest.Podman([]string{"volume", "create", vol}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", vol}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + pvc := new(v1.PersistentVolumeClaim) + err := yaml.Unmarshal(kube.Out.Contents(), pvc) + Expect(err).To(BeNil()) + Expect(pvc.GetName()).To(Equal(vol)) + Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce)) + Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi")) + }) + + It("podman generate kube on named volume with options", func() { + vol := "complex-named-volume" + volDevice := "tmpfs" + volType := "tmpfs" + volOpts := "nodev,noexec" + + session := podmanTest.Podman([]string{"volume", "create", "--opt", "device=" + volDevice, "--opt", "type=" + volType, "--opt", "o=" + volOpts, vol}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", vol}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + pvc := new(v1.PersistentVolumeClaim) + err := yaml.Unmarshal(kube.Out.Contents(), pvc) + Expect(err).To(BeNil()) + Expect(pvc.GetName()).To(Equal(vol)) + Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce)) + Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi")) + + for k, v := range pvc.GetAnnotations() { + switch k { + case util.VolumeDeviceAnnotation: + Expect(v).To(Equal(volDevice)) + case util.VolumeTypeAnnotation: + Expect(v).To(Equal(volType)) + case util.VolumeMountOptsAnnotation: + Expect(v).To(Equal(volOpts)) + } + } + }) }) diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 93c8426a7..41afd9f75 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -10,6 +10,7 @@ import ( "strings" "text/template" + "github.com/containers/podman/v3/pkg/util" . "github.com/containers/podman/v3/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -83,6 +84,26 @@ data: {{ end }} ` +var persistentVolumeClaimYamlTemplate = ` +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Name }} +{{ with .Annotations }} + annotations: + {{ range $key, $value := . }} + {{ $key }}: {{ $value }} + {{ end }} +{{ end }} +spec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: "1Gi" + storageClassName: default +` + var podYamlTemplate = ` apiVersion: v1 kind: Pod @@ -337,10 +358,31 @@ spec: privileged: false readOnlyRootFilesystem: false workingDir: / + volumeMounts: + {{ if .VolumeMount }} + - name: {{.VolumeName}} + mountPath: {{ .VolumeMountPath }} + readonly: {{.VolumeReadOnly}} + {{ end }} {{ end }} {{ end }} {{ end }} - {{ end }} + {{ with .Volumes }} + volumes: + {{ range . }} + - name: {{ .Name }} + {{- if (eq .VolumeType "HostPath") }} + hostPath: + path: {{ .HostPath.Path }} + type: {{ .HostPath.Type }} + {{- end }} + {{- if (eq .VolumeType "PersistentVolumeClaim") }} + persistentVolumeClaim: + claimName: {{ .PersistentVolumeClaim.ClaimName }} + {{- end }} + {{ end }} + {{ end }} +{{ end }} ` var ( @@ -352,6 +394,7 @@ var ( defaultVolName = "testVol" defaultDeploymentName = "testDeployment" defaultConfigMapName = "testConfigMap" + defaultPVCName = "testPVC" seccompPwdEPERM = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`) // CPU Period in ms defaultCPUPeriod = 100 @@ -386,6 +429,8 @@ func getKubeYaml(kind string, object interface{}) (string, error) { yamlTemplate = podYamlTemplate case "deployment": yamlTemplate = deploymentYamlTemplate + case "persistentVolumeClaim": + yamlTemplate = persistentVolumeClaimYamlTemplate default: return "", fmt.Errorf("unsupported kubernetes kind") } @@ -467,6 +512,39 @@ func withConfigMapData(k, v string) configMapOption { } } +// PVC describes the options a kube yaml can be configured at persistent volume claim level +type PVC struct { + Name string + Annotations map[string]string +} + +func getPVC(options ...pvcOption) *PVC { + pvc := PVC{ + Name: defaultPVCName, + Annotations: map[string]string{}, + } + + for _, option := range options { + option(&pvc) + } + + return &pvc +} + +type pvcOption func(*PVC) + +func withPVCName(name string) pvcOption { + return func(pvc *PVC) { + pvc.Name = name + } +} + +func withPVCAnnotations(k, v string) pvcOption { + return func(pvc *PVC) { + pvc.Annotations[k] = v + } +} + // Pod describes the options a kube yaml can be configured at pod level type Pod struct { Name string @@ -1941,8 +2019,106 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`}) Expect(inspect.OutputToString()).To(Equal("true")) }) + It("podman play kube persistentVolumeClaim", func() { + volName := "myvol" + volDevice := "tmpfs" + volType := "tmpfs" + volOpts := "nodev,noexec" + + pvc := getPVC(withPVCName(volName), + withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice), + withPVCAnnotations(util.VolumeTypeAnnotation, volType), + withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts)) + err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"inspect", volName, "--format", ` +Name: {{ .Name }} +Device: {{ .Options.device }} +Type: {{ .Options.type }} +o: {{ .Options.o }}`}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(ContainSubstring("Name: " + volName)) + Expect(inspect.OutputToString()).To(ContainSubstring("Device: " + volDevice)) + Expect(inspect.OutputToString()).To(ContainSubstring("Type: " + volType)) + Expect(inspect.OutputToString()).To(ContainSubstring("o: " + volOpts)) + }) + // Multi doc related tests - It("podman play kube multi doc yaml", func() { + It("podman play kube multi doc yaml with persistentVolumeClaim, service and deployment", func() { + yamlDocs := []string{} + + serviceTemplate := `apiVersion: v1 +kind: Service +metadata: + name: %s +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 9376 + selector: + app: %s +` + // generate persistentVolumeClaim + volName := "multiFoo" + pvc := getPVC(withPVCName(volName)) + + // generate deployment + deploymentName := "multiFoo" + podName := "multiFoo" + ctrName := "ctr-01" + ctr := getCtr(withVolumeMount("/test", false)) + ctr.Name = ctrName + pod := getPod(withPodName(podName), withVolume(getPersistentVolumeClaimVolume(volName)), withCtr(ctr)) + deployment := getDeployment(withPod(pod)) + deployment.Name = deploymentName + + // add pvc + k, err := getKubeYaml("persistentVolumeClaim", pvc) + Expect(err).To(BeNil()) + yamlDocs = append(yamlDocs, k) + + // add service + yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, deploymentName, deploymentName)) + + // add deployment + k, err = getKubeYaml("deployment", deployment) + Expect(err).To(BeNil()) + yamlDocs = append(yamlDocs, k) + + // generate multi doc yaml + err = generateMultiDocKubeYaml(yamlDocs, kubeYaml) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + inspectVolume := podmanTest.Podman([]string{"inspect", volName, "--format", "'{{ .Name }}'"}) + inspectVolume.WaitWithDefaultTimeout() + Expect(inspectVolume.ExitCode()).To(Equal(0)) + Expect(inspectVolume.OutputToString()).To(ContainSubstring(volName)) + + inspectPod := podmanTest.Podman([]string{"inspect", podName + "-pod-0", "--format", "'{{ .State }}'"}) + inspectPod.WaitWithDefaultTimeout() + Expect(inspectPod.ExitCode()).To(Equal(0)) + Expect(inspectPod.OutputToString()).To(ContainSubstring(`Running`)) + + inspectMounts := podmanTest.Podman([]string{"inspect", podName + "-pod-0-" + ctrName, "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"}) + inspectMounts.WaitWithDefaultTimeout() + Expect(inspectMounts.ExitCode()).To(Equal(0)) + + correct := fmt.Sprintf("volume:%s", volName) + Expect(inspectMounts.OutputToString()).To(Equal(correct)) + }) + + It("podman play kube multi doc yaml with multiple services, pods and deployments", func() { yamlDocs := []string{} podNames := []string{} @@ -1958,7 +2134,7 @@ spec: selector: app: %s ` - // generate servies, pods and deployments + // generate services, pods and deployments for i := 0; i < 2; i++ { podName := fmt.Sprintf("testPod%d", i) deploymentName := fmt.Sprintf("testDeploy%d", i) -- cgit v1.2.3-54-g00ecf