From a6ea17455cb0c7bdc3d250e57e20d6dc9f5df45d Mon Sep 17 00:00:00 2001 From: baude Date: Wed, 15 Jan 2020 12:28:46 -0600 Subject: [CI:DOCS]swagger cleanup and left-hand nav add a static tags file so we can dictate the left-hand navigation. in doing so we now override the tag in the swagger:operation. we now have images and images (compat) as a way to differentiate. Signed-off-by: baude --- pkg/bindings/connection.go | 62 +++++++++++++++++++++++++ pkg/bindings/containers.go | 6 ++- pkg/bindings/errors.go | 46 +++++++++++++++++++ pkg/bindings/images.go | 111 +++++++++++++++++++++++++++++++++++++++++++++ pkg/bindings/pods.go | 3 +- pkg/bindings/volumes.go | 2 +- 6 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 pkg/bindings/connection.go create mode 100644 pkg/bindings/errors.go create mode 100644 pkg/bindings/images.go (limited to 'pkg/bindings') diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go new file mode 100644 index 000000000..551a63c62 --- /dev/null +++ b/pkg/bindings/connection.go @@ -0,0 +1,62 @@ +package bindings + +import ( + "fmt" + "io" + "net/http" +) + +const ( + defaultConnection string = "http://localhost:8080/v1.24/libpod" + pingConnection string = "http://localhost:8080/_ping" +) + +type APIResponse struct { + *http.Response + Request *http.Request +} + +type Connection struct { + url string + client *http.Client +} + +func NewConnection(url string) (Connection, error) { + if len(url) < 1 { + url = defaultConnection + } + newConn := Connection{ + url: url, + client: &http.Client{}, + } + response, err := http.Get(pingConnection) + if err != nil { + return newConn, err + } + if err := response.Body.Close(); err != nil { + return newConn, err + } + return newConn, err +} + +func (c Connection) makeEndpoint(u string) string { + return fmt.Sprintf("%s%s", defaultConnection, u) +} + +func (c Connection) newRequest(httpMethod, endpoint string, httpBody io.Reader, params map[string]string) (*APIResponse, error) { + e := c.makeEndpoint(endpoint) + req, err := http.NewRequest(httpMethod, e, httpBody) + if err != nil { + return nil, err + } + if len(params) > 0 { + // if more desirable we could use url to form the encoded endpoint with params + r := req.URL.Query() + for k, v := range params { + r.Add(k, v) + } + req.URL.RawQuery = r.Encode() + } + response, err := c.client.Do(req) // nolint + return &APIResponse{response, req}, err +} diff --git a/pkg/bindings/containers.go b/pkg/bindings/containers.go index cd0b09767..01f68f970 100644 --- a/pkg/bindings/containers.go +++ b/pkg/bindings/containers.go @@ -109,12 +109,14 @@ func (c Connection) UnpauseContainer(nameOrID string) error { } func (c Connection) WaitContainer(nameOrID string) error { - _, err := http.Post(c.makeEndpoint(fmt.Sprintf("containers/%s/wait", nameOrID)), "application/json", nil) + // TODO when returns are ironed out, we can should use the newRequest approach + _, err := http.Post(c.makeEndpoint(fmt.Sprintf("containers/%s/wait", nameOrID)), "application/json", nil) // nolint return err } func (c Connection) ContainerExists(nameOrID string) (bool, error) { - response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/containers/%s/exists", nameOrID))) + response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/containers/%s/exists", nameOrID))) // nolint + defer closeResponseBody(response) if err != nil { return false, err } diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go new file mode 100644 index 000000000..9a02925a3 --- /dev/null +++ b/pkg/bindings/errors.go @@ -0,0 +1,46 @@ +package bindings + +import ( + "encoding/json" + "io/ioutil" + "net/http" + + "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +var ( + ErrNotImplemented = errors.New("function not implemented") +) + +func handleError(data []byte) error { + e := utils.ErrorModel{} + if err := json.Unmarshal(data, &e); err != nil { + return err + } + return e +} + +func (a APIResponse) Process(unmarshalInto interface{}) error { + data, err := ioutil.ReadAll(a.Response.Body) + if err != nil { + return errors.Wrap(err, "unable to process API response") + } + if a.Response.StatusCode == http.StatusOK { + if unmarshalInto != nil { + return json.Unmarshal(data, unmarshalInto) + } + return nil + } + // TODO should we add a debug here with the response code? + return handleError(data) +} + +func closeResponseBody(r *http.Response) { + if r != nil { + if err := r.Body.Close(); err != nil { + logrus.Error(errors.Wrap(err, "unable to close response body")) + } + } +} diff --git a/pkg/bindings/images.go b/pkg/bindings/images.go new file mode 100644 index 000000000..3abc8c372 --- /dev/null +++ b/pkg/bindings/images.go @@ -0,0 +1,111 @@ +package bindings + +import ( + "fmt" + "io" + "net/http" + "strconv" + + "github.com/containers/libpod/pkg/api/handlers" + "github.com/containers/libpod/pkg/inspect" +) + +func (c Connection) ImageExists(nameOrID string) (bool, error) { + response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/images/%s/exists", nameOrID))) // nolint + defer closeResponseBody(response) + if err != nil { + return false, err + } + if response.StatusCode == http.StatusOK { + return true, nil + } + return false, nil +} + +func (c Connection) ListImages() ([]handlers.ImageSummary, error) { + imageSummary := []handlers.ImageSummary{} + response, err := c.newRequest(http.MethodGet, "/images/json", nil, nil) + if err != nil { + return imageSummary, err + } + return imageSummary, response.Process(&imageSummary) +} + +func (c Connection) GetImage(nameOrID string) (*inspect.ImageData, error) { + inspectedData := inspect.ImageData{} + response, err := c.newRequest(http.MethodGet, fmt.Sprintf("/images/%s/json", nameOrID), nil, nil) + if err != nil { + return &inspectedData, err + } + return &inspectedData, response.Process(&inspectedData) +} + +func (c Connection) ImageTree(nameOrId string) error { + return ErrNotImplemented +} + +func (c Connection) ImageHistory(nameOrID string) ([]handlers.HistoryResponse, error) { + history := []handlers.HistoryResponse{} + response, err := c.newRequest(http.MethodGet, fmt.Sprintf("/images/%s/history", nameOrID), nil, nil) + if err != nil { + return history, err + } + return history, response.Process(&history) +} + +func (c Connection) LoadImage(r io.Reader) error { + // TODO this still needs error handling added + _, err := http.Post(c.makeEndpoint("/images/loads"), "application/json", r) //nolint + return err +} + +func (c Connection) RemoveImage(nameOrID string, force bool) ([]map[string]string, error) { + deletes := []map[string]string{} + params := make(map[string]string) + params["force"] = strconv.FormatBool(force) + response, err := c.newRequest(http.MethodDelete, fmt.Sprintf("/images/%s", nameOrID), nil, params) + if err != nil { + return nil, err + } + return deletes, response.Process(&deletes) +} + +func (c Connection) ExportImage(nameOrID string, w io.Writer, format string, compress bool) error { + params := make(map[string]string) + params["format"] = format + params["compress"] = strconv.FormatBool(compress) + response, err := c.newRequest(http.MethodGet, fmt.Sprintf("/images/%s/get", nameOrID), nil, params) + if err != nil { + return err + } + if err := response.Process(nil); err != nil { + return err + } + _, err = io.Copy(w, response.Body) + return err +} + +func (c Connection) PruneImages(all bool, filters []string) ([]string, error) { + var ( + deleted []string + ) + params := make(map[string]string) + // FIXME How do we do []strings? + //params["filters"] = format + response, err := c.newRequest(http.MethodPost, "/images/prune", nil, params) + if err != nil { + return deleted, err + } + return deleted, response.Process(nil) +} + +func (c Connection) TagImage(nameOrID string) error { + var () + response, err := c.newRequest(http.MethodPost, fmt.Sprintf("/images/%s/tag", nameOrID), nil, nil) + if err != nil { + return err + } + return response.Process(nil) +} + +func (c Connection) BuildImage(nameOrId string) {} diff --git a/pkg/bindings/pods.go b/pkg/bindings/pods.go index eac9d2ef5..704d71477 100644 --- a/pkg/bindings/pods.go +++ b/pkg/bindings/pods.go @@ -14,7 +14,8 @@ func (c Connection) CreatePod() error { } func (c Connection) PodExists(nameOrID string) (bool, error) { - response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/pods/%s/exists", nameOrID))) + response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/pods/%s/exists", nameOrID))) // nolint + defer closeResponseBody(response) if err != nil { return false, err } diff --git a/pkg/bindings/volumes.go b/pkg/bindings/volumes.go index 27e6f9efa..219f924e7 100644 --- a/pkg/bindings/volumes.go +++ b/pkg/bindings/volumes.go @@ -52,7 +52,7 @@ func (c Connection) PruneVolumes() ([]string, error) { func (c Connection) RemoveVolume(nameOrID string, force bool) error { params := make(map[string]string) params["force"] = strconv.FormatBool(force) - response, err := c.newRequest(http.MethodPost, fmt.Sprintf("/volumes/prune", nameOrID), nil, params) + response, err := c.newRequest(http.MethodPost, "/volumes/prune", nil, params) if err != nil { return err } -- cgit v1.2.3-54-g00ecf