func CleanupGarden(gardenClient garden.Client) []error { containers, err := gardenClient.Containers(nil) Expect(err).NotTo(HaveOccurred()) fmt.Fprintf(ginkgo.GinkgoWriter, "cleaning up %d Garden containers", len(containers)) // even if containers fail to destroy, stop garden, but still report the // errors destroyContainerErrors := []error{} for _, container := range containers { info, _ := container.Info() fmt.Fprintf(ginkgo.GinkgoWriter, "cleaning up container %s (%s)", container.Handle(), info.ContainerPath) RETRY_LOOP: // try to Destroy the container up to 3 times for i := 0; i < 3; i++ { err := gardenClient.Destroy(container.Handle()) switch { case err == nil: // move on if Destroy succeeds break RETRY_LOOP case strings.Contains(err.Error(), "unknown handle"): // move on if container doesn't exist break RETRY_LOOP case strings.Contains(err.Error(), "container already being destroyed"): // move on if container is already being destroyed break RETRY_LOOP case i == 2: // record an error if Destroy failed 3 times destroyContainerErrors = append(destroyContainerErrors, err) default: // try Destroy again otherwise time.Sleep(50 * time.Millisecond) } } } return destroyContainerErrors }
func destroyContainers(gardenClient garden.Client, containersFetcher *executorContainers, logger lager.Logger) { logger.Info("executor-fetching-containers-to-destroy") containers, err := containersFetcher.Containers() if err != nil { logger.Fatal("executor-failed-to-get-containers", err) return } else { logger.Info("executor-fetched-containers-to-destroy", lager.Data{"num-containers": len(containers)}) } for _, container := range containers { logger.Info("executor-destroying-container", lager.Data{"container-handle": container.Handle()}) err := gardenClient.Destroy(container.Handle()) if err != nil { logger.Fatal("executor-failed-to-destroy-container", err, lager.Data{ "handle": container.Handle(), }) } else { logger.Info("executor-destroyed-stray-container", lager.Data{ "handle": container.Handle(), }) } } }
func cleanupContainers(client garden.Client) { containers, err := client.Containers(nil) if err != nil { panic(err) } for _, container := range containers { err = client.Destroy(container.Handle()) if err != nil { panic(err) } } listContainers(client) }
BeforeEach(func() { serverBackend.CreateReturns(nil, errors.New("oh no!")) }) It("returns an error", func() { _, err := apiClient.Create(garden.ContainerSpec{ Handle: "some-handle", }) Ω(err).Should(HaveOccurred()) }) }) }) Context("and the client sends a destroy request", func() { It("destroys the container", func() { err := apiClient.Destroy("some-handle") Ω(err).ShouldNot(HaveOccurred()) Ω(serverBackend.DestroyArgsForCall(0)).Should(Equal("some-handle")) }) Context("concurrent with other destroy requests", func() { var destroying chan struct{} BeforeEach(func() { destroying = make(chan struct{}) serverBackend.DestroyStub = func(string) error { close(destroying) time.Sleep(time.Second) return nil