diff options
author | Jordan Christiansen <xordspar0@gmail.com> | 2020-09-28 13:57:58 -0500 |
---|---|---|
committer | Jordan Christiansen <xordspar0@gmail.com> | 2020-10-12 08:38:37 -0500 |
commit | a413d4d77f1701a62b9bb2e7beb00145544e2306 (patch) | |
tree | fd29521eed106a03104eeeaecc6ce5fad040b617 /test/e2e | |
parent | cec240375d6dceb09c705d6d55e67aeff037327f (diff) | |
download | podman-a413d4d77f1701a62b9bb2e7beb00145544e2306.tar.gz podman-a413d4d77f1701a62b9bb2e7beb00145544e2306.tar.bz2 podman-a413d4d77f1701a62b9bb2e7beb00145544e2306.zip |
Add support for resource limits to play kube
Signed-off-by: Jordan Christiansen <xordspar0@gmail.com>
Diffstat (limited to 'test/e2e')
-rw-r--r-- | test/e2e/common_test.go | 9 | ||||
-rw-r--r-- | test/e2e/play_kube_test.go | 131 |
2 files changed, 136 insertions, 4 deletions
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index ec910109b..e36c86690 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -612,6 +612,15 @@ func SkipIfRootlessCgroupsV1(reason string) { } } +func SkipIfUnprevilegedCPULimits() { + info := GetHostDistributionInfo() + if isRootless() && + info.Distribution == "fedora" && + (info.Version == "31" || info.Version == "32") { + ginkgo.Skip("Rootless Fedora doesn't have permission to set CPU limits before version 33") + } +} + func SkipIfRootless(reason string) { checkReason(reason) if os.Geteuid() != 0 { diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index b6a390950..3906fa49d 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strconv" "strings" "text/template" @@ -111,7 +112,19 @@ spec: image: {{ .Image }} name: {{ .Name }} imagePullPolicy: {{ .PullPolicy }} - resources: {} + {{- if or .CpuRequest .CpuLimit .MemoryRequest .MemoryLimit }} + resources: + {{- if or .CpuRequest .MemoryRequest }} + requests: + {{if .CpuRequest }}cpu: {{ .CpuRequest }}{{ end }} + {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} + {{- end }} + {{- if or .CpuLimit .MemoryLimit }} + limits: + {{if .CpuLimit }}cpu: {{ .CpuLimit }}{{ end }} + {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} + {{- end }} + {{- end }} {{ if .SecurityContext }} securityContext: allowPrivilegeEscalation: true @@ -223,7 +236,19 @@ spec: image: {{ .Image }} name: {{ .Name }} imagePullPolicy: {{ .PullPolicy }} - resources: {} + {{- if or .CpuRequest .CpuLimit .MemoryRequest .MemoryLimit }} + resources: + {{- if or .CpuRequest .MemoryRequest }} + requests: + {{if .CpuRequest }}cpu: {{ .CpuRequest }}{{ end }} + {{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }} + {{- end }} + {{- if or .CpuLimit .MemoryLimit }} + limits: + {{if .CpuLimit }}cpu: {{ .CpuLimit }}{{ end }} + {{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }} + {{- end }} + {{- end }} {{ if .SecurityContext }} securityContext: allowPrivilegeEscalation: true @@ -261,6 +286,8 @@ var ( defaultDeploymentName = "testDeployment" defaultConfigMapName = "testConfigMap" seccompPwdEPERM = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`) + // CPU Period in ms + defaultCPUPeriod = 100 ) func writeYaml(content string, fileName string) error { @@ -503,6 +530,10 @@ type Ctr struct { Image string Cmd []string Arg []string + CpuRequest string + CpuLimit string + MemoryRequest string + MemoryLimit string SecurityContext bool Caps bool CapAdd []string @@ -521,7 +552,25 @@ type Ctr struct { // getCtr takes a list of ctrOptions and returns a Ctr with sane defaults // and the configured options func getCtr(options ...ctrOption) *Ctr { - c := Ctr{defaultCtrName, defaultCtrImage, defaultCtrCmd, defaultCtrArg, true, false, nil, nil, "", "", "", false, "", "", false, []Env{}, []EnvFrom{}} + c := Ctr{ + Name: defaultCtrName, + Image: defaultCtrImage, + Cmd: defaultCtrCmd, + Arg: defaultCtrArg, + SecurityContext: true, + Caps: false, + CapAdd: nil, + CapDrop: nil, + PullPolicy: "", + HostIP: "", + Port: "", + VolumeMount: false, + VolumeMountPath: "", + VolumeName: "", + VolumeReadOnly: false, + Env: []Env{}, + EnvFrom: []EnvFrom{}, + } for _, option := range options { option(&c) } @@ -548,6 +597,30 @@ func withImage(img string) ctrOption { } } +func withCpuRequest(request string) ctrOption { + return func(c *Ctr) { + c.CpuRequest = request + } +} + +func withCpuLimit(limit string) ctrOption { + return func(c *Ctr) { + c.CpuLimit = limit + } +} + +func withMemoryRequest(request string) ctrOption { + return func(c *Ctr) { + c.MemoryRequest = request + } +} + +func withMemoryLimit(limit string) ctrOption { + return func(c *Ctr) { + c.MemoryLimit = limit + } +} + func withSecurityContext(sc bool) ctrOption { return func(c *Ctr) { c.SecurityContext = sc @@ -648,7 +721,12 @@ type EnvFrom struct { From string } -var _ = Describe("Podman generate kube", func() { +func milliCPUToQuota(milliCPU string) int { + milli, _ := strconv.Atoi(strings.Trim(milliCPU, "m")) + return milli * defaultCPUPeriod +} + +var _ = Describe("Podman play kube", func() { var ( tempdir string err error @@ -1324,4 +1402,49 @@ spec: Expect(inspect.OutputToString()).To(ContainSubstring(correctLabels)) } }) + + It("podman play kube allows setting resource limits", func() { + SkipIfContainerized("Resource limits require a running systemd") + SkipIfRootlessCgroupsV1("Limits require root or cgroups v2") + SkipIfUnprevilegedCPULimits() + podmanTest.CgroupManager = "systemd" + + var ( + numReplicas int32 = 3 + expectedCpuRequest string = "100m" + expectedCpuLimit string = "200m" + expectedMemoryRequest string = "10000000" + expectedMemoryLimit string = "20000000" + ) + + expectedCpuQuota := milliCPUToQuota(expectedCpuLimit) + + deployment := getDeployment( + withReplicas(numReplicas), + withPod(getPod(withCtr(getCtr( + withCpuRequest(expectedCpuRequest), + withCpuLimit(expectedCpuLimit), + withMemoryRequest(expectedMemoryRequest), + withMemoryLimit(expectedMemoryLimit), + ))))) + err := generateKubeYaml("deployment", deployment, kubeYaml) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + for _, pod := range getPodNamesInDeployment(deployment) { + inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", ` +CpuPeriod: {{ .HostConfig.CpuPeriod }} +CpuQuota: {{ .HostConfig.CpuQuota }} +Memory: {{ .HostConfig.Memory }} +MemoryReservation: {{ .HostConfig.MemoryReservation }}`}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(ContainSubstring(fmt.Sprintf("%s: %d", "CpuQuota", expectedCpuQuota))) + Expect(inspect.OutputToString()).To(ContainSubstring("MemoryReservation: " + expectedMemoryRequest)) + Expect(inspect.OutputToString()).To(ContainSubstring("Memory: " + expectedMemoryLimit)) + } + }) }) |