func (b *LinuxBackend) ApplyLimits(container garden.Container, limits garden.Limits) error { if limits.CPU != (garden.CPULimits{}) { if err := container.LimitCPU(limits.CPU); err != nil { return err } } if limits.Disk != (garden.DiskLimits{}) { if err := container.LimitDisk(limits.Disk); err != nil { return err } } if limits.Bandwidth != (garden.BandwidthLimits{}) { if err := container.LimitBandwidth(limits.Bandwidth); err != nil { return err } } if limits.Memory != (garden.MemoryLimits{}) { if err := container.LimitMemory(limits.Memory); err != nil { return err } } return nil }
ghttp.CombineHandlers( ghttp.VerifyRequest("POST", "/api/containers/containerhandle/memory_limit"), ghttp.RespondWith(200, `{}`), func(w http.ResponseWriter, req *http.Request) { body, err := ioutil.ReadAll(req.Body) req.Body.Close() Expect(err).ShouldNot(HaveOccurred()) requestBody = string(body) }, ), ) }) It("sets limits on the container", func() { limit := garden.MemoryLimits{LimitInBytes: 555} err := container.LimitMemory(limit) Expect(err).NotTo(HaveOccurred()) Expect(server.ReceivedRequests()).Should(HaveLen(1)) Expect(requestBody).Should(Equal(`{"limit_in_bytes":555}`)) }) }) Context("Containerizer returns non 200", func() { BeforeEach(func() { server.AppendHandlers( ghttp.CombineHandlers( ghttp.VerifyRequest("POST", "/api/containers/containerhandle/memory_limit"), ghttp.RespondWith(500, "{}"), ), )
BeforeEach(func() { fakeConnection.LimitDiskReturns(garden.DiskLimits{}, disaster) }) It("returns the error", func() { err := container.LimitDisk(garden.DiskLimits{}) Ω(err).Should(Equal(disaster)) }) }) }) Describe("LimitMemory", func() { It("sends a limit bandwidth request", func() { err := container.LimitMemory(garden.MemoryLimits{ LimitInBytes: 1, }) Ω(err).ShouldNot(HaveOccurred()) handle, limits := fakeConnection.LimitMemoryArgsForCall(0) Ω(handle).Should(Equal("some-handle")) Ω(limits).Should(Equal(garden.MemoryLimits{LimitInBytes: 1})) }) Context("when the request fails", func() { disaster := errors.New("oh no!") BeforeEach(func() { fakeConnection.LimitMemoryReturns(garden.MemoryLimits{}, disaster) })
err := client.Destroy(container.Handle()) Expect(err).ShouldNot(HaveOccurred()) }) It("is enforced when changed at creation", func() { container = createContainer(garden.ContainerSpec{ Limits: garden.Limits{ Memory: garden.MemoryLimits{64 * 1024 * 1024}, }, }) AssertMemoryLimits(container) }) It("is enforced when changed dynamically", func() { container = createDefaultContainer() err := container.LimitMemory(garden.MemoryLimits{64 * 1024 * 1024}) Expect(err).ShouldNot(HaveOccurred()) AssertMemoryLimits(container) }) It("handles large limits", func() { container = createDefaultContainer() err := container.LimitMemory(garden.MemoryLimits{4 * 1024 * 1024 * 1024}) Expect(err).ShouldNot(HaveOccurred()) }) }) XDescribe("a cpu limit", func() { var containers [2]garden.Container
BeforeEach(func() { fakeContainer.CurrentBandwidthLimitsReturns(garden.BandwidthLimits{}, errors.New("oh no!")) }) It("fails", func() { _, err := container.CurrentBandwidthLimits() Ω(err).Should(HaveOccurred()) }) }) }) Describe("limiting memory", func() { setLimits := garden.MemoryLimits{1024} It("sets the container's memory limits", func() { err := container.LimitMemory(setLimits) Ω(err).ShouldNot(HaveOccurred()) Ω(fakeContainer.LimitMemoryArgsForCall(0)).Should(Equal(setLimits)) }) itResetsGraceTimeWhenHandling(func() { err := container.LimitMemory(setLimits) Ω(err).ShouldNot(HaveOccurred()) }) itFailsWhenTheContainerIsNotFound(func() error { return container.LimitMemory(garden.MemoryLimits{123}) }) Context("when limiting the memory fails", func() {