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/api/Makefile | 3 + pkg/api/handlers/libpod/containers.go | 5 -- pkg/api/handlers/swagger.go | 8 +- pkg/api/server/register_containers.go | 160 +++++++++++++++++++++++----------- pkg/api/server/register_images.go | 90 ++++++++++++++----- pkg/api/server/swagger.go | 6 +- pkg/api/tags.yaml | 13 +++ 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 +- 13 files changed, 421 insertions(+), 94 deletions(-) create mode 100644 pkg/api/Makefile create mode 100644 pkg/api/tags.yaml create mode 100644 pkg/bindings/connection.go create mode 100644 pkg/bindings/errors.go create mode 100644 pkg/bindings/images.go (limited to 'pkg') diff --git a/pkg/api/Makefile b/pkg/api/Makefile new file mode 100644 index 000000000..5fb4e7da5 --- /dev/null +++ b/pkg/api/Makefile @@ -0,0 +1,3 @@ +swagger: + swagger generate spec -o swagger.yaml -w ./ + cat tags.yaml >> swagger.yaml diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index ceb7460da..388be24b6 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -30,11 +30,6 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) { } func RemoveContainer(w http.ResponseWriter, r *http.Request) { - // 204 no error - // 400 bad param - // 404 no such container - // 409 conflict - // 500 internal error decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { Force bool `schema:"force"` diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go index b677a5a0b..c845c8195 100644 --- a/pkg/api/handlers/swagger.go +++ b/pkg/api/handlers/swagger.go @@ -57,9 +57,7 @@ type swagLibpodInspectImageResponse struct { // swagger:response DocsContainerPruneReport type swagContainerPruneReport struct { // in: body - Body struct { - ContainersPruneReport - } + Body []ContainersPruneReport } // Inspect container @@ -84,9 +82,7 @@ type swagDockerTopResponse struct { // swagger:response LibpodListContainersResponse type swagLibpodListContainersResponse struct { // in:body - Body struct { - shared.PsContainerOutput - } + Body []shared.PsContainerOutput } // Inspect container diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 95b986170..8b0b816cd 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -10,30 +10,34 @@ import ( ) func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { - // swagger:operation POST /containers/create containers createContainer + // swagger:operation POST /containers/create compat containerCreate // --- - // summary: Create a container - // produces: - // - application/json - // parameters: - // - in: query - // name: name - // type: string - // description: container name - // responses: - // '201': - // $ref: "#/responses/ContainerCreateResponse" - // '400': - // "$ref": "#/responses/BadParamError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '409': - // "$ref": "#/responses/ConflictError" - // '500': - // "$ref": "#/responses/InternalError" + // summary: Create a container + // tags: + // - containers (compat) + // produces: + // - application/json + // parameters: + // - in: query + // name: name + // type: string + // description: container name + // responses: + // '201': + // $ref: "#/responses/ContainerCreateResponse" + // '400': + // "$ref": "#/responses/BadParamError" + // '404': + // "$ref": "#/responses/NoSuchContainer" + // '409': + // "$ref": "#/responses/ConflictError" + // '500': + // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/create"), APIHandler(s.Context, generic.CreateContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/json containers listContainers + // swagger:operation GET /containers/json compat listContainers // --- + // tags: + // - containers (compat) // summary: List containers // description: Returns a list of containers // parameters: @@ -66,8 +70,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/json"), APIHandler(s.Context, generic.ListContainers)).Methods(http.MethodGet) - // swagger:operation POST /containers/prune containers pruneContainers + // swagger:operation POST /containers/prune compat pruneContainers // --- + // tags: + // - containers (compat) // summary: Delete stopped containers // description: Remove containers not in use // parameters: @@ -86,8 +92,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/prune"), APIHandler(s.Context, generic.PruneContainers)).Methods(http.MethodPost) - // swagger:operation DELETE /containers/{nameOrID} containers removeContainer + // swagger:operation DELETE /containers/{nameOrID} compat removeContainer // --- + // tags: + // - containers (compat) // summary: Remove a container // parameters: // - in: path @@ -122,8 +130,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}"), APIHandler(s.Context, generic.RemoveContainer)).Methods(http.MethodDelete) - // swagger:operation GET /containers/{nameOrID}/json containers getContainer + // swagger:operation GET /containers/{nameOrID}/json compat getContainer // --- + // tags: + // - containers (compat) // summary: Inspect container // description: Return low-level information about a container. // parameters: @@ -146,8 +156,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/json"), APIHandler(s.Context, generic.GetContainer)).Methods(http.MethodGet) - // swagger:operation post /containers/{nameOrID}/kill containers killcontainer + // swagger:operation post /containers/{nameOrID}/kill compat killcontainer // --- + // tags: + // - containers (compat) // summary: Kill container // description: Signal to send to the container as an integer or string (e.g. SIGINT) // parameters: @@ -171,8 +183,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/kill"), APIHandler(s.Context, generic.KillContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/{nameOrID}/logs containers LogsFromContainer + // swagger:operation GET /containers/{nameOrID}/logs compat LogsFromContainer // --- + // tags: + // - containers (compat) // summary: Get container logs // description: Get stdout and stderr logs from a container. // parameters: @@ -220,8 +234,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/logs"), APIHandler(s.Context, generic.LogsFromContainer)).Methods(http.MethodGet) - // swagger:operation POST /containers/{nameOrID}/pause containers pauseContainer + // swagger:operation POST /containers/{nameOrID}/pause compat pauseContainer // --- + // tags: + // - containers (compat) // summary: Pause container // description: Use the cgroups freezer to suspend all processes in a container. // parameters: @@ -240,8 +256,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/pause"), APIHandler(s.Context, handlers.PauseContainer)).Methods(http.MethodPost) r.HandleFunc(VersionedPath("/containers/{name:..*}/rename"), APIHandler(s.Context, handlers.UnsupportedHandler)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/restart containers restartContainer + // swagger:operation POST /containers/{nameOrID}/restart compat restartContainer // --- + // tags: + // - containers (compat) // summary: Restart container // parameters: // - in: path @@ -262,8 +280,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/start containers startContainer + // swagger:operation POST /containers/{nameOrID}/start compat startContainer // --- + // tags: + // - containers (compat) // summary: Start a container // parameters: // - in: path @@ -286,8 +306,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/{nameOrID}/stats containers statsContainer + // swagger:operation GET /containers/{nameOrID}/stats compat statsContainer // --- + // tags: + // - containers (compat) // summary: Get stats for a container // description: This returns a live stream of a container’s resource usage statistics. // parameters: @@ -310,8 +332,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet) - // swagger:operation POST /containers/{nameOrID}/stop containers stopContainer + // swagger:operation POST /containers/{nameOrID}/stop compat stopContainer // --- + // tags: + // - containers (compat) // summary: Stop a container // parameters: // - in: path @@ -334,8 +358,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/{nameOrID}/top containers topContainer + // swagger:operation GET /containers/{nameOrID}/top compat topContainer // --- + // tags: + // - containers (compat) // summary: List processes running inside a container // parameters: // - in: path @@ -356,8 +382,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet) - // swagger:operation POST /containers/{nameOrID}/unpause containers unpauseContainer + // swagger:operation POST /containers/{nameOrID}/unpause compat unpauseContainer // --- + // tags: + // - containers (compat) // summary: Unpause container // description: Resume a paused container // parameters: @@ -375,8 +403,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/{name:..*}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/wait containers waitContainer + // swagger:operation POST /containers/{nameOrID}/wait compat waitContainer // --- + // tags: + // - containers (compat) // summary: Wait on a container to exit // description: Block until a container stops, then returns the exit code. // parameters: @@ -404,8 +434,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { */ r.HandleFunc(VersionedPath("/libpod/containers/create"), APIHandler(s.Context, libpod.CreateContainer)).Methods(http.MethodPost) - // swagger:operation GET /libpod/containers/json containers libpodListContainers + // swagger:operation GET /libpod/containers/json libpod libpodListContainers // --- + // tags: + // - containers // summary: List containers // description: Returns a list of containers // produces: @@ -413,16 +445,16 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // responses: // '200': // schema: - // type: array - // items: // "$ref": "#/responses/LibpodListContainersResponse" // '400': // "$ref": "#/responses/BadParamError" // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/json"), APIHandler(s.Context, libpod.ListContainers)).Methods(http.MethodGet) - // swagger:operation POST /libpod/containers/prune containers libpodPruneContainers + // swagger:operation POST /libpod/containers/prune libpod libpodPruneContainers // --- + // tags: + // - containers // summary: Prune unused containers // description: Remove stopped and exited containers // parameters: @@ -445,8 +477,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/prune"), APIHandler(s.Context, libpod.PruneContainers)).Methods(http.MethodPost) - // swagger:operation GET /libpod/containers/showmounted containers showMounterContainers + // swagger:operation GET /libpod/containers/showmounted libpod showMounterContainers // --- + // tags: + // - containers // summary: Show mounted containers // description: Lists all mounted containers mount points // produces: @@ -461,8 +495,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/showmounted"), APIHandler(s.Context, libpod.ShowMountedContainers)).Methods(http.MethodGet) - // swagger:operation DELETE /libpod/containers/json containers libpodRemoveContainer + // swagger:operation DELETE /libpod/containers/json libpod libpodRemoveContainer // --- + // tags: + // - containers // summary: Delete container // parameters: // - in: path @@ -491,8 +527,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}"), APIHandler(s.Context, libpod.RemoveContainer)).Methods(http.MethodDelete) - // swagger:operation GET /libpod/containers/{nameOrID}/json containers libpodGetContainer + // swagger:operation GET /libpod/containers/{nameOrID}/json libpod libpodGetContainer // --- + // tags: + // - containers // summary: Inspect container // description: Return low-level information about a container. // parameters: @@ -514,8 +552,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/json"), APIHandler(s.Context, libpod.GetContainer)).Methods(http.MethodGet) - // swagger:operation POST /libpod/containers/{nameOrID}/kill containers libpodKillContainer + // swagger:operation POST /libpod/containers/{nameOrID}/kill libpod libpodKillContainer // --- + // tags: + // - containers // summary: Kill container // description: send a signal to a container, defaults to killing the container // parameters: @@ -540,8 +580,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/kill"), APIHandler(s.Context, libpod.KillContainer)).Methods(http.MethodGet) - // swagger:operation GET /libpod/containers/{nameOrID}/mount containers mountContainer + // swagger:operation GET /libpod/containers/{nameOrID}/mount libpod mountContainer // --- + // tags: + // - containers // summary: Mount a container // description: Mount a container to the filesystem // parameters: @@ -564,8 +606,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/mount"), APIHandler(s.Context, libpod.MountContainer)).Methods(http.MethodPost) r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/logs"), APIHandler(s.Context, libpod.LogsFromContainer)).Methods(http.MethodGet) - // swagger:operation POST /libpod/containers/{nameOrID}/pause containers libpodPauseContainer + // swagger:operation POST /libpod/containers/{nameOrID}/pause libpod libpodPauseContainer // --- + // tags: + // - containers // summary: Pause a container // description: Use the cgroups freezer to suspend all processes in a container. // parameters: @@ -583,8 +627,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/pause"), APIHandler(s.Context, handlers.PauseContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{nameOrID}/restart containers libpodRestartContainer + // swagger:operation POST /libpod/containers/{nameOrID}/restart libpod libpodRestartContainer // --- + // tags: + // - containers // summary: Restart a container // parameters: // - in: path @@ -605,8 +651,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{nameOrID}/start containers libpodStartContainer + // swagger:operation POST /libpod/containers/{nameOrID}/start libpod libpodStartContainer // --- + // tags: + // - containers // summary: Start a container // parameters: // - in: path @@ -629,8 +677,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost) - // swagger:operation GET /libpod/containers/{nameOrID}/stats containers statsContainer + // swagger:operation GET /libpod/containers/{nameOrID}/stats libpod statsContainer // --- + // tags: + // - containers // summary: Get stats for a container // description: This returns a live stream of a container’s resource usage statistics. // parameters: @@ -654,8 +704,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet) r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet) - // swagger:operation POST /libpod/containers/{nameOrID}/unpause containers libpodUnpauseContainer + // swagger:operation POST /libpod/containers/{nameOrID}/unpause libpod libpodUnpauseContainer // --- + // tags: + // - containers // summary: Unpause Container // parameters: // - in: path @@ -672,8 +724,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{nameOrID}/wait containers libpodWaitContainer + // swagger:operation POST /libpod/containers/{nameOrID}/wait libpod libpodWaitContainer // --- + // tags: + // - containers // summary: Wait on a container to exit // parameters: // - in: path @@ -694,8 +748,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/wait"), APIHandler(s.Context, libpod.WaitContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{nameOrID}/exists containers containerExists + // swagger:operation POST /libpod/containers/{nameOrID}/exists libpod containerExists // --- + // tags: + // - containers // summary: Check if container exists // description: Quick way to determine if a container exists by name or ID // parameters: @@ -713,8 +769,10 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/exists"), APIHandler(s.Context, libpod.ContainerExists)).Methods(http.MethodGet) - // swagger:operation POST /libpod/containers/{nameOrID}/stop containers libpodStopContainer + // swagger:operation POST /libpod/containers/{nameOrID}/stop libpod libpodStopContainer // --- + // tags: + // - containers // summary: Stop a container // parameters: // - in: path diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 916534fc7..cd42afe71 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -10,9 +10,11 @@ import ( ) func (s *APIServer) registerImagesHandlers(r *mux.Router) error { - // swagger:operation POST /images/create compat_images createImage + // swagger:operation POST /images/create compat createImage // // --- + // tags: + // - images (compat) // summary: Create an image from an image // description: Create an image by either pulling it from a registry or importing it. // produces: @@ -40,8 +42,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // schema: // $ref: '#/responses/GenericError' r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromImage)).Methods(http.MethodPost).Queries("fromImage", "{fromImage}") - // swagger:operation POST /images/create compat_images createImage + // swagger:operation POST /images/create compat createImage // --- + // tags: + // - images (compat) // summary: Create an image from Source // description: Create an image by either pulling it from a registry or importing it. // produces: @@ -69,8 +73,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // schema: // $ref: '#/responses/GenericError' r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromSrc)).Methods(http.MethodPost).Queries("fromSrc", "{fromSrc}") - // swagger:operation GET /images/json compat_images listImages + // swagger:operation GET /images/json compat listImages // --- + // tags: + // - images (compat) // summary: List Images // description: Returns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image. // produces: @@ -85,9 +91,11 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/json"), APIHandler(s.Context, generic.GetImages)).Methods(http.MethodGet) - // swagger:operation POST /images/load compat_images loadImage + // swagger:operation POST /images/load compat loadImage // // --- + // tags: + // - images (compat) // summary: Import image // description: Load a set of images and tags into a repository. // parameters: @@ -107,8 +115,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost) - // swagger:operation POST /images/prune compat_images pruneImages + // swagger:operation POST /images/prune compat pruneImages // --- + // tags: + // - images (compat) // summary: Prune unused images // description: Remove images from local storage that are not being used by a container // parameters: @@ -132,8 +142,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/prune"), APIHandler(s.Context, generic.PruneImages)).Methods(http.MethodPost) - // swagger:operation GET /images/search compat_images searchImages + // swagger:operation GET /images/search compat searchImages // --- + // tags: + // - images (compat) // summary: Search images // description: Search registries for an image // parameters: @@ -161,8 +173,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet) - // swagger:operation DELETE /images/{nameOrID} compat_images removeImage + // swagger:operation DELETE /images/{nameOrID} compat removeImage // --- + // tags: + // - images (compat) // summary: Remove Image // description: Delete an image from local storage // parameters: @@ -186,8 +200,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/{name:..*}"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete) - // swagger:operation GET /images/{nameOrID}/get compat_images exportImage + // swagger:operation GET /images/{nameOrID}/get compat exportImage // --- + // tags: + // - images (compat) // summary: Export an image // description: Export an image in tarball format // parameters: @@ -206,8 +222,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/{name:..*}/get"), APIHandler(s.Context, generic.ExportImage)).Methods(http.MethodGet) - // swagger:operation GET /images/{nameOrID}/history compat_images imageHistory + // swagger:operation GET /images/{nameOrID}/history compat imageHistory // --- + // tags: + // - images (compat) // summary: History of an image // description: Return parent layers of an image. // parameters: @@ -225,8 +243,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/images/{name:..*}/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet) - // swagger:operation GET /images/{nameOrID}/json compat_images inspectImage + // swagger:operation GET /images/{nameOrID}/json compat inspectImage // --- + // tags: + // - images (compat) // summary: Inspect an image // description: Return low-level information about an image. // parameters: @@ -244,8 +264,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/images/{name:..*}/json"), APIHandler(s.Context, generic.GetImage)) - // swagger:operation POST /images/{nameOrID}/tag compat_images tagImage + // swagger:operation POST /images/{nameOrID}/tag compat tagImage // --- + // tags: + // - images (compat) // summary: Tag an image // description: Tag an image so that it becomes part of a repository. // parameters: @@ -275,8 +297,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/{name:..*}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost) - // swagger:operation POST /commit/ compat_commit commitContainer + // swagger:operation POST /commit/ compat commitContainer // --- + // tags: + // - commit (compat) // summary: Create a new image from a container // parameters: // - in: query @@ -322,8 +346,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { libpod endpoints */ - // swagger:operation POST /libpod/images/{nameOrID}/exists images libpodImageExists + // swagger:operation POST /libpod/images/{nameOrID}/exists libpod libpodImageExists // --- + // tags: + // - images // summary: Image exists // description: Check if image exists in local store // parameters: @@ -342,8 +368,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/{name:..*}/exists"), APIHandler(s.Context, libpod.ImageExists)) r.Handle(VersionedPath("/libpod/images/{name:..*}/tree"), APIHandler(s.Context, libpod.ImageTree)) - // swagger:operation GET /libpod/images/{nameOrID}/history images libpodImageHistory + // swagger:operation GET /libpod/images/{nameOrID}/history libpod libpodImageHistory // --- + // tags: + // - images // summary: History of an image // description: Return parent layers of an image. // parameters: @@ -363,22 +391,24 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet) - // swagger:operation GET /libpod/images/json images libpodListImages + // swagger:operation GET /libpod/images/json libpod libpodListImages // --- + // tags: + // - images // summary: List Images // description: Returns a list of images on the server // produces: // - application/json // responses: // '200': - // schema: - // items: // $ref: "#/responses/DockerImageSummary" // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/json"), APIHandler(s.Context, libpod.GetImages)).Methods(http.MethodGet) - // swagger:operation POST /libpod/images/load images libpodLoadImage + // swagger:operation POST /libpod/images/load libpod libpodLoadImage // --- + // tags: + // - images // summary: Import image // description: Load a set of images and tags into a repository. // parameters: @@ -398,8 +428,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost) - // swagger:operation POST /libpod/images/prune images libpodPruneImages + // swagger:operation POST /libpod/images/prune libpod libpodPruneImages // --- + // tags: + // - images // summary: Prune unused images // description: Remove images that are not being used by a container // parameters: @@ -426,8 +458,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/prune"), APIHandler(s.Context, libpod.PruneImages)).Methods(http.MethodPost) - // swagger:operation GET /libpod/images/search images libpodSearchImages + // swagger:operation GET /libpod/images/search libpod libpodSearchImages // --- + // tags: + // - images // summary: Search images // description: Search registries for images // parameters: @@ -457,8 +491,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet) - // swagger:operation DELETE /libpod/images/{nameOrID} images libpodRemoveImage + // swagger:operation DELETE /libpod/images/{nameOrID} libpod libpodRemoveImage // --- + // tags: + // - images // summary: Remove Image // description: Delete an image from local store // parameters: @@ -482,8 +518,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/{name:..*}"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete) - // swagger:operation GET /libpod/images/{nameOrID}/get images libpoodExportImage + // swagger:operation GET /libpod/images/{nameOrID}/get libpod libpoodExportImage // --- + // tags: + // - images // summary: Export an image // description: Export an image as a tarball // parameters: @@ -512,8 +550,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/{name:..*}/get"), APIHandler(s.Context, libpod.ExportImage)).Methods(http.MethodGet) - // swagger:operation GET /libpod/images/{nameOrID}/json images libpodInspectImage + // swagger:operation GET /libpod/images/{nameOrID}/json libpod libpodInspectImage // --- + // tags: + // - images // summary: Inspect an image // description: Obtain low-level information about an image // parameters: @@ -531,8 +571,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // '500': // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/{name:..*}/json"), APIHandler(s.Context, libpod.GetImage)) - // swagger:operation POST /libpod/images/{nameOrID}/tag images libpodTagImage + // swagger:operation POST /libpod/images/{nameOrID}/tag libpod libpodTagImage // --- + // tags: + // - images // summary: Tag an image // description: Tag an image so that it becomes part of a repository. // parameters: diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go index 95129e637..dbf499ce7 100644 --- a/pkg/api/server/swagger.go +++ b/pkg/api/server/swagger.go @@ -117,9 +117,7 @@ type swagPodAlreadyStopped struct { // swagger:response DockerImageSummary type swagImageSummary struct { // in:body - Body struct { - handlers.ImageSummary - } + Body []handlers.ImageSummary } // List Containers @@ -128,7 +126,7 @@ type swagListContainers struct { // in:body Body struct { // This causes go-swagger to crash - //handlers.Container + // handlers.Container } } diff --git a/pkg/api/tags.yaml b/pkg/api/tags.yaml new file mode 100644 index 000000000..ad0de656f --- /dev/null +++ b/pkg/api/tags.yaml @@ -0,0 +1,13 @@ +tags: + - name: containers + description: Actions related to containers + - name: images + description: Actions related to images + - name: pods + description: Actions related to pods + - name: volumes + description: Actions related to volumes + - name: containers (compat) + description: Actions related to containers for the compatibility endpoints + - name: images (compat) + description: Actions related to images for the compatibility endpoints 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