summaryrefslogtreecommitdiff
path: root/pkg/bindings
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2020-02-21 12:32:42 -0600
committerBrent Baude <bbaude@redhat.com>2020-02-21 16:11:39 -0600
commitf0df07b5931b256b0ddadb80a8357985038cfe26 (patch)
tree5bc5132d488fe285d64d6b517d587a8c68ea38cd /pkg/bindings
parentf51cf8546d17c68f5ade1b4c8558d120c583316e (diff)
downloadpodman-f0df07b5931b256b0ddadb80a8357985038cfe26.tar.gz
podman-f0df07b5931b256b0ddadb80a8357985038cfe26.tar.bz2
podman-f0df07b5931b256b0ddadb80a8357985038cfe26.zip
add more image tests for go bindings
adding more image tests for go bindings. one big change is that the params were converted from map[string]string to url.values to account for the ability to send []string as query params Signed-off-by: Brent Baude <bbaude@redhat.com>
Diffstat (limited to 'pkg/bindings')
-rw-r--r--pkg/bindings/connection.go9
-rw-r--r--pkg/bindings/containers/containers.go45
-rw-r--r--pkg/bindings/images/images.go82
-rw-r--r--pkg/bindings/images/search.go9
-rw-r--r--pkg/bindings/pods/pods.go17
-rw-r--r--pkg/bindings/test/common_test.go13
-rw-r--r--pkg/bindings/test/images_test.go112
-rw-r--r--pkg/bindings/volumes/volumes.go5
8 files changed, 226 insertions, 66 deletions
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 75f1fc6a5..ba5f9c3aa 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -206,7 +206,7 @@ func unixClient(_url *url.URL) (*http.Client, error) {
}
// DoRequest assembles the http request and returns the response
-func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, queryParams map[string]string, pathValues ...string) (*APIResponse, error) {
+func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, queryParams url.Values, pathValues ...string) (*APIResponse, error) {
var (
err error
response *http.Response
@@ -225,12 +225,7 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
return nil, err
}
if len(queryParams) > 0 {
- // if more desirable we could use url to form the encoded endpoint with params
- r := req.URL.Query()
- for k, v := range queryParams {
- r.Add(k, v)
- }
- req.URL.RawQuery = r.Encode()
+ req.URL.RawQuery = queryParams.Encode()
}
// Give the Do three chances in the case of a comm/service hiccup
for i := 0; i < 3; i++ {
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index a437e9a9b..2985787a6 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -3,6 +3,7 @@ package containers
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod"
@@ -21,28 +22,28 @@ func List(ctx context.Context, filters map[string][]string, all *bool, last *int
return nil, err
}
var containers []lpapiv2.ListContainer
- params := make(map[string]string)
+ params := url.Values{}
if all != nil {
- params["all"] = strconv.FormatBool(*all)
+ params.Set("all", strconv.FormatBool(*all))
}
if last != nil {
- params["last"] = strconv.Itoa(*last)
+ params.Set("last", strconv.Itoa(*last))
}
if pod != nil {
- params["pod"] = strconv.FormatBool(*pod)
+ params.Set("pod", strconv.FormatBool(*pod))
}
if size != nil {
- params["size"] = strconv.FormatBool(*size)
+ params.Set("size", strconv.FormatBool(*size))
}
if sync != nil {
- params["sync"] = strconv.FormatBool(*sync)
+ params.Set("sync", strconv.FormatBool(*sync))
}
if filters != nil {
filterString, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = filterString
+ params.Set("filters", filterString)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/json", params)
if err != nil {
@@ -63,13 +64,13 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if filters != nil {
filterString, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = filterString
+ params.Set("filters", filterString)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/prune", params)
if err != nil {
@@ -86,12 +87,12 @@ func Remove(ctx context.Context, nameOrID string, force, volumes *bool) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
if volumes != nil {
- params["vols"] = strconv.FormatBool(*volumes)
+ params.Set("vols", strconv.FormatBool(*volumes))
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/containers/%s", params, nameOrID)
if err != nil {
@@ -109,9 +110,9 @@ func Inspect(ctx context.Context, nameOrID string, size *bool) (*libpod.InspectC
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if size != nil {
- params["size"] = strconv.FormatBool(*size)
+ params.Set("size", strconv.FormatBool(*size))
}
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/json", params, nameOrID)
if err != nil {
@@ -129,8 +130,8 @@ func Kill(ctx context.Context, nameOrID string, signal string) error {
if err != nil {
return err
}
- params := make(map[string]string)
- params["signal"] = signal
+ params := url.Values{}
+ params.Set("signal", signal)
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/kill", params, nameOrID)
if err != nil {
return err
@@ -162,9 +163,9 @@ func Restart(ctx context.Context, nameOrID string, timeout *int) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if timeout != nil {
- params["t"] = strconv.Itoa(*timeout)
+ params.Set("t", strconv.Itoa(*timeout))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restart", params, nameOrID)
if err != nil {
@@ -181,9 +182,9 @@ func Start(ctx context.Context, nameOrID string, detachKeys *string) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if detachKeys != nil {
- params["detachKeys"] = *detachKeys
+ params.Set("detachKeys", *detachKeys)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/start", params, nameOrID)
if err != nil {
@@ -242,13 +243,13 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
// Stop stops a running container. The timeout is optional. The nameOrID can be a container name
// or a partial/full ID
func Stop(ctx context.Context, nameOrID string, timeout *int) error {
- params := make(map[string]string)
+ params := url.Values{}
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
if timeout != nil {
- params["t"] = strconv.Itoa(*timeout)
+ params.Set("t", strconv.Itoa(*timeout))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/stop", params, nameOrID)
if err != nil {
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 271d58952..c84aa4601 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -2,8 +2,10 @@ package images
import (
"context"
+ "errors"
"io"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/pkg/api/handlers"
@@ -33,16 +35,16 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*handl
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if all != nil {
- params["all"] = strconv.FormatBool(*all)
+ params.Set("all", strconv.FormatBool(*all))
}
if filters != nil {
strFilters, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = strFilters
+ params.Set("filters", strFilters)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params)
if err != nil {
@@ -58,9 +60,9 @@ func GetImage(ctx context.Context, nameOrID string, size *bool) (*inspect.ImageD
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if size != nil {
- params["size"] = strconv.FormatBool(*size)
+ params.Set("size", strconv.FormatBool(*size))
}
inspectedData := inspect.ImageData{}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID)
@@ -88,15 +90,21 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse,
return history, response.Process(&history)
}
-func Load(ctx context.Context, r io.Reader) error {
+func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
+ var id handlers.IDResponse
conn, err := bindings.GetClient(ctx)
if err != nil {
- return err
+ return "", err
}
- // TODO this still needs error handling added
- //_, err := http.Post(c.makeEndpoint("/images/loads"), "application/json", r) //nolint
- _ = conn
- return bindings.ErrNotImplemented
+ params := url.Values{}
+ if name != nil {
+ params.Set("reference", *name)
+ }
+ response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
+ if err != nil {
+ return "", err
+ }
+ return id.ID, response.Process(&id)
}
// Remove deletes an image from local storage. The optional force parameter will forcibly remove
@@ -107,9 +115,9 @@ func Remove(ctx context.Context, nameOrID string, force *bool) ([]map[string]str
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/images/%s", params, nameOrID)
if err != nil {
@@ -125,12 +133,12 @@ func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, c
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if format != nil {
- params["format"] = *format
+ params.Set("format", *format)
}
if compress != nil {
- params["compress"] = strconv.FormatBool(*compress)
+ params.Set("compress", strconv.FormatBool(*compress))
}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nameOrID)
if err != nil {
@@ -153,13 +161,13 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if filters != nil {
stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = stringFilter
+ params.Set("filters", stringFilter)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params)
if err != nil {
@@ -174,9 +182,9 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error {
if err != nil {
return err
}
- params := make(map[string]string)
- params["tag"] = tag
- params["repo"] = repo
+ params := url.Values{}
+ params.Set("tag", tag)
+ params.Set("repo", repo)
response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nameOrID)
if err != nil {
return err
@@ -185,3 +193,35 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error {
}
func Build(nameOrId string) {}
+
+// Imports adds the given image to the local image store. This can be done by file and the given reader
+// or via the url parameter. Additional metadata can be associated with the image by using the changes and
+// message parameters. The image can also be tagged given a reference. One of url OR r must be provided.
+func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (string, error) {
+ var id handlers.IDResponse
+ if r != nil && u != nil {
+ return "", errors.New("url and r parameters cannot be used together")
+ }
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return "", err
+ }
+ params := url.Values{}
+ for _, change := range changes {
+ params.Add("changes", change)
+ }
+ if message != nil {
+ params.Set("message", *message)
+ }
+ if reference != nil {
+ params.Set("reference", *reference)
+ }
+ if u != nil {
+ params.Set("url", *u)
+ }
+ response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params)
+ if err != nil {
+ return "", err
+ }
+ return id.ID, response.Process(&id)
+}
diff --git a/pkg/bindings/images/search.go b/pkg/bindings/images/search.go
index dca1b0e63..183ff3d77 100644
--- a/pkg/bindings/images/search.go
+++ b/pkg/bindings/images/search.go
@@ -3,6 +3,7 @@ package images
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod/image"
@@ -20,17 +21,17 @@ func Search(ctx context.Context, term string, limit *int, filters map[string][]s
if err != nil {
return nil, err
}
- params := make(map[string]string)
- params["term"] = term
+ params := url.Values{}
+ params.Set("term", term)
if limit != nil {
- params["limit"] = strconv.Itoa(*limit)
+ params.Set("limit", strconv.Itoa(*limit))
}
if filters != nil {
stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = stringFilter
+ params.Set("filters", stringFilter)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params)
if err != nil {
diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go
index 838b22e43..1a8c31be1 100644
--- a/pkg/bindings/pods/pods.go
+++ b/pkg/bindings/pods/pods.go
@@ -3,6 +3,7 @@ package pods
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod"
@@ -48,9 +49,9 @@ func Kill(ctx context.Context, nameOrID string, signal *string) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if signal != nil {
- params["signal"] = *signal
+ params.Set("signal", *signal)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/kill", params, nameOrID)
if err != nil {
@@ -95,13 +96,13 @@ func List(ctx context.Context, filters map[string][]string) ([]*libpod.PodInspec
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if filters != nil {
stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = stringFilter
+ params.Set("filters", stringFilter)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/pods/json", params)
if err != nil {
@@ -130,9 +131,9 @@ func Remove(ctx context.Context, nameOrID string, force *bool) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s", params, nameOrID)
if err != nil {
@@ -166,9 +167,9 @@ func Stop(ctx context.Context, nameOrID string, timeout *int) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if timeout != nil {
- params["t"] = strconv.Itoa(*timeout)
+ params.Set("t", strconv.Itoa(*timeout))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/stop", params, nameOrID)
if err != nil {
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index 98d64bbaa..38f5014ca 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -20,9 +20,18 @@ type testImage struct {
}
const (
+ devPodmanBinaryLocation string = "../../../bin/podman"
defaultPodmanBinaryLocation string = "/usr/bin/podman"
)
+func getPodmanBinary() string {
+ _, err := os.Stat(devPodmanBinaryLocation)
+ if os.IsNotExist(err) {
+ return defaultPodmanBinaryLocation
+ }
+ return devPodmanBinaryLocation
+}
+
var (
ImageCacheDir = "/tmp/podman/imagecachedir"
LockTmpDir string
@@ -50,7 +59,7 @@ type bindingTest struct {
func (b *bindingTest) runPodman(command []string) *gexec.Session {
var cmd []string
- podmanBinary := defaultPodmanBinaryLocation
+ podmanBinary := getPodmanBinary()
val, ok := os.LookupEnv("PODMAN_BINARY")
if ok {
podmanBinary = val
@@ -166,7 +175,7 @@ func (b *bindingTest) restoreImageFromCache(i testImage) {
// and add or append the alpine image to it
func (b *bindingTest) RunTopContainer(containerName *string, insidePod *bool, podName *string) {
cmd := []string{"run", "-dt"}
- if *insidePod && podName != nil {
+ if insidePod != nil && podName != nil {
pName := *podName
cmd = append(cmd, "--pod", pName)
} else if containerName != nil {
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index 0b51c8c9e..c51ce4a32 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -3,6 +3,8 @@ package test_bindings
import (
"context"
"net/http"
+ "os"
+ "path/filepath"
"time"
"github.com/containers/libpod/pkg/bindings"
@@ -71,6 +73,14 @@ var _ = Describe("Podman images", func() {
// Inspect by long name
_, err = images.GetImage(connText, alpine.name, nil)
Expect(err).To(BeNil())
+ // TODO it looks like the images API alwaays returns size regardless
+ // of bool or not. What should we do ?
+ //Expect(data.Size).To(BeZero())
+
+ // Enabling the size parameter should result in size being populated
+ data, err = images.GetImage(connText, alpine.name, &trueFlag)
+ Expect(err).To(BeNil())
+ Expect(data.Size).To(BeNumerically(">", 0))
})
// Test to validate the remove image api
@@ -181,4 +191,106 @@ var _ = Describe("Podman images", func() {
Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
})
+ It("Image Exists", func() {
+ // exists on bogus image should be false, with no error
+ exists, err := images.Exists(connText, "foobar")
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+
+ // exists with shortname should be true
+ exists, err = images.Exists(connText, alpine.shortName)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // exists with fqname should be true
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+ })
+
+ It("Load|Import Image", func() {
+ // load an image
+ _, err := images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err := images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ f, err := os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ defer f.Close()
+ Expect(err).To(BeNil())
+ names, err := images.Load(connText, f, nil)
+ Expect(err).To(BeNil())
+ Expect(names).To(Equal(alpine.name))
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // load with a repo name
+ f, err = os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ Expect(err).To(BeNil())
+ _, err = images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ newName := "quay.io/newname:fizzle"
+ names, err = images.Load(connText, f, &newName)
+ Expect(err).To(BeNil())
+ Expect(names).To(Equal(alpine.name))
+ exists, err = images.Exists(connText, newName)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // load with a bad repo name should trigger a 500
+ f, err = os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ Expect(err).To(BeNil())
+ _, err = images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ badName := "quay.io/newName:fizzle"
+ _, err = images.Load(connText, f, &badName)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("Export Image", func() {
+ // Export an image
+ exportPath := filepath.Join(bt.tempDirPath, alpine.tarballName)
+ w, err := os.Create(filepath.Join(bt.tempDirPath, alpine.tarballName))
+ defer w.Close()
+ Expect(err).To(BeNil())
+ err = images.Export(connText, alpine.name, w, nil, nil)
+ Expect(err).To(BeNil())
+ _, err = os.Stat(exportPath)
+ Expect(err).To(BeNil())
+
+ // TODO how do we verify that a format change worked?
+ })
+
+ It("Import Image", func() {
+ // load an image
+ _, err = images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err := images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ f, err := os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ defer f.Close()
+ Expect(err).To(BeNil())
+ changes := []string{"CMD /bin/foobar"}
+ testMessage := "test_import"
+ _, err = images.Import(connText, changes, &testMessage, &alpine.name, nil, f)
+ Expect(err).To(BeNil())
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+ data, err := images.GetImage(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ Expect(data.Comment).To(Equal(testMessage))
+
+ })
+
})
diff --git a/pkg/bindings/volumes/volumes.go b/pkg/bindings/volumes/volumes.go
index 8313a7460..7f6a9cc9b 100644
--- a/pkg/bindings/volumes/volumes.go
+++ b/pkg/bindings/volumes/volumes.go
@@ -3,6 +3,7 @@ package volumes
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod"
@@ -73,9 +74,9 @@ func Remove(ctx context.Context, nameOrID string, force *bool) error {
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/%s/prune", params, nameOrID)
if err != nil {