Beispiel #1
0
func (g *Gardener) GraceTime(container garden.Container) time.Duration {
	property, ok := g.PropertyManager.Get(container.Handle(), GraceTimeKey)
	if !ok {
		return 0
	}

	var graceTime time.Duration
	_, err := fmt.Sscanf(property, "%d", &graceTime)
	if err != nil {
		return 0
	}

	return graceTime
}
func createAndStream(index int, b Benchmarker, archive string) {
	var handle string
	var ctr garden.Container
	var err error

	b.Time(fmt.Sprintf("stream-%d", index), func() {
		creationTime := b.Time(fmt.Sprintf("create-%d", index), func() {
			By("creating container " + strconv.Itoa(index))
			ctr, err = gardenClient.Create(garden.ContainerSpec{
				Limits: garden.Limits{
					Disk: garden.DiskLimits{ByteHard: 2 * 1024 * 1024 * 1024},
				},
				Privileged: true,
			})
			Expect(err).ToNot(HaveOccurred())
			handle = ctr.Handle()
			By("done creating container " + strconv.Itoa(index))
		})
		now := time.Now()
		emitMetric(map[string]interface{}{
			"series": []map[string]interface{}{
				{
					"metric": "garden.container-creation-time",
					"points": [][]int64{
						{now.Unix(), int64(creationTime)},
					},
					"tags": []string{"deployment:" + os.Getenv("ENVIRONMENT") + "-garden"},
				},
			},
		})

		By("starting stream in to container " + handle)

		streamin(ctr, archive)

		By("succefully streamed in to container " + handle)

		b.Time(fmt.Sprintf("delete-%d", index), func() {
			By("destroying container " + handle)
			Expect(gardenClient.Destroy(handle)).To(Succeed())
			By("successfully destroyed container " + handle)
		})
	})
}
func streamin(ctr garden.Container, archive string) {
	for i := 0; i < 20; i++ {
		By(fmt.Sprintf("preparing stream %d for handle %s", i, ctr.Handle()))
		// Stream in a tar file to ctr
		var tarStream io.Reader

		pwd, err := os.Getwd()
		Expect(err).ToNot(HaveOccurred())
		tgzPath := path.Join(pwd, archive)
		tgz, err := os.Open(tgzPath)
		Expect(err).ToNot(HaveOccurred())
		tarStream, err = gzip.NewReader(tgz)
		Expect(err).ToNot(HaveOccurred())

		By(fmt.Sprintf("starting stream %d for handle: %s", i, ctr.Handle()))
		Expect(ctr.StreamIn(garden.StreamInSpec{
			User:      "******",
			Path:      fmt.Sprintf("/root/stream-file-%d", i),
			TarStream: tarStream,
		})).To(Succeed())
		By(fmt.Sprintf("stream %d done for handle: %s", i, ctr.Handle()))

		tgz.Close()
	}
}
Beispiel #4
0
	BeforeEach(func() {
		container = nil
		args = []string{}
	})

	JustBeforeEach(func() {
		if supplyDefaultRootfs {
			client = startGarden(args...)
		} else {
			client = startGardenWithoutDefaultRootfs(args...)
		}
	})

	AfterEach(func() {
		if container != nil {
			Expect(client.Destroy(container.Handle())).To(Succeed())
		}
	})

	Context("without a default rootfs", func() {
		BeforeEach(func() {
			supplyDefaultRootfs = false
		})

		It("fails if a rootfs is not supplied in container spec", func() {
			var err error

			container, err = client.Create(garden.ContainerSpec{RootFSPath: ""})
			Expect(err).To(HaveOccurred())
			Expect(err).To(MatchError(ContainSubstring("RootFSPath: is a required parameter, since no default rootfs was provided to the server.")))
		})
Beispiel #5
0
			Expect(err).NotTo(HaveOccurred())

			process, err := container.Run(garden.ProcessSpec{
				Path: "sh",
				Args: []string{"-c", `
					while true; do
						echo 'sleeping'
					  sleep 1
					done
				`},
			}, garden.ProcessIO{})

			Expect(err).NotTo(HaveOccurred())

			processID = process.ID()
			hostProcessDir := filepath.Join(client.DepotDir, container.Handle(), "processes", processID)
			hostPidFilePath := filepath.Join(hostProcessDir, "pidfile")

			// Finds the pid on the host.
			pidBytes, err := ioutil.ReadFile(hostPidFilePath)
			Expect(err).NotTo(HaveOccurred())

			Expect(client.Stop()).To(Succeed())

			pid, err := strconv.Atoi(string(pidBytes))
			Expect(err).NotTo(HaveOccurred())

			hostProcess, err := os.FindProcess(pid)
			Expect(err).NotTo(HaveOccurred())

			Expect(hostProcess.Kill()).To(Succeed())
Beispiel #6
0
				Expect(string(out)).NotTo(MatchRegexp(fmt.Sprintf("%sinstance.*", interfacePrefix)))
			})

			It("destroys the remaining containers' bridges", func() {
				out, err := exec.Command("ifconfig").CombinedOutput()
				Expect(err).NotTo(HaveOccurred())

				pattern := fmt.Sprintf(".*w%d%s.*", GinkgoParallelNode(), subnetName)
				Expect(string(out)).NotTo(MatchRegexp(pattern))
			})

			It("kills the container processes", func() {
				processes, err := exec.Command("ps", "aux").CombinedOutput()
				Expect(err).NotTo(HaveOccurred())

				Expect(string(processes)).NotTo(ContainSubstring(fmt.Sprintf("run runc /tmp/test-garden-%d/containers/%s", GinkgoParallelNode(), container.Handle())))
			})

			Context("when the garden server does not shut down gracefully", func() {
				BeforeEach(func() {
					gracefulShutdown = false
				})

				It("destroys orphaned containers' iptables filter rules", func() {
					out, err := exec.Command("iptables", "-w", "-S", "-t", "filter").CombinedOutput()
					Expect(err).NotTo(HaveOccurred())
					Expect(string(out)).NotTo(MatchRegexp(fmt.Sprintf("%sinstance.*", interfacePrefix)))
				})

				It("destroys orphaned containers' iptables nat rules", func() {
					out, err := exec.Command("iptables", "-w", "-S", "-t", "nat").CombinedOutput()
	})

	JustBeforeEach(func() {
		var err error

		client := New(fakeConnection)

		fakeConnection.CreateReturns("some-handle", nil)

		container, err = client.Create(garden.ContainerSpec{})
		Ω(err).ShouldNot(HaveOccurred())
	})

	Describe("Handle", func() {
		It("returns the container's handle", func() {
			Ω(container.Handle()).Should(Equal("some-handle"))
		})
	})

	Describe("Stop", func() {
		It("sends a stop request", func() {
			err := container.Stop(true)
			Ω(err).ShouldNot(HaveOccurred())

			handle, kill := fakeConnection.StopArgsForCall(0)
			Ω(handle).Should(Equal("some-handle"))
			Ω(kill).Should(BeTrue())
		})

		Context("when stopping fails", func() {
			disaster := errors.New("oh no!")
Beispiel #8
0
		info, err := container.Info()
		Expect(err).NotTo(HaveOccurred())
		Expect(info.State).To(Equal("active"))
	})

	It("can return the network information", func() {
		info, err := container.Info()
		Expect(err).NotTo(HaveOccurred())
		Expect(info.ContainerIP).To(Equal("10.252.0.2"))
		Expect(info.HostIP).To(Equal("10.252.0.1"))
	})

	It("can return the container path", func() {
		info, err := container.Info()
		Expect(err).NotTo(HaveOccurred())
		Expect(info.ContainerPath).To(Equal(path.Join(client.DepotDir, container.Handle())))
	})

	It("can return the list of properties", func() {
		Expect(container.SetProperty("abc", "xyz")).To(Succeed())

		info, err := container.Info()
		Expect(err).NotTo(HaveOccurred())

		Expect(info.Properties).To(HaveKeyWithValue("foo", "bar"))
		Expect(info.Properties).To(HaveKeyWithValue("abc", "xyz"))
	})

	It("can return port mappings", func() {
		hostPort, containerPort, err := container.NetIn(0, 0)
		Expect(err).NotTo(HaveOccurred())
Beispiel #9
0
		var itRemovesTheNetworkBridge = func() {
			It("should remove the network bridge", func() {
				session, err := gexec.Start(
					exec.Command("ip", "link", "show", networkBridgeName),
					GinkgoWriter, GinkgoWriter,
				)
				Expect(err).NotTo(HaveOccurred())

				session.Wait()
				Expect(session.ExitCode()).NotTo(Equal(0))
			})
		}

		Context("when destroy is called", func() {
			JustBeforeEach(func() {
				Expect(client.Destroy(container.Handle())).To(Succeed())
			})

			itCleansUpPerContainerNetworkingResources()
			itRemovesTheNetworkBridge()

			Context("and there was more than one containers in the same subnet", func() {
				var otherContainer garden.Container

				JustBeforeEach(func() {
					var err error

					otherContainer, err = client.Create(garden.ContainerSpec{
						Network: networkSpec,
					})
					Expect(err).NotTo(HaveOccurred())
Beispiel #10
0
	Context("after creating a container without a specified handle", func() {
		var (
			privileged bool

			initProcPid int
		)

		JustBeforeEach(func() {
			var err error
			container, err = client.Create(garden.ContainerSpec{
				Privileged: privileged,
			})
			Expect(err).NotTo(HaveOccurred())

			initProcPid = initProcessPID(container.Handle())
		})

		It("should create a depot subdirectory based on the container handle", func() {
			Expect(container.Handle()).NotTo(BeEmpty())
			Expect(filepath.Join(client.DepotDir, container.Handle())).To(BeADirectory())
			Expect(filepath.Join(client.DepotDir, container.Handle(), "config.json")).To(BeARegularFile())
		})

		It("should lookup the right container", func() {
			lookupContainer, lookupError := client.Lookup(container.Handle())

			Expect(lookupError).NotTo(HaveOccurred())
			Expect(lookupContainer).To(Equal(container))
		})
		Context("when destroying other containers on the same subnet", func() {
			It("should continue to route traffic successfully", func() {
				var (
					err            error
					googleDNSIP    string
					otherContainer garden.Container
				)

				googleDNSIP = "8.8.8.8"
				for i := 0; i < 5; i++ {
					otherContainer, err = gardenClient.Create(garden.ContainerSpec{
						Network: networkSpec,
					})
					Expect(err).NotTo(HaveOccurred())

					Expect(gardenClient.Destroy(otherContainer.Handle())).To(Succeed())
					Expect(checkConnection(container, googleDNSIP, 53)).To(Succeed())
				}
			})
		})

		Context("when creating a container in a previously used subnet", func() {
			var newContainer garden.Container

			JustBeforeEach(func() {
				var err error

				Expect(gardenClient.Destroy(container.Handle())).To(Succeed())

				newContainer, err = gardenClient.Create(garden.ContainerSpec{
					Network: networkSpec,
					SrcPath: srcPath,
					DstPath: dstPath,
					Mode:    bindMountMode,
					Origin:  bindMountOrigin,
				}},
				Network: fmt.Sprintf("10.0.%d.0/24", GinkgoParallelNode()),
			})
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		err := os.RemoveAll(srcPath)
		Expect(err).ToNot(HaveOccurred())

		if container != nil {
			err := client.Destroy(container.Handle())
			Expect(err).ToNot(HaveOccurred())
		}

		Expect(client.DestroyAndStop()).To(Succeed())
	})

	Context("which is read-only", func() {
		BeforeEach(func() {
			bindMountMode = garden.BindMountModeRO
			dstPath = "/home/alice/readonly"
		})

		Context("and with privileged=true", func() {
			BeforeEach(func() {
				privilegedContainer = true
Beispiel #13
0
func (s *GardenServer) reapContainer(container garden.Container) {
	s.logger.Info("reaping", lager.Data{
		"handle":     container.Handle(),
		"grace-time": s.backend.GraceTime(container).String(),
	})

	s.destroysL.Lock()
	_, alreadyDestroying := s.destroys[container.Handle()]
	if !alreadyDestroying {
		s.destroys[container.Handle()] = struct{}{}
	}
	s.destroysL.Unlock()

	if alreadyDestroying {
		s.logger.Info("skipping reap due to concurrent delete request", lager.Data{
			"handle":     container.Handle(),
			"grace-time": s.backend.GraceTime(container).String(),
		})
		return
	}

	s.backend.Destroy(container.Handle())

	s.destroysL.Lock()
	delete(s.destroys, container.Handle())
	s.destroysL.Unlock()
}
			})
		})
	})

	Describe("multiple containers", func() {
		var extraContainer garden.Container

		BeforeEach(func() {
			var err error
			extraContainer, err = gardenClient.Create(garden.ContainerSpec{})
			Expect(err).ToNot(HaveOccurred())
		})

		AfterEach(func() {
			if extraContainer != nil {
				Expect(gardenClient.Destroy(extraContainer.Handle())).To(Succeed())
			}
		})

		It("should list all containers", func() {
			containers, err := gardenClient.Containers(garden.Properties{})
			Expect(err).ToNot(HaveOccurred())

			handles := []string{}
			for _, c := range containers {
				handles = append(handles, c.Handle())
			}

			Expect(handles).To(ContainElement(container.Handle()))
			Expect(handles).To(ContainElement(extraContainer.Handle()))
		})
Beispiel #15
0
	})

	Describe("a second container", func() {
		var otherContainer garden.Container

		JustBeforeEach(func() {
			var err error
			otherContainer, err = client.Create(garden.ContainerSpec{
				Network: containerNetwork,
			})

			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {
			Expect(client.Destroy(otherContainer.Handle())).To(Succeed())
		})

		It("should have the next IP address", func() {
			buffer := gbytes.NewBuffer()
			proc, err := otherContainer.Run(
				garden.ProcessSpec{
					Path: "ifconfig",
					User: "******",
				}, garden.ProcessIO{Stdout: buffer},
			)

			Expect(err).NotTo(HaveOccurred())
			Expect(proc.Wait()).To(Equal(0))

			Expect(buffer).To(gbytes.Say(ipAddress(containerNetwork, 3)))