From 08bb9317cbd1a00b4dd52bc3409699271351403d Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Fri, 14 Feb 2020 12:11:23 -0600 Subject: add caching for binding tests add the ability to cache images instead of pull them. makes tests faster and less network use when we flip on CI. Also added list images with filter test Signed-off-by: Brent Baude --- pkg/api/handlers/utils/images.go | 9 +++-- pkg/bindings/test/common_test.go | 76 +++++++++++++++++++++++++++++++++++++--- pkg/bindings/test/images_test.go | 65 ++++++++++++++++++++-------------- 3 files changed, 117 insertions(+), 33 deletions(-) (limited to 'pkg') diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index 2b651584a..d0dfbf3ab 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -31,9 +31,12 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) { if _, found := mux.Vars(r)["digests"]; found && query.Digests { UnSupportedParameter("digests") } - - if _, found := r.URL.Query()["filters"]; found { - filters = append(filters, fmt.Sprintf("reference=%s", "")) + if len(query.Filters) > 0 { + for k, v := range query.Filters { + for _, val := range v { + filters = append(filters, fmt.Sprintf("%s=%s", k, val)) + } + } } return runtime.ImageRuntime().GetImagesWithFilters(filters) } diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go index 22cd0b7e0..dba94cb35 100644 --- a/pkg/bindings/test/common_test.go +++ b/pkg/bindings/test/common_test.go @@ -13,10 +13,30 @@ import ( "github.com/pkg/errors" ) +type testImage struct { + name string + shortName string + tarballName string +} + const ( defaultPodmanBinaryLocation string = "/usr/bin/podman" - alpine string = "docker.io/library/alpine:latest" - busybox string = "docker.io/library/busybox:latest" +) + +var ( + ImageCacheDir = "/tmp/podman/imagecachedir" + LockTmpDir string + alpine = testImage{ + name: "docker.io/library/alpine:latest", + shortName: "alpine", + tarballName: "alpine.tar", + } + busybox = testImage{ + name: "docker.io/library/busybox:latest", + shortName: "busybox", + tarballName: "busybox.tar", + } + CACHE_IMAGES = []testImage{alpine, busybox} ) type bindingTest struct { @@ -109,7 +129,7 @@ func (b *bindingTest) startAPIService() *gexec.Session { var ( cmd []string ) - cmd = append(cmd, "--log-level=debug", "service", "--timeout=999999", b.sock) + cmd = append(cmd, "--log-level=debug", "system", "service", "--timeout=999999", b.sock) return b.runPodman(cmd) } @@ -127,6 +147,21 @@ func (b *bindingTest) Pull(name string) { p.Wait(45) } +func (b *bindingTest) Save(i testImage) { + p := b.runPodman([]string{"save", "-o", filepath.Join(ImageCacheDir, i.tarballName), i.name}) + p.Wait(45) +} + +func (b *bindingTest) RestoreImagesFromCache() { + for _, i := range CACHE_IMAGES { + b.restoreImageFromCache(i) + } +} +func (b *bindingTest) restoreImageFromCache(i testImage) { + p := b.runPodman([]string{"load", "-i", filepath.Join(ImageCacheDir, i.tarballName), i.name}) + p.Wait(45) +} + // Run a container and add append the alpine image to it func (b *bindingTest) RunTopContainer(name *string) { cmd := []string{"run", "-dt"} @@ -134,7 +169,7 @@ func (b *bindingTest) RunTopContainer(name *string) { containerName := *name cmd = append(cmd, "--name", containerName) } - cmd = append(cmd, alpine, "top") + cmd = append(cmd, alpine.name, "top") p := b.runPodman(cmd) p.Wait(45) } @@ -149,3 +184,36 @@ func StringInSlice(s string, sl []string) bool { } return false } + +var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { + // make cache dir + if err := os.MkdirAll(ImageCacheDir, 0777); err != nil { + fmt.Printf("%q\n", err) + os.Exit(1) + } + + // If running localized tests, the cache dir is created and populated. if the + // tests are remote, this is a no-op + createCache() + path, err := ioutil.TempDir("", "libpodlock") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return []byte(path) +}, func(data []byte) { + LockTmpDir = string(data) +}) + +func createCache() { + b := newBindingTest() + for _, i := range CACHE_IMAGES { + _, err := os.Stat(filepath.Join(ImageCacheDir, i.tarballName)) + if os.IsNotExist(err) { + // pull the image + b.Pull(i.name) + b.Save(i) + } + } + b.cleanup() +} diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go index fea611601..74e0cc67a 100644 --- a/pkg/bindings/test/images_test.go +++ b/pkg/bindings/test/images_test.go @@ -2,6 +2,7 @@ package test_bindings import ( "context" + "net/http" "time" "github.com/containers/libpod/pkg/bindings" @@ -34,8 +35,7 @@ var _ = Describe("Podman images", func() { //podmanTest.Setup() //podmanTest.SeedImages() bt = newBindingTest() - bt.Pull(alpine) - bt.Pull(busybox) + bt.RestoreImagesFromCache() s = bt.startAPIService() time.Sleep(1 * time.Second) connText, err = bindings.NewConnection(bt.sock) @@ -54,10 +54,10 @@ var _ = Describe("Podman images", func() { _, err = images.GetImage(connText, "foobar5000", nil) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) // Inspect by short name - data, err := images.GetImage(connText, "alpine", nil) + data, err := images.GetImage(connText, alpine.shortName, nil) Expect(err).To(BeNil()) // Inspect with full ID @@ -68,10 +68,9 @@ var _ = Describe("Podman images", func() { _, err = images.GetImage(connText, data.ID[0:12], nil) Expect(err).To(BeNil()) - // The test to inspect by long name needs to fixed. - // Inspect by long name should work, it doesnt (yet) i think it needs to be html escaped - // _, err = images.GetImage(connText, alpine, nil) - // Expect(err).To(BeNil()) + // Inspect by long name + _, err = images.GetImage(connText, alpine.name, nil) + Expect(err).To(BeNil()) }) // Test to validate the remove image api @@ -80,17 +79,17 @@ var _ = Describe("Podman images", func() { _, err = images.Remove(connText, "foobar5000", &falseFlag) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) // Remove an image by name, validate image is removed and error is nil - inspectData, err := images.GetImage(connText, "busybox", nil) + inspectData, err := images.GetImage(connText, busybox.shortName, nil) Expect(err).To(BeNil()) - response, err := images.Remove(connText, "busybox", nil) + response, err := images.Remove(connText, busybox.shortName, nil) Expect(err).To(BeNil()) Expect(inspectData.ID).To(Equal(response[0]["Deleted"])) - inspectData, err = images.GetImage(connText, "busybox", nil) + inspectData, err = images.GetImage(connText, busybox.shortName, nil) code, _ = bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) // Start a container with alpine image var top string = "top" @@ -102,38 +101,38 @@ var _ = Describe("Podman images", func() { // try to remove the image "alpine". This should fail since we are not force // deleting hence image cannot be deleted until the container is deleted. - response, err = images.Remove(connText, "alpine", &falseFlag) + response, err = images.Remove(connText, alpine.shortName, &falseFlag) code, _ = bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 500)) + Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) // Removing the image "alpine" where force = true - response, err = images.Remove(connText, "alpine", &trueFlag) + response, err = images.Remove(connText, alpine.shortName, &trueFlag) Expect(err).To(BeNil()) // Checking if both the images are gone as well as the container is deleted - inspectData, err = images.GetImage(connText, "busybox", nil) + inspectData, err = images.GetImage(connText, busybox.shortName, nil) code, _ = bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) - inspectData, err = images.GetImage(connText, "alpine", nil) + inspectData, err = images.GetImage(connText, alpine.shortName, nil) code, _ = bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) _, err = containers.Inspect(connText, "top", &falseFlag) code, _ = bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) }) // Tests to validate the image tag command. It("tag image", func() { // Validates if invalid image name is given a bad response is encountered. - err = images.Tag(connText, "dummy", "demo", "alpine") + err = images.Tag(connText, "dummy", "demo", alpine.shortName) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", 404)) + Expect(code).To(BeNumerically("==", http.StatusNotFound)) // Validates if the image is tagged sucessfully. - err = images.Tag(connText, "alpine", "demo", "alpine") + err = images.Tag(connText, alpine.shortName, "demo", alpine.shortName) Expect(err).To(BeNil()) //Validates if name updates when the image is retagged. @@ -164,8 +163,22 @@ var _ = Describe("Podman images", func() { for _, i := range imageSummary { names = append(names, i.RepoTags...) } - Expect(StringInSlice(alpine, names)).To(BeTrue()) - Expect(StringInSlice(busybox, names)).To(BeTrue()) + Expect(StringInSlice(alpine.name, names)).To(BeTrue()) + Expect(StringInSlice(busybox.name, names)).To(BeTrue()) + + // List images with a filter + filters := make(map[string][]string) + filters["reference"] = []string{alpine.name} + filteredImages, err := images.List(connText, &falseFlag, filters) + Expect(err).To(BeNil()) + Expect(len(filteredImages)).To(BeNumerically("==", 1)) + + // List images with a bad filter + filters["name"] = []string{alpine.name} + _, err = images.List(connText, &falseFlag, filters) + Expect(err).ToNot(BeNil()) + code, _ := bindings.CheckResponseCode(err) + Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) }) }) -- cgit v1.2.3-54-g00ecf