diff options
Diffstat (limited to 'pkg')
30 files changed, 1318 insertions, 870 deletions
diff --git a/pkg/adapter/client.go b/pkg/adapter/client.go index da4670892..5774ebe72 100644 --- a/pkg/adapter/client.go +++ b/pkg/adapter/client.go @@ -57,7 +57,7 @@ func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) { // last resort is to make a socket connection with the default varlink address for root user } else { logrus.Debug("creating a varlink address based default root address") - remoteEndpoint, err = newSocketConnection(DefaultAddress) + remoteEndpoint, err = newSocketConnection(DefaultVarlinkAddress) } return } diff --git a/pkg/adapter/client_config.go b/pkg/adapter/client_config.go index 3559b16e3..8187b03b1 100644 --- a/pkg/adapter/client_config.go +++ b/pkg/adapter/client_config.go @@ -1,7 +1,10 @@ package adapter -// DefaultAddress is the default address of the varlink socket -const DefaultAddress = "unix:/run/podman/io.podman" +// DefaultAPIAddress is the default address of the REST socket +const DefaultAPIAddress = "unix:/run/podman/podman.sock" + +// DefaultVarlinkAddress is the default address of the varlink socket +const DefaultVarlinkAddress = "unix:/run/podman/io.podman" // EndpointType declares the type of server connection type EndpointType int diff --git a/pkg/api/Makefile b/pkg/api/Makefile index 3d70376df..f564b6516 100644 --- a/pkg/api/Makefile +++ b/pkg/api/Makefile @@ -1,5 +1,13 @@ +export GO111MODULE=off + SWAGGER_OUT ?= swagger.yaml -swagger: - swagger generate spec -o ${SWAGGER_OUT} -w ./ - cat tags.yaml >> swagger.yaml +validate: ${SWAGGER_OUT} + swagger validate ${SWAGGER_OUT} + +.PHONY: ${SWAGGER_OUT} +${SWAGGER_OUT}: + # generate doesn't remove file on error + rm -f ${SWAGGER_OUT} + swagger generate spec -o ${SWAGGER_OUT} -i tags.yaml -w ./ + diff --git a/pkg/api/handlers/handler.go b/pkg/api/handlers/handler.go index 2efeb1379..4f303f6ab 100644 --- a/pkg/api/handlers/handler.go +++ b/pkg/api/handlers/handler.go @@ -36,11 +36,11 @@ func getRuntime(r *http.Request) *libpod.Runtime { return r.Context().Value("runtime").(*libpod.Runtime) } -func getHeader(r *http.Request, k string) string { - return r.Header.Get(k) -} - -func hasHeader(r *http.Request, k string) bool { - _, found := r.Header[k] - return found -} +// func getHeader(r *http.Request, k string) string { +// return r.Header.Get(k) +// } +// +// func hasHeader(r *http.Request, k string) bool { +// _, found := r.Header[k] +// return found +// } diff --git a/pkg/api/handlers/images.go b/pkg/api/handlers/images.go index d4cddbfb2..b4acdc312 100644 --- a/pkg/api/handlers/images.go +++ b/pkg/api/handlers/images.go @@ -74,8 +74,25 @@ func TagImage(w http.ResponseWriter, r *http.Request) { } func RemoveImage(w http.ResponseWriter, r *http.Request) { + decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) + query := struct { + noPrune bool + }{ + // This is where you can override the golang default value for one of fields + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) + return + } + muxVars := mux.Vars(r) + if _, found := muxVars["noprune"]; found { + if query.noPrune { + utils.UnSupportedParameter("noprune") + } + } name := mux.Vars(r)["name"] newImage, err := runtime.ImageRuntime().NewFromLocal(name) if err != nil { diff --git a/pkg/api/handlers/images_build.go b/pkg/api/handlers/images_build.go index c7c746392..b29c45574 100644 --- a/pkg/api/handlers/images_build.go +++ b/pkg/api/handlers/images_build.go @@ -1,6 +1,7 @@ package handlers import ( + "bytes" "encoding/base64" "encoding/json" "fmt" @@ -9,58 +10,66 @@ import ( "net/http" "os" "path/filepath" + "strconv" "strings" "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/storage/pkg/archive" - log "github.com/sirupsen/logrus" + "github.com/gorilla/mux" ) func BuildImage(w http.ResponseWriter, r *http.Request) { authConfigs := map[string]AuthConfig{} - if hasHeader(r, "X-Registry-Config") { - registryHeader := getHeader(r, "X-Registry-Config") - authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(registryHeader)) + if hdr, found := r.Header["X-Registry-Config"]; found && len(hdr) > 0 { + authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(hdr[0])) if json.NewDecoder(authConfigsJSON).Decode(&authConfigs) != nil { - utils.BadRequest(w, "X-Registry-Config", registryHeader, json.NewDecoder(authConfigsJSON).Decode(&authConfigs)) + utils.BadRequest(w, "X-Registry-Config", hdr[0], json.NewDecoder(authConfigsJSON).Decode(&authConfigs)) return } } + if hdr, found := r.Header["Content-Type"]; found && len(hdr) > 0 { + if hdr[0] != "application/x-tar" { + utils.BadRequest(w, "Content-Type", hdr[0], + fmt.Errorf("Content-Type: %s is not supported. Should be \"application/x-tar\"", hdr[0])) + } + } + anchorDir, err := extractTarFile(r, w) if err != nil { utils.InternalServerError(w, err) return } - // defer os.RemoveAll(anchorDir) + defer os.RemoveAll(anchorDir) query := struct { - Dockerfile string `json:"dockerfile"` - Tag string `json:"t"` - ExtraHosts string `json:"extrahosts"` - Remote string `json:"remote"` - Quiet bool `json:"q"` - NoCache bool `json:"nocache"` - CacheFrom string `json:"cachefrom"` - Pull string `json:"pull"` - Rm bool `json:"rm"` - ForceRm bool `json:"forcerm"` - Memory int `json:"memory"` - MemSwap int `json:"memswap"` - CpuShares int `json:"cpushares"` - CpuSetCpus string `json:"cpusetcpus"` - CpuPeriod int `json:"cpuperiod"` - CpuQuota int `json:"cpuquota"` - BuildArgs string `json:"buildargs"` - ShmSize int `json:"shmsize"` - Squash bool `json:"squash"` - Labels string `json:"labels"` - NetworkMode string `json:"networkmode"` - Platform string `json:"platform"` - Target string `json:"target"` - Outputs string `json:"outputs"` + Dockerfile string `schema:"dockerfile"` + Tag string `schema:"t"` + ExtraHosts string `schema:"extrahosts"` + Remote string `schema:"remote"` + Quiet bool `schema:"q"` + NoCache bool `schema:"nocache"` + CacheFrom string `schema:"cachefrom"` + Pull bool `schema:"pull"` + Rm bool `schema:"rm"` + ForceRm bool `schema:"forcerm"` + Memory int64 `schema:"memory"` + MemSwap int64 `schema:"memswap"` + CpuShares uint64 `schema:"cpushares"` + CpuSetCpus string `schema:"cpusetcpus"` + CpuPeriod uint64 `schema:"cpuperiod"` + CpuQuota int64 `schema:"cpuquota"` + BuildArgs string `schema:"buildargs"` + ShmSize int `schema:"shmsize"` + Squash bool `schema:"squash"` + Labels string `schema:"labels"` + NetworkMode string `schema:"networkmode"` + Platform string `schema:"platform"` + Target string `schema:"target"` + Outputs string `schema:"outputs"` + Registry string `schema:"registry"` }{ Dockerfile: "Dockerfile", Tag: "", @@ -69,7 +78,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { Quiet: false, NoCache: false, CacheFrom: "", - Pull: "", + Pull: false, Rm: true, ForceRm: false, Memory: 0, @@ -86,6 +95,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { Platform: "", Target: "", Outputs: "", + Registry: "docker.io", } if err := decodeQuery(r, &query); err != nil { @@ -93,80 +103,121 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { return } - // Tag is the name with optional tag... - var name = query.Tag - var tag string + var ( + // Tag is the name with optional tag... + name = query.Tag + tag = "latest" + ) if strings.Contains(query.Tag, ":") { tokens := strings.SplitN(query.Tag, ":", 2) name = tokens[0] tag = tokens[1] } + if t, found := mux.Vars(r)["target"]; found { + name = t + } + var buildArgs = map[string]string{} - if found := hasVar(r, "buildargs"); found { - if err := json.Unmarshal([]byte(query.BuildArgs), &buildArgs); err != nil { - utils.BadRequest(w, "buildargs", query.BuildArgs, err) + if a, found := mux.Vars(r)["buildargs"]; found { + if err := json.Unmarshal([]byte(a), &buildArgs); err != nil { + utils.BadRequest(w, "buildargs", a, err) return } } // convert label formats var labels = []string{} - if hasVar(r, "labels") { + if l, found := mux.Vars(r)["labels"]; found { var m = map[string]string{} - if err := json.Unmarshal([]byte(query.Labels), &m); err != nil { - utils.BadRequest(w, "labels", query.Labels, err) + if err := json.Unmarshal([]byte(l), &m); err != nil { + utils.BadRequest(w, "labels", l, err) return } for k, v := range m { - labels = append(labels, fmt.Sprintf("%s=%v", k, v)) + labels = append(labels, k+"="+v) + } + } + + pullPolicy := buildah.PullIfMissing + if _, found := mux.Vars(r)["pull"]; found { + if query.Pull { + pullPolicy = buildah.PullAlways } } + // build events will be recorded here + var ( + buildEvents = []string{} + progress = bytes.Buffer{} + ) + buildOptions := imagebuildah.BuildOptions{ ContextDirectory: filepath.Join(anchorDir, "build"), - PullPolicy: 0, - Registry: "", - IgnoreUnrecognizedInstructions: false, + PullPolicy: pullPolicy, + Registry: query.Registry, + IgnoreUnrecognizedInstructions: true, Quiet: query.Quiet, - Isolation: 0, + Isolation: buildah.IsolationChroot, Runtime: "", RuntimeArgs: nil, TransientMounts: nil, - Compression: 0, + Compression: archive.Gzip, Args: buildArgs, Output: name, AdditionalTags: []string{tag}, - Log: nil, - In: nil, - Out: nil, - Err: nil, - SignaturePolicyPath: "", - ReportWriter: nil, - OutputFormat: "", - SystemContext: nil, - NamespaceOptions: nil, - ConfigureNetwork: 0, - CNIPluginPath: "", - CNIConfigDir: "", - IDMappingOptions: nil, - AddCapabilities: nil, - DropCapabilities: nil, - CommonBuildOpts: &buildah.CommonBuildOptions{}, - DefaultMountsFilePath: "", - IIDFile: "", - Squash: query.Squash, - Labels: labels, - Annotations: nil, - OnBuild: nil, - Layers: false, - NoCache: query.NoCache, - RemoveIntermediateCtrs: query.Rm, - ForceRmIntermediateCtrs: query.ForceRm, - BlobDirectory: "", - Target: query.Target, - Devices: nil, + Log: func(format string, args ...interface{}) { + buildEvents = append(buildEvents, fmt.Sprintf(format, args...)) + }, + In: nil, + Out: &progress, + Err: &progress, + SignaturePolicyPath: "", + ReportWriter: &progress, + OutputFormat: buildah.Dockerv2ImageManifest, + SystemContext: nil, + NamespaceOptions: nil, + ConfigureNetwork: 0, + CNIPluginPath: "", + CNIConfigDir: "", + IDMappingOptions: nil, + AddCapabilities: nil, + DropCapabilities: nil, + CommonBuildOpts: &buildah.CommonBuildOptions{ + AddHost: nil, + CgroupParent: "", + CPUPeriod: query.CpuPeriod, + CPUQuota: query.CpuQuota, + CPUShares: query.CpuShares, + CPUSetCPUs: query.CpuSetCpus, + CPUSetMems: "", + HTTPProxy: false, + Memory: query.Memory, + DNSSearch: nil, + DNSServers: nil, + DNSOptions: nil, + MemorySwap: query.MemSwap, + LabelOpts: nil, + SeccompProfilePath: "", + ApparmorProfile: "", + ShmSize: strconv.Itoa(query.ShmSize), + Ulimit: nil, + Volumes: nil, + }, + DefaultMountsFilePath: "", + IIDFile: "", + Squash: query.Squash, + Labels: labels, + Annotations: nil, + OnBuild: nil, + Layers: false, + NoCache: query.NoCache, + RemoveIntermediateCtrs: query.Rm, + ForceRmIntermediateCtrs: query.ForceRm, + BlobDirectory: "", + Target: query.Target, + Devices: nil, } id, _, err := getRuntime(r).Build(r.Context(), buildOptions, query.Dockerfile) @@ -179,17 +230,13 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { struct { Stream string `json:"stream"` }{ - Stream: fmt.Sprintf("Successfully built %s\n", id), + Stream: progress.String() + "\n" + + strings.Join(buildEvents, "\n") + + fmt.Sprintf("\nSuccessfully built %s\n", id), }) } func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) { - var ( - // length int64 - // n int64 - copyErr error - ) - // build a home for the request body anchorDir, err := ioutil.TempDir("", "libpod_builder") if err != nil { @@ -204,26 +251,14 @@ func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) { } defer tarBall.Close() - // if hasHeader(r, "Content-Length") { - // length, err := strconv.ParseInt(getHeader(r, "Content-Length"), 10, 64) - // if err != nil { - // return "", errors.New(fmt.Sprintf("Failed request: unable to parse Content-Length of '%s'", getHeader(r, "Content-Length"))) - // } - // n, copyErr = io.CopyN(tarBall, r.Body, length+1) - // } else { - _, copyErr = io.Copy(tarBall, r.Body) - // } + // Content-Length not used as too many existing API clients didn't honor it + _, err = io.Copy(tarBall, r.Body) r.Body.Close() - if copyErr != nil { + if err != nil { utils.InternalServerError(w, fmt.Errorf("failed Request: Unable to copy tar file from request body %s", r.RequestURI)) } - log.Debugf("Content-Length: %s", getVar(r, "Content-Length")) - - // if hasHeader(r, "Content-Length") && n != length { - // return "", errors.New(fmt.Sprintf("Failed request: Given Content-Length does not match file size %d != %d", n, length)) - // } _, _ = tarBall.Seek(0, 0) if err := archive.Untar(tarBall, buildDir, &archive.TarOptions{}); err != nil { diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 388be24b6..e16a4ea1f 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -143,6 +143,22 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { } +func UnmountContainer(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + name := mux.Vars(r)["name"] + conn, err := runtime.LookupContainer(name) + if err != nil { + utils.ContainerNotFound(w, name, err) + return + } + // TODO In future it might be an improvement that libpod unmount return a + // "container not mounted" error so we can surface that to the endpoint user + if err := conn.Unmount(false); err != nil { + utils.InternalServerError(w, err) + } + utils.WriteResponse(w, http.StatusNoContent, "") + +} func MountContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) name := mux.Vars(r)["name"] diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index daaf9d018..14f8e8de7 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -12,6 +12,7 @@ import ( "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/containers/libpod/pkg/util" "github.com/gorilla/mux" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -384,18 +385,27 @@ func PodKill(w http.ResponseWriter, r *http.Request) { var ( runtime = r.Context().Value("runtime").(*libpod.Runtime) decoder = r.Context().Value("decoder").(*schema.Decoder) + signal = "SIGKILL" ) query := struct { - signal int `schema:"signal"` + signal string `schema:"signal"` }{ // override any golang type defaults } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) return } + muxVars := mux.Vars(r) + if _, found := muxVars["signal"]; found { + signal = query.signal + } + + sig, err := util.ParseSignal(signal) + if err != nil { + utils.InternalServerError(w, errors.Wrapf(err, "unable to parse signal value")) + } name := mux.Vars(r)["name"] pod, err := runtime.LookupPod(name) if err != nil { @@ -419,8 +429,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) { utils.Error(w, msg, http.StatusConflict, errors.Errorf("cannot kill a pod with no running containers: %s", pod.ID())) return } - // TODO How do we differentiate if a signal was sent vs accepting the pod/container default? - _, err = pod.Kill(uint(query.signal)) + _, err = pod.Kill(uint(sig)) if err != nil { utils.Error(w, "Something went wrong", http.StatusInternalServerError, err) return diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go index c845c8195..5509c1d46 100644 --- a/pkg/api/handlers/swagger.go +++ b/pkg/api/handlers/swagger.go @@ -30,9 +30,7 @@ type swagImageInspect struct { // swagger:response DocsImageDeleteResponse type swagImageDeleteResponse struct { // in:body - Body struct { - image.ImageDeleteResponse - } + Body []image.ImageDeleteResponse } // Search results @@ -98,9 +96,7 @@ type swagLibpodInspectContainerResponse struct { // swagger:response ListPodsResponse type swagListPodsResponse struct { // in:body - Body struct { - libpod.PodInspect - } + Body []libpod.PodInspect } // Inspect pod diff --git a/pkg/api/handlers/utils/errors.go b/pkg/api/handlers/utils/errors.go index 3ec0742bd..9d2081cd8 100644 --- a/pkg/api/handlers/utils/errors.go +++ b/pkg/api/handlers/utils/errors.go @@ -27,34 +27,34 @@ func Error(w http.ResponseWriter, apiMessage string, code int, err error) { WriteJSON(w, code, em) } -func VolumeNotFound(w http.ResponseWriter, nameOrId string, err error) { +func VolumeNotFound(w http.ResponseWriter, name string, err error) { if errors.Cause(err) != define.ErrNoSuchVolume { InternalServerError(w, err) } - msg := fmt.Sprintf("No such volume: %s", nameOrId) + msg := fmt.Sprintf("No such volume: %s", name) Error(w, msg, http.StatusNotFound, err) } -func ContainerNotFound(w http.ResponseWriter, nameOrId string, err error) { +func ContainerNotFound(w http.ResponseWriter, name string, err error) { if errors.Cause(err) != define.ErrNoSuchCtr { InternalServerError(w, err) } - msg := fmt.Sprintf("No such container: %s", nameOrId) + msg := fmt.Sprintf("No such container: %s", name) Error(w, msg, http.StatusNotFound, err) } -func ImageNotFound(w http.ResponseWriter, nameOrId string, err error) { +func ImageNotFound(w http.ResponseWriter, name string, err error) { if errors.Cause(err) != define.ErrNoSuchImage { InternalServerError(w, err) } - msg := fmt.Sprintf("No such image: %s", nameOrId) + msg := fmt.Sprintf("No such image: %s", name) Error(w, msg, http.StatusNotFound, err) } -func PodNotFound(w http.ResponseWriter, nameOrId string, err error) { +func PodNotFound(w http.ResponseWriter, name string, err error) { if errors.Cause(err) != define.ErrNoSuchPod { InternalServerError(w, err) } - msg := fmt.Sprintf("No such pod: %s", nameOrId) + msg := fmt.Sprintf("No such pod: %s", name) Error(w, msg, http.StatusNotFound, err) } @@ -73,9 +73,11 @@ func BadRequest(w http.ResponseWriter, key string, value string, err error) { } type ErrorModel struct { - // root cause + // API root cause formatted for automated parsing + // example: API root cause Because string `json:"cause"` - // error message + // human error message, formatted for a human to read + // example: human error message Message string `json:"message"` } @@ -86,3 +88,8 @@ func (e ErrorModel) Error() string { func (e ErrorModel) Cause() error { return errors.New(e.Because) } + +// UnsupportedParameter logs a given param by its string name as not supported. +func UnSupportedParameter(param string) { + log.Infof("API parameter %q: not supported", param) +} diff --git a/pkg/api/server/docs.go b/pkg/api/server/docs.go new file mode 100644 index 000000000..e028c6302 --- /dev/null +++ b/pkg/api/server/docs.go @@ -0,0 +1,29 @@ +// Package api Provides a container compatible interface. (Experimental) +// +// This documentation describes the HTTP Libpod interface. It is to be considered +// only as experimental as this point. The endpoints, parameters, inputs, and +// return values can all change. +// +// Terms Of Service: +// +// Schemes: http, https +// Host: podman.io +// BasePath: / +// Version: 0.0.1 +// License: Apache-2.0 https://opensource.org/licenses/Apache-2.0 +// Contact: Podman <podman@lists.podman.io> https://podman.io/community/ +// Extensions: +// x-logo: +// - url: https://raw.githubusercontent.com/containers/libpod/master/logo/podman-logo.png +// - altText: "Podman logo" +// +// Produces: +// - application/json +// - text/plain +// - text/html +// +// Consumes: +// - application/json +// - application/x-tar +// swagger:meta +package server diff --git a/pkg/api/server/listener_api.go b/pkg/api/server/listener_api.go new file mode 100644 index 000000000..4984216b8 --- /dev/null +++ b/pkg/api/server/listener_api.go @@ -0,0 +1,31 @@ +package server + +import ( + "net" + "os" + "path/filepath" + + "github.com/pkg/errors" +) + +// ListenUnix follows stdlib net.Listen() API, providing a unix listener for given path +// ListenUnix will delete and create files/directories as needed +func ListenUnix(network string, path string) (net.Listener, error) { + // setup custom listener for API server + err := os.MkdirAll(filepath.Dir(path), 0770) + if err != nil { + return nil, errors.Wrapf(err, "api.ListenUnix() failed to create %s", filepath.Dir(path)) + } + os.Remove(path) + + listener, err := net.Listen(network, path) + if err != nil { + return nil, errors.Wrapf(err, "api.ListenUnix() failed to create net.Listen(%s, %s)", network, path) + } + + _, err = os.Stat(path) + if err != nil { + return nil, errors.Wrapf(err, "net.Listen(%s, %s) failed to report the failure to create socket", network, path) + } + return listener, nil +} diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 6f4222d8f..58920d106 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -23,21 +23,21 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // 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" + // 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 compat listContainers // --- - // tags: - // - containers (compat) + // tags: + // - containers (compat) // summary: List containers // description: Returns a list of containers // parameters: @@ -63,17 +63,17 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // "$ref": "#/responses/DocsListContainer" - // '400': - // "$ref": "#/responses/BadParamError" - // '500': - // "$ref": "#/responses/InternalError" + // 200: + // $ref: "#/responses/DocsListContainer" + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/json"), APIHandler(s.Context, generic.ListContainers)).Methods(http.MethodGet) // swagger:operation POST /containers/prune compat pruneContainers // --- - // tags: - // - containers (compat) + // tags: + // - containers (compat) // summary: Delete stopped containers // description: Remove containers not in use // parameters: @@ -87,76 +87,78 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // "$ref": "#/responses/DocsContainerPruneReport" - // '500': - // "$ref": "#/responses/InternalError" + // 200: + // $ref: "#/responses/DocsContainerPruneReport" + // 500: + // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/containers/prune"), APIHandler(s.Context, generic.PruneContainers)).Methods(http.MethodPost) - // swagger:operation DELETE /containers/{nameOrID} compat removeContainer + // swagger:operation DELETE /containers/{name} compat removeContainer // --- - // tags: - // - containers (compat) + // tags: + // - containers (compat) // summary: Remove a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: force - // type: bool + // type: boolean // default: false // description: If the container is running, kill it before removing it. // - in: query // name: v - // type: bool + // type: boolean // default: false // description: Remove the volumes associated with the container. // - in: query // name: link - // type: bool + // type: boolean // description: not supported // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '400': - // "$ref": "#/responses/BadParamError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '409': - // "$ref": "#/responses/ConflictError" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}"), APIHandler(s.Context, generic.RemoveContainer)).Methods(http.MethodDelete) - // swagger:operation GET /containers/{nameOrID}/json compat getContainer + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}"), APIHandler(s.Context, generic.RemoveContainer)).Methods(http.MethodDelete) + // swagger:operation GET /containers/{name}/json compat getContainer // --- - // tags: - // - containers (compat) + // tags: + // - containers (compat) // summary: Inspect container // description: Return low-level information about a container. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or id of the container // - in: query // name: size - // type: bool + // type: boolean // default: false // description: include the size of the container // produces: // - application/json // responses: - // '200': - // "$ref": "#/responses/DocsContainerInspectResponse" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/json"), APIHandler(s.Context, generic.GetContainer)).Methods(http.MethodGet) - // swagger:operation post /containers/{nameOrID}/kill compat killcontainer + // 200: + // $ref: "#/responses/DocsContainerInspectResponse" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/json"), APIHandler(s.Context, generic.GetContainer)).Methods(http.MethodGet) + // swagger:operation post /containers/{name}/kill compat killcontainer // --- // tags: // - containers (compat) @@ -164,26 +166,28 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Signal to send to the container as an integer or string (e.g. SIGINT) // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: signal - // type: int + // type: string + // default: TERM // description: signal to be sent to container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '409': - // "$ref": "#/responses/ConflictError" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/kill"), APIHandler(s.Context, generic.KillContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/{nameOrID}/logs compat LogsFromContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/kill"), APIHandler(s.Context, generic.KillContainer)).Methods(http.MethodPost) + // swagger:operation GET /containers/{name}/logs compat LogsFromContainer // --- // tags: // - containers (compat) @@ -191,20 +195,21 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Get stdout and stderr logs from a container. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: follow - // type: bool + // type: boolean // description: Keep connection after returning logs. // - in: query // name: stdout - // type: bool + // type: boolean // description: not supported // - in: query // name: stderr - // type: bool + // type: boolean // description: not supported? // - in: query // name: since @@ -216,7 +221,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Only return logs before this time, as a UNIX timestamp // - in: query // name: timestamps - // type: bool + // type: boolean // default: false // description: Add timestamps to every log line // - in: query @@ -227,14 +232,14 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': + // 200: // description: logs returned as a stream in response body. - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/logs"), APIHandler(s.Context, generic.LogsFromContainer)).Methods(http.MethodGet) - // swagger:operation POST /containers/{nameOrID}/pause compat pauseContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/logs"), APIHandler(s.Context, generic.LogsFromContainer)).Methods(http.MethodGet) + // swagger:operation POST /containers/{name}/pause compat pauseContainer // --- // tags: // - containers (compat) @@ -242,52 +247,55 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Use the cgroups freezer to suspend all processes in a container. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$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 compat restartContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $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/{name}/restart compat restartContainer // --- // tags: // - containers (compat) // summary: Restart container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: t - // type: int + // type: integer // description: timeout before sending kill signal to container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/start compat startContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost) + // swagger:operation POST /containers/{name}/start compat startContainer // --- // tags: // - containers (compat) // summary: Start a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -297,16 +305,16 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '304': - // "$ref": "#/responses/ContainerAlreadyStartedError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/{nameOrID}/stats compat statsContainer + // 304: + // $ref: "#/responses/ContainerAlreadyStartedError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost) + // swagger:operation GET /containers/{name}/stats compat statsContainer // --- // tags: // - containers (compat) @@ -314,58 +322,62 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: This returns a live stream of a container’s resource usage statistics. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: stream - // type: bool + // type: boolean // default: true // description: Stream the output // produces: // - application/json // responses: - // '200': - // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet) - // swagger:operation POST /containers/{nameOrID}/stop compat stopContainer + // 200: + // description: OK + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet) + // swagger:operation POST /containers/{name}/stop compat stopContainer // --- // tags: // - containers (compat) // summary: Stop a container + // description: Stop a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: t - // type: int + // type: integer // description: number of seconds to wait before killing container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '304': - // "$ref": "#/responses/ContainerAlreadyStoppedError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost) - // swagger:operation GET /containers/{nameOrID}/top compat topContainer + // 304: + // $ref: "#/responses/ContainerAlreadyStoppedError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost) + // swagger:operation GET /containers/{name}/top compat topContainer // --- // tags: // - containers (compat) // summary: List processes running inside a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -375,14 +387,14 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // "ref": "#/responses/DockerTopResponse" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet) - // swagger:operation POST /containers/{nameOrID}/unpause compat unpauseContainer + // 200: + // $ref: "#/responses/DockerTopResponse" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet) + // swagger:operation POST /containers/{name}/unpause compat unpauseContainer // --- // tags: // - containers (compat) @@ -390,20 +402,21 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Resume a paused container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/wait compat waitContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost) + // swagger:operation POST /containers/{name}/wait compat waitContainer // --- // tags: // - containers (compat) @@ -411,7 +424,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Block until a container stops, then returns the exit code. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -421,14 +435,14 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': + // 200: // $ref: "#/responses/ContainerWaitResponse" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/wait"), APIHandler(s.Context, generic.WaitContainer)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/attach compat attach + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/wait"), APIHandler(s.Context, generic.WaitContainer)).Methods(http.MethodPost) + // swagger:operation POST /containers/{name}/attach compat attach // --- // tags: // - containers (compat) @@ -436,7 +450,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Hijacks the connection to forward the container's standard streams to the client. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -447,42 +462,42 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // - in: query // name: logs // required: false - // type: bool + // type: boolean // description: Not yet supported // - in: query // name: stream // required: false - // type: bool + // type: boolean // default: true // description: If passed, must be set to true; stream=false is not yet supported // - in: query // name: stdout // required: false - // type: bool + // type: boolean // description: Attach to container STDOUT // - in: query // name: stderr // required: false - // type: bool + // type: boolean // description: Attach to container STDERR // - in: query // name: stdin // required: false - // type: bool + // type: boolean // description: Attach to container STDIN // produces: // - application/json // responses: - // '101': + // 101: // description: No error, connection has been hijacked for transporting streams. - // '400': - // "$ref": "#/responses/BadParamError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/attach"), APIHandler(s.Context, handlers.AttachContainer)).Methods(http.MethodPost) - // swagger:operation POST /containers/{nameOrID}/resize compat resize + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/attach"), APIHandler(s.Context, handlers.AttachContainer)).Methods(http.MethodPost) + // swagger:operation POST /containers/{name}/resize compat resize // --- // tags: // - containers (compat) @@ -490,29 +505,30 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Resize the terminal attached to a container (for use with Attach). // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: h - // type: int + // type: integer // required: false // description: Height to set for the terminal, in characters // - in: query // name: w - // type: int + // type: integer // required: false // description: Width to set for the terminal, in characters // produces: // - application/json // responses: - // '200': - // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name:..*}/resize"), APIHandler(s.Context, handlers.ResizeContainer)).Methods(http.MethodPost) + // 200: + // $ref: "#/responses/ok" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/containers/{name}/resize"), APIHandler(s.Context, handlers.ResizeContainer)).Methods(http.MethodPost) /* libpod endpoints @@ -528,13 +544,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // schema: - // "$ref": "#/responses/LibpodListContainersResponse" - // '400': - // "$ref": "#/responses/BadParamError" - // '500': - // "$ref": "#/responses/InternalError" + // 200: + // $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 libpod libpodPruneContainers // --- @@ -545,8 +560,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // parameters: // - in: query // name: force - // type: bool - // description: something + // type: boolean + // description: TODO This should be removed from API. Will always be true... // - in: query // name: filters // type: string @@ -557,10 +572,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // description: to be determined - // '500': - // "$ref": "#/responses/InternalError" + // 200: + // type: string + // description: success + // example: OK + // 500: + // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/prune"), APIHandler(s.Context, libpod.PruneContainers)).Methods(http.MethodPost) // swagger:operation GET /libpod/containers/showmounted libpod showMounterContainers // --- @@ -571,48 +588,50 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': + // 200: // description: mounted containers // schema: // type: object // additionalProperties: // type: string - // '500': - // "$ref": "#/responses/InternalError" + // 500: + // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/showmounted"), APIHandler(s.Context, libpod.ShowMountedContainers)).Methods(http.MethodGet) - // swagger:operation DELETE /libpod/containers/json libpod libpodRemoveContainer + // swagger:operation DELETE /libpod/containers/{name} libpod libpodRemoveContainer // --- // tags: // - containers // summary: Delete container + // description: Delete container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: force - // type: bool + // type: boolean // description: need something // - in: query // name: v - // type: bool + // type: boolean // description: delete volumes // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '400': - // "$ref": "#/responses/BadParamError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '409': - // "$ref": "#/responses/ConflictError" - // '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 libpod libpodGetContainer + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}"), APIHandler(s.Context, libpod.RemoveContainer)).Methods(http.MethodDelete) + // swagger:operation GET /libpod/containers/{name}/json libpod libpodGetContainer // --- // tags: // - containers @@ -620,24 +639,25 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Return low-level information about a container. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: size - // type: bool + // type: boolean // description: display filesystem usage // produces: // - application/json // responses: - // '200': - // "$ref": "#/responses/LibpodInspectContainerResponse" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '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 libpod libpodKillContainer + // 200: + // $ref: "#/responses/LibpodInspectContainerResponse" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/json"), APIHandler(s.Context, libpod.GetContainer)).Methods(http.MethodGet) + // swagger:operation POST /libpod/containers/{name}/kill libpod libpodKillContainer // --- // tags: // - containers @@ -645,27 +665,28 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: send a signal to a container, defaults to killing the container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: signal - // type: int - // default: 15 - // description: signal to be sent to container + // type: string + // default: TERM + // description: signal to be sent to container, either by integer or SIG_ name // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '409': - // "$ref": "#/responses/ConflictError" - // '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 libpod mountContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/kill"), APIHandler(s.Context, libpod.KillContainer)).Methods(http.MethodGet) + // swagger:operation GET /libpod/containers/{name}/mount libpod mountContainer // --- // tags: // - containers @@ -673,25 +694,48 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Mount a container to the filesystem // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '200': + // 200: // description: mounted container // schema: // description: id // type: string - // example: 3c784de79b791b4ebd3ac55e511f97fedc042328499554937a3f8bfd9c1a2cb8 - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$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 libpod libpodPauseContainer + // example: /var/lib/containers/storage/overlay/f3f693bd88872a1e3193f4ebb925f4c282e8e73aadb8ab3e7492754dda3a02a4/merged + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/mount"), APIHandler(s.Context, libpod.MountContainer)).Methods(http.MethodPost) + // swagger:operation POST /libpod/containers/{name}/unmount libpod libpodUnmountContainer + // --- + // tags: + // - containers + // summary: Unmount a container + // description: Unmount a container from the filesystem + // produces: + // - application/json + // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: the name or ID of the container + // responses: + // 204: + // description: ok + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/unmount"), APIHandler(s.Context, libpod.UnmountContainer)).Methods(http.MethodPost) + r.HandleFunc(VersionedPath("/libpod/containers/{name}/logs"), APIHandler(s.Context, libpod.LogsFromContainer)).Methods(http.MethodGet) + // swagger:operation POST /libpod/containers/{name}/pause libpod libpodPauseContainer // --- // tags: // - containers @@ -699,51 +743,54 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Use the cgroups freezer to suspend all processes in a container. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" + // 404: + // "$ref": "#/responses/NoSuchContainer" + // 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 libpod libpodRestartContainer + // swagger:operation POST /libpod/containers/{name}/restart libpod libpodRestartContainer // --- // tags: // - containers // summary: Restart a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: t - // type: int + // type: integer // description: timeout before sending kill signal to container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '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 libpod libpodStartContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost) + // swagger:operation POST /libpod/containers/{name}/start libpod libpodStartContainer // --- // tags: // - containers // summary: Start a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -753,16 +800,16 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '304': - // "$ref": "#/responses/ContainerAlreadyStartedError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '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 libpod statsContainer + // 304: + // $ref: "#/responses/ContainerAlreadyStartedError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost) + // swagger:operation GET /libpod/containers/{name}/stats libpod libpodStatsContainer // --- // tags: // - containers @@ -770,82 +817,89 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: This returns a live stream of a container’s resource usage statistics. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: stream - // type: bool + // type: boolean // default: true // description: Stream the output // produces: // - application/json // responses: - // '200': + // 200: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet) - // swagger:operation GET /libpod/containers/{nameOrID}/top libpod libpodTopContainer - // - // List processes running inside a container. Note - // + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet) + // swagger:operation GET /libpod/containers/{name}/top libpod libpodTopContainer // --- // tags: // - containers + // summary: List processes + // description: List processes running inside a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true - // description: the name or ID of the container + // description: | + // Name of container to query for processes + // (As of version 1.xx) // - in: query // name: stream - // type: bool + // type: boolean // default: true // description: Stream the output + // - in: query // name: ps_args // type: string + // default: -ef // description: arguments to pass to ps such as aux. Requires ps(1) to be installed in the container if no ps(1) compatible AIX descriptors are used. // produces: // - application/json // responses: - // '200': - // "ref": "#/responses/DockerTopResponse" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet) - // swagger:operation POST /libpod/containers/{nameOrID}/unpause libpod libpodUnpauseContainer + // 200: + // $ref: "#/responses/DockerTopResponse" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet) + // swagger:operation POST /libpod/containers/{name}/unpause libpod libpodUnpauseContainer // --- // tags: // - containers // summary: Unpause Container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '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 libpod libpodWaitContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost) + // swagger:operation POST /libpod/containers/{name}/wait libpod libpodWaitContainer // --- // tags: // - containers // summary: Wait on a container to exit // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -855,14 +909,14 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '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 libpod containerExists + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/wait"), APIHandler(s.Context, libpod.WaitContainer)).Methods(http.MethodPost) + // swagger:operation POST /libpod/containers/{name}/exists libpod containerExists // --- // tags: // - containers @@ -870,46 +924,48 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Quick way to determine if a container exists by name or ID // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '204': + // 204: // description: container exists - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '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 libpod libpodStopContainer + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/exists"), APIHandler(s.Context, libpod.ContainerExists)).Methods(http.MethodGet) + // swagger:operation POST /libpod/containers/{name}/stop libpod libpodStopContainer // --- // tags: // - containers // summary: Stop a container // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: t - // type: int + // type: integer // description: number of seconds to wait before killing container // produces: // - application/json // responses: - // '204': + // 204: // description: no error - // '304': - // "$ref": "#/responses/ContainerAlreadyStoppedError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{nameOrID}/attach libpod attach + // 304: + // $ref: "#/responses/ContainerAlreadyStoppedError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost) + // swagger:operation POST /libpod/containers/{name}/attach libpod libpodAttach // --- // tags: // - containers @@ -917,7 +973,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Hijacks the connection to forward the container's standard streams to the client. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -928,42 +985,42 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // - in: query // name: logs // required: false - // type: bool + // type: boolean // description: Not yet supported // - in: query // name: stream // required: false - // type: bool + // type: boolean // default: true // description: If passed, must be set to true; stream=false is not yet supported // - in: query // name: stdout // required: false - // type: bool + // type: boolean // description: Attach to container STDOUT // - in: query // name: stderr // required: false - // type: bool + // type: boolean // description: Attach to container STDERR // - in: query // name: stdin // required: false - // type: bool + // type: boolean // description: Attach to container STDIN // produces: // - application/json // responses: - // '101': + // 101: // description: No error, connection has been hijacked for transporting streams. - // '400': - // "$ref": "#/responses/BadParamError" - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/attach"), APIHandler(s.Context, handlers.AttachContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{nameOrID}/resize libpod resize + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/attach"), APIHandler(s.Context, handlers.AttachContainer)).Methods(http.MethodPost) + // swagger:operation POST /libpod/containers/{name}/resize libpod libpodResize // --- // tags: // - containers @@ -971,28 +1028,29 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // description: Resize the terminal attached to a container (for use with Attach). // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query // name: h - // type: int + // type: integer // required: false // description: Height to set for the terminal, in characters // - in: query // name: w - // type: int + // type: integer // required: false // description: Width to set for the terminal, in characters // produces: // - application/json // responses: - // '200': - // description: no error - // '404': - // "$ref": "#/responses/NoSuchContainer" - // '500': - // "$ref": "#/responses/InternalError" - r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/resize"), APIHandler(s.Context, handlers.ResizeContainer)).Methods(http.MethodPost) + // 200: + // $ref: "#/responses/ok" + // 404: + // $ref: "#/responses/NoSuchContainer" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/libpod/containers/{name}/resize"), APIHandler(s.Context, handlers.ResizeContainer)).Methods(http.MethodPost) return nil } diff --git a/pkg/api/server/register_distribution.go b/pkg/api/server/register_distribution.go index 23820b4a7..b0ac61fb8 100644 --- a/pkg/api/server/register_distribution.go +++ b/pkg/api/server/register_distribution.go @@ -6,6 +6,6 @@ import ( ) func (s *APIServer) RegisterDistributionHandlers(r *mux.Router) error { - r.HandleFunc(VersionedPath("/distribution/{name:..*}/json"), handlers.UnsupportedHandler) + r.HandleFunc(VersionedPath("/distribution/{name}/json"), handlers.UnsupportedHandler) return nil } diff --git a/pkg/api/server/register_events.go b/pkg/api/server/register_events.go index 56cf96de1..a32244f4d 100644 --- a/pkg/api/server/register_events.go +++ b/pkg/api/server/register_events.go @@ -8,24 +8,29 @@ import ( func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error { // swagger:operation GET /events system getEvents // --- + // tags: + // - system // summary: Returns events filtered on query parameters + // description: Returns events filtered on query parameters // produces: // - application/json // parameters: // - name: since + // type: string // in: query // description: start streaming events from this time // - name: until + // type: string // in: query // description: stop streaming events later than this // - name: filters + // type: string // in: query // description: JSON encoded map[string][]string of constraints // responses: - // "200": - // description: OK - // "500": - // description: Failed + // 200: + // $ref: "#/responses/ok" + // 500: // "$ref": "#/responses/InternalError" r.Handle(VersionedPath("/events"), APIHandler(s.Context, handlers.GetEvents)) return nil diff --git a/pkg/api/server/register_healthcheck.go b/pkg/api/server/register_healthcheck.go index e4cc145d5..1286324f0 100644 --- a/pkg/api/server/register_healthcheck.go +++ b/pkg/api/server/register_healthcheck.go @@ -8,6 +8,6 @@ import ( ) func (s *APIServer) registerHealthCheckHandlers(r *mux.Router) error { - r.Handle(VersionedPath("/libpod/containers/{name:..*}/runhealthcheck"), APIHandler(s.Context, libpod.RunHealthCheck)).Methods(http.MethodGet) + r.Handle(VersionedPath("/libpod/containers/{name}/runhealthcheck"), APIHandler(s.Context, libpod.RunHealthCheck)).Methods(http.MethodGet) return nil } diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index cd42afe71..6e8b79313 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -11,11 +11,10 @@ import ( func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // swagger:operation POST /images/create compat createImage - // // --- // tags: // - images (compat) - // summary: Create an image from an image + // summary: Create an image // description: Create an image by either pulling it from a registry or importing it. // produces: // - application/json @@ -25,53 +24,30 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // type: string // description: needs description // - in: query - // name: tag - // type: string - // description: needs description - // responses: - // '200': - // schema: - // items: - // $ref: "to be determined" - // '404': - // description: repo or image does not exist - // schema: - // $ref: "#/responses/InternalError" - // '500': - // description: unexpected 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 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: - // - application/json - // parameters: - // - in: query // name: fromSrc // type: string // description: needs description // - in: query - // name: changes - // type: to be determined + // name: tag + // type: string // description: needs description + // - in: header + // name: X-Registry-Auth + // type: string + // description: A base64-encoded auth configuration. + // - in: body + // name: request + // schema: + // type: string + // description: Image content if fromSrc parameter was used // responses: - // '200': - // schema: - // items: - // $ref: "to be determined" - // '404': - // description: repo or image does not exist - // schema: - // $ref: "#/responses/InternalError" - // '500': - // description: unexpected error - // schema: - // $ref: '#/responses/GenericError' + // 200: + // $ref: "#/responses/ok" + // 404: + // $ref: "#/responses/NoSuchImage" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromImage)).Methods(http.MethodPost).Queries("fromImage", "{fromImage}") r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromSrc)).Methods(http.MethodPost).Queries("fromSrc", "{fromSrc}") // swagger:operation GET /images/json compat listImages // --- @@ -82,17 +58,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // schema: - // type: array - // items: - // schema: - // $ref: "#/responses/DockerImageSummary" - // '500': - // $ref: '#/responses/InternalError' + // 200: + // $ref: "#/responses/DockerImageSummary" + // 500: + // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/json"), APIHandler(s.Context, generic.GetImages)).Methods(http.MethodGet) // swagger:operation POST /images/load compat loadImage - // // --- // tags: // - images (compat) @@ -101,19 +72,20 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // parameters: // - in: query // name: quiet - // type: bool + // type: boolean // description: not supported // - in: body + // name: request // description: tarball of container image - // type: string - // format: binary + // schema: + // type: string // produces: // - application/json // responses: - // '200': + // 200: // description: no error - // '500': - // $ref: '#/responses/InternalError' + // 500: + // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost) // swagger:operation POST /images/prune compat pruneImages // --- @@ -135,12 +107,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // schema: - // items: - // $ref: "#/responses/DocsImageDeleteResponse" - // '500': - // $ref: '#/responses/InternalError' + // 200: + // $ref: "#/responses/DocsImageDeleteResponse" + // 500: + // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/prune"), APIHandler(s.Context, generic.PruneImages)).Methods(http.MethodPost) // swagger:operation GET /images/search compat searchImages // --- @@ -155,7 +125,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: term to search // - in: query // name: limit - // type: int + // type: integer // description: maximum number of results // - in: query // name: filters @@ -168,39 +138,44 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // $ref: "#/responses/DocsSearchResponse" - // '500': - // $ref: '#/responses/InternalError' + // 200: + // $ref: "#/responses/DocsSearchResponse" + // 500: + // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet) - // swagger:operation DELETE /images/{nameOrID} compat removeImage + // swagger:operation DELETE /images/{name} compat removeImage // --- // tags: // - images (compat) // summary: Remove Image // description: Delete an image from local storage // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: name or ID of image to delete // - in: query // name: force - // type: bool + // type: boolean // description: remove the image even if used by containers or has other tags // - in: query // name: noprune - // type: bool + // type: boolean // description: not supported. will be logged as an invalid parameter if enabled // produces: // - application/json // responses: - // '200': - // $ref: "#/responses/DocsImageDeleteResponse" - // '400': - // $ref: '#/responses/BadParamError' - // '409': - // $ref: '#/responses/ConflictError' - // '500': - // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/images/{name:..*}"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete) - // swagger:operation GET /images/{nameOrID}/get compat exportImage + // 200: + // $ref: "#/responses/DocsImageDeleteResponse" + // 404: + // $ref: '#/responses/NoSuchImage' + // 409: + // $ref: '#/responses/ConflictError' + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/images/name"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete) + // swagger:operation GET /images/{name}/get compat exportImage // --- // tags: // - images (compat) @@ -208,21 +183,22 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Export an image in tarball format // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '200': + // 200: // description: no error // schema: // type: string // format: binary - // '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 imageHistory + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/images/{name}/get"), APIHandler(s.Context, generic.ExportImage)).Methods(http.MethodGet) + // swagger:operation GET /images/{name}/history compat imageHistory // --- // tags: // - images (compat) @@ -230,20 +206,21 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Return parent layers of an image. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '200': + // 200: // $ref: "#/responses/DocsHistory" - // '404': + // 404: // $ref: "#/responses/NoSuchImage" - // '500': + // 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 inspectImage + r.Handle(VersionedPath("/images/{name}/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet) + // swagger:operation GET /images/{name}/json compat inspectImage // --- // tags: // - images (compat) @@ -251,20 +228,21 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Return low-level information about an image. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '200': - // $ref: "#/responses/DocsImageInspect" - // '404': - // $ref: "#/responses/NoSuchImage" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/images/{name:..*}/json"), APIHandler(s.Context, generic.GetImage)) - // swagger:operation POST /images/{nameOrID}/tag compat tagImage + // 200: + // $ref: "#/responses/DocsImageInspect" + // 404: + // $ref: "#/responses/NoSuchImage" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/images/{name}/json"), APIHandler(s.Context, generic.GetImage)) + // swagger:operation POST /images/{name}/tag compat tagImage // --- // tags: // - images (compat) @@ -272,7 +250,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Tag an image so that it becomes part of a repository. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -296,7 +275,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // $ref: '#/responses/ConflictError' // 500: // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/images/{name:..*}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost) + r.Handle(VersionedPath("/images/{name}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost) // swagger:operation POST /commit/ compat commitContainer // --- // tags: @@ -325,7 +304,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: author of the image // - in: query // name: pause - // type: bool + // type: boolean // description: pause the container before committing it // - in: query // name: changes @@ -334,19 +313,228 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '201': + // 201: // description: no error - // '404': - // $ref: '#/responses/NoSuchImage' - // '500': - // $ref: '#/responses/InternalError' + // 404: + // $ref: '#/responses/NoSuchImage' + // 500: + // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/commit"), APIHandler(s.Context, generic.CommitContainer)).Methods(http.MethodPost) + // swagger:operation POST /build images buildImage + // --- + // tags: + // - images + // summary: Create image + // description: Build an image from the given Dockerfile(s) + // parameters: + // - in: query + // name: dockerfile + // type: string + // default: Dockerfile + // description: | + // Path within the build context to the `Dockerfile`. + // This is ignored if remote is specified and points to an external `Dockerfile`. + // - in: query + // name: t + // type: string + // default: latest + // description: A name and optional tag to apply to the image in the `name:tag` format. + // - in: query + // name: extrahosts + // type: string + // default: + // description: | + // TBD Extra hosts to add to /etc/hosts + // (As of version 1.xx) + // - in: query + // name: remote + // type: string + // default: + // description: | + // A Git repository URI or HTTP/HTTPS context URI. + // If the URI points to a single text file, the file’s contents are placed + // into a file called Dockerfile and the image is built from that file. If + // the URI points to a tarball, the file is downloaded by the daemon and the + // contents therein used as the context for the build. If the URI points to a + // tarball and the dockerfile parameter is also specified, there must be a file + // with the corresponding path inside the tarball. + // (As of version 1.xx) + // - in: query + // name: q + // type: boolean + // default: false + // description: | + // Suppress verbose build output + // - in: query + // name: nocache + // type: boolean + // default: false + // description: | + // Do not use the cache when building the image + // (As of version 1.xx) + // - in: query + // name: cachefrom + // type: string + // default: + // description: | + // JSON array of images used to build cache resolution + // (As of version 1.xx) + // - in: query + // name: pull + // type: boolean + // default: false + // description: | + // Attempt to pull the image even if an older image exists locally + // (As of version 1.xx) + // - in: query + // name: rm + // type: boolean + // default: true + // description: | + // Remove intermediate containers after a successful build + // (As of version 1.xx) + // - in: query + // name: forcerm + // type: boolean + // default: false + // description: | + // Always remove intermediate containers, even upon failure + // (As of version 1.xx) + // - in: query + // name: memory + // type: integer + // description: | + // Memory is the upper limit (in bytes) on how much memory running containers can use + // (As of version 1.xx) + // - in: query + // name: memswap + // type: integer + // description: | + // MemorySwap limits the amount of memory and swap together + // (As of version 1.xx) + // - in: query + // name: cpushares + // type: integer + // description: | + // CPUShares (relative weight + // (As of version 1.xx) + // - in: query + // name: cpusetcpus + // type: string + // description: | + // CPUSetCPUs in which to allow execution (0-3, 0,1) + // (As of version 1.xx) + // - in: query + // name: cpuperiod + // type: integer + // description: | + // CPUPeriod limits the CPU CFS (Completely Fair Scheduler) period + // (As of version 1.xx) + // - in: query + // name: cpuquota + // type: integer + // description: | + // CPUQuota limits the CPU CFS (Completely Fair Scheduler) quota + // (As of version 1.xx) + // - in: query + // name: buildargs + // type: string + // default: + // description: | + // JSON map of string pairs denoting build-time variables. + // For example, the build argument `Foo` with the value of `bar` would be encoded in JSON as `["Foo":"bar"]`. + // + // For example, buildargs={"Foo":"bar"}. + // + // Note(s): + // * This should not be used to pass secrets. + // * The value of buildargs should be URI component encoded before being passed to the API. + // + // (As of version 1.xx) + // - in: query + // name: shmsize + // type: integer + // default: 67108864 + // description: | + // ShmSize is the "size" value to use when mounting an shmfs on the container's /dev/shm directory. + // Default is 64MB + // (As of version 1.xx) + // - in: query + // name: squash + // type: boolean + // default: false + // description: | + // Silently ignored. + // Squash the resulting images layers into a single layer + // (As of version 1.xx) + // - in: query + // name: labels + // type: string + // default: + // description: | + // JSON map of key, value pairs to set as labels on the new image + // (As of version 1.xx) + // - in: query + // name: networkmode + // type: string + // default: bridge + // description: | + // Sets the networking mode for the run commands during build. + // Supported standard values are: + // * `bridge` limited to containers within a single host, port mapping required for external access + // * `host` no isolation between host and containers on this network + // * `none` disable all networking for this container + // * container:<nameOrID> share networking with given container + // ---All other values are assumed to be a custom network's name + // (As of version 1.xx) + // - in: query + // name: platform + // type: string + // default: + // description: | + // Platform format os[/arch[/variant]] + // (As of version 1.xx) + // - in: query + // name: target + // type: string + // default: + // description: | + // Target build stage + // (As of version 1.xx) + // - in: query + // name: outputs + // type: string + // default: + // description: | + // output configuration TBD + // (As of version 1.xx) + // produces: + // - application/json + // responses: + // 200: + // description: OK (As of version 1.xx) + // schema: + // type: object + // required: + // - stream + // properties: + // stream: + // type: string + // description: output from build process + // example: | + // (build details...) + // Successfully built 8ba084515c724cbf90d447a63600c0a6 + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost) /* libpod endpoints */ - // swagger:operation POST /libpod/images/{nameOrID}/exists libpod libpodImageExists + // swagger:operation POST /libpod/images/{name}/exists libpod libpodImageExists // --- // tags: // - images @@ -354,21 +542,22 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Check if image exists in local store // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '204': + // 204: // description: image exists - // '404': - // $ref: '#/responses/NoSuchImage' - // '500': - // $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 libpod libpodImageHistory + // 404: + // $ref: '#/responses/NoSuchImage' + // 500: + // $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/{name}/history libpod libpodImageHistory // --- // tags: // - images @@ -376,21 +565,20 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Return parent layers of an image. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '200': - // schema: - // items: - // $ref: "#/responses/HistoryResponse" - // '404': - // $ref: '#/responses/NoSuchImage' - // '500': - // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/libpod/images/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet) + // 200: + // $ref: "#/responses/DocsHistory" + // 404: + // $ref: '#/responses/NoSuchImage' + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/libpod/images/{name}/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet) // swagger:operation GET /libpod/images/json libpod libpodListImages // --- // tags: @@ -400,10 +588,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // $ref: "#/responses/DockerImageSummary" - // '500': - // $ref: '#/responses/InternalError' + // 200: + // $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 libpod libpodLoadImage // --- @@ -414,18 +602,20 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // parameters: // - in: query // name: quiet - // type: bool + // type: boolean // description: not supported // - in: body + // name: request // description: tarball of container image - // type: string - // format: binary + // required: true + // schema: + // type: string // produces: // - application/json // responses: - // '200': + // 200: // description: no error - // '500': + // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost) // swagger:operation POST /libpod/images/prune libpod libpodPruneImages @@ -447,16 +637,15 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune images with (or without, in case `label!=...` is used) the specified labels. // - in: query // name: all - // type: bool + // type: boolean // description: prune all images // produces: // - application/json // responses: - // '200': - // items: - // $ref: "#/responses/DocsImageDeleteResponse" - // '500': - // $ref: '#/responses/InternalError' + // 200: + // $ref: "#/responses/DocsImageDeleteResponse" + // 500: + // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/prune"), APIHandler(s.Context, libpod.PruneImages)).Methods(http.MethodPost) // swagger:operation GET /libpod/images/search libpod libpodSearchImages // --- @@ -471,7 +660,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: term to search // - in: query // name: limit - // type: int + // type: integer // description: maximum number of results // - in: query // name: filters @@ -484,41 +673,42 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '200': - // schema: - // items: - // $ref: "#/responses/DocsSearchResponse" - // '500': + // 200: + // $ref: "#/responses/DocsSearchResponse" + // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet) - // swagger:operation DELETE /libpod/images/{nameOrID} libpod libpodRemoveImage + // swagger:operation DELETE /libpod/images/{name} libpod libpodRemoveImage // --- // tags: // - images // summary: Remove Image // description: Delete an image from local store // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: name or ID of image to delete // - in: query // name: force - // type: bool + // type: boolean // description: remove the image even if used by containers or has other tags // produces: // - application/json // responses: - // '200': - // schema: - // items: - // $ref: "#/responses/DocsIageDeleteResponse" - // '400': - // $ref: "#/responses/BadParamError" - // '404': - // $ref: '#/responses/NoSuchImage' - // '409': - // $ref: '#/responses/ConflictError' - // '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 libpod libpoodExportImage + // 200: + // $ref: "#/responses/DocsImageDeleteResponse" + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: '#/responses/NoSuchImage' + // 409: + // $ref: '#/responses/ConflictError' + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/libpod/images/name"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete) + // swagger:operation GET /libpod/images/{name}/get libpod libpoodExportImage // --- // tags: // - images @@ -526,7 +716,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Export an image as a tarball // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -535,22 +726,22 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: format for exported image // - in: query // name: compress - // type: bool + // type: boolean // description: use compression on image // produces: // - application/json // responses: - // '200': + // 200: // description: no error // schema: // type: string // format: binary - // '404': - // $ref: '#/responses/NoSuchImage' - // '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 libpod libpodInspectImage + // 404: + // $ref: '#/responses/NoSuchImage' + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/libpod/images/{name}/get"), APIHandler(s.Context, libpod.ExportImage)).Methods(http.MethodGet) + // swagger:operation GET /libpod/images/{name}/json libpod libpodInspectImage // --- // tags: // - images @@ -558,20 +749,21 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Obtain low-level information about an image // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // produces: // - application/json // responses: - // '200': - // $ref: "#/responses/DocsLibpodInspectImageResponse" - // '404': - // $ref: '#/responses/NoSuchImage' - // '500': - // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/libpod/images/{name:..*}/json"), APIHandler(s.Context, libpod.GetImage)) - // swagger:operation POST /libpod/images/{nameOrID}/tag libpod libpodTagImage + // 200: + // $ref: "#/responses/DocsLibpodInspectImageResponse" + // 404: + // $ref: '#/responses/NoSuchImage' + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/libpod/images/{name}/json"), APIHandler(s.Context, libpod.GetImage)) + // swagger:operation POST /libpod/images/{name}/tag libpod libpodTagImage // --- // tags: // - images @@ -579,7 +771,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Tag an image so that it becomes part of a repository. // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the container // - in: query @@ -593,18 +786,17 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // produces: // - application/json // responses: - // '201': + // 201: // description: no error - // '400': - // $ref: '#/responses/BadParamError' - // '404': - // $ref: '#/responses/NoSuchImage' - // '409': - // $ref: '#/responses/ConflictError' - // '500': - // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/libpod/images/{name:..*}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost) + // 400: + // $ref: '#/responses/BadParamError' + // 404: + // $ref: '#/responses/NoSuchImage' + // 409: + // $ref: '#/responses/ConflictError' + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/libpod/images/{name}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost) - r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost) return nil } diff --git a/pkg/api/server/register_info.go b/pkg/api/server/register_info.go index a7fb18721..8c50fed7f 100644 --- a/pkg/api/server/register_info.go +++ b/pkg/api/server/register_info.go @@ -10,15 +10,17 @@ import ( func (s *APIServer) registerInfoHandlers(r *mux.Router) error { // swagger:operation GET /info libpod libpodGetInfo // --- + // tags: + // - system // summary: Get info // description: Returns information on the system and libpod configuration // produces: // - application/json // responses: - // '200': + // 200: // description: to be determined - // '500': - // "$ref": "#/responses/InternalError" + // 500: + // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/info"), APIHandler(s.Context, generic.GetInfo)).Methods(http.MethodGet) return nil } diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go index 5069326b6..1ef14b58c 100644 --- a/pkg/api/server/register_pods.go +++ b/pkg/api/server/register_pods.go @@ -16,17 +16,15 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // parameters: // - in: query // name: filters - // descriptions: needs description and plumbing for filters + // type: string + // description: needs description and plumbing for filters // responses: - // '200': - // properties: - // items: - // $ref: "#/responses/ListPodsResponse" - // type: array - // '400': - // $ref: "#/responses/BadParamError" - // '500': - // $ref: "#/responses/InternalError" + // 200: + // $ref: "#/responses/ListPodsResponse" + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/libpod/pods/json"), APIHandler(s.Context, libpod.Pods)).Methods(http.MethodGet) r.Handle(VersionedPath("/libpod/pods/create"), APIHandler(s.Context, libpod.PodCreate)).Methods(http.MethodPost) // swagger:operation POST /libpod/pods/prune pods PrunePods @@ -36,61 +34,63 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // - in: query // name: force // description: force delete - // type: bool + // type: boolean // default: false // produces: // - application/json // responses: - // '204': - // description: no error - // '400': - // $ref: "#/responses/BadParamError" - // '500': - // $ref: "#/responses/InternalError" + // 204: + // description: no error + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/libpod/pods/prune"), APIHandler(s.Context, libpod.PodPrune)).Methods(http.MethodPost) - // swagger:operation DELETE /libpod/pods/{nameOrID} pods removePod + // swagger:operation DELETE /libpod/pods/{name} pods removePod // --- // summary: Remove pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // - in: query // name: force - // type: bool + // type: boolean // description: force delete // responses: - // '204': - // description: no error - // '400': - // $ref: "#/responses/BadParamError" - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}"), APIHandler(s.Context, libpod.PodDelete)).Methods(http.MethodDelete) - // swagger:operation GET /libpod/pods/{nameOrID}/json pods inspectPod + // 204: + // description: no error + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}"), APIHandler(s.Context, libpod.PodDelete)).Methods(http.MethodDelete) + // swagger:operation GET /libpod/pods/{name}/json pods inspectPod // --- // summary: Inspect pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // responses: - // '200': - // $ref: "#/responses/InspectPodResponse" - // '404': + // 200: + // $ref: "#/responses/InspectPodResponse" + // 404: // $ref: "#/responses/NoSuchPod" - // '500': + // 500: // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/json"), APIHandler(s.Context, libpod.PodInspect)).Methods(http.MethodGet) - // swagger:operation GET /libpod/pods/{nameOrID}/exists pods podExists + r.Handle(VersionedPath("/libpod/pods/{name}/json"), APIHandler(s.Context, libpod.PodInspect)).Methods(http.MethodGet) + // swagger:operation GET /libpod/pods/{name}/exists pods podExists // --- // summary: Pod exists // description: Check if a pod exists by name or ID @@ -98,142 +98,151 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // responses: - // '204': - // description: pod exists - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/exists"), APIHandler(s.Context, libpod.PodExists)).Methods(http.MethodGet) - // swagger:operation POST /libpod/pods/{nameOrID}/kill pods killPod + // 204: + // description: pod exists + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/exists"), APIHandler(s.Context, libpod.PodExists)).Methods(http.MethodGet) + // swagger:operation POST /libpod/pods/{name}/kill pods killPod // --- // summary: Kill a pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // - in: query // name: signal - // type: int + // type: string // description: signal to be sent to pod + // default: SIGKILL // responses: - // '204': - // description: no error - // '400': - // $ref: "#/responses/BadParamError" - // '404': - // $ref: "#/responses/NoSuchPod" - // '409': - // $ref: "#/responses/ConflictError" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/kill"), APIHandler(s.Context, libpod.PodKill)).Methods(http.MethodPost) - // swagger:operation POST /libpod/pods/{nameOrID}/pause pods pausePod + // 204: + // description: no error + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchPod" + // 409: + // $ref: "#/responses/ConflictError" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/kill"), APIHandler(s.Context, libpod.PodKill)).Methods(http.MethodPost) + // swagger:operation POST /libpod/pods/{name}/pause pods pausePod // --- // summary: Pause a pod + // description: Pause a pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // responses: - // '204': - // description: no error - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/pause"), APIHandler(s.Context, libpod.PodPause)).Methods(http.MethodPost) - // swagger:operation POST /libpod/pods/{nameOrID}/restart pods restartPod + // 204: + // description: no error + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/pause"), APIHandler(s.Context, libpod.PodPause)).Methods(http.MethodPost) + // swagger:operation POST /libpod/pods/{name}/restart pods restartPod // --- // summary: Restart a pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // responses: - // '204': - // description: no error - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/restart"), APIHandler(s.Context, libpod.PodRestart)).Methods(http.MethodPost) - // swagger:operation POST /libpod/pods/{nameOrID}/start pods startPod + // 204: + // description: no error + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/restart"), APIHandler(s.Context, libpod.PodRestart)).Methods(http.MethodPost) + // swagger:operation POST /libpod/pods/{name}/start pods startPod // --- // summary: Start a pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // responses: - // '204': - // description: no error - // '304': - // $ref: "#/responses/PodAlreadyStartedError" - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/start"), APIHandler(s.Context, libpod.PodStart)).Methods(http.MethodPost) - // swagger:operation POST /libpod/pods/{nameOrID}/stop pods stopPod + // 204: + // description: no error + // 304: + // $ref: "#/responses/PodAlreadyStartedError" + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/start"), APIHandler(s.Context, libpod.PodStart)).Methods(http.MethodPost) + // swagger:operation POST /libpod/pods/{name}/stop pods stopPod // --- // summary: Stop a pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // - in: query // name: t - // type: int + // type: integer // description: timeout // responses: - // '204': - // description: no error - // '304': - // $ref: "#/responses/PodAlreadyStoppedError" - // '400': - // $ref: "#/responses/BadParamError" - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/stop"), APIHandler(s.Context, libpod.PodStop)).Methods(http.MethodPost) - // swagger:operation POST /libpod/pods/{nameOrID}/unpause pods unpausePod + // 204: + // description: no error + // 304: + // $ref: "#/responses/PodAlreadyStoppedError" + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/stop"), APIHandler(s.Context, libpod.PodStop)).Methods(http.MethodPost) + // swagger:operation POST /libpod/pods/{name}/unpause pods unpausePod // --- // summary: Unpause a pod // produces: // - application/json // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the pod // responses: - // '204': - // description: no error - // '404': - // $ref: "#/responses/NoSuchPod" - // '500': - // $ref: "#/responses/InternalError" - r.Handle(VersionedPath("/libpod/pods/{name:..*}/unpause"), APIHandler(s.Context, libpod.PodUnpause)).Methods(http.MethodPost) + // 204: + // description: no error + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/{name}/unpause"), APIHandler(s.Context, libpod.PodUnpause)).Methods(http.MethodPost) return nil } diff --git a/pkg/api/server/register_volumes.go b/pkg/api/server/register_volumes.go index 34138cfbf..d34c71238 100644 --- a/pkg/api/server/register_volumes.go +++ b/pkg/api/server/register_volumes.go @@ -31,12 +31,13 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.Handle("/libpod/volumes/prune", APIHandler(s.Context, libpod.PruneVolumes)).Methods(http.MethodPost) - // swagger:operation GET /volumes/{nameOrID}/json volumes inspectVolume + // swagger:operation GET /volumes/{name}/json volumes inspectVolume // --- // summary: Inspect volume // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the volume // produces: @@ -48,30 +49,31 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // "$ref": "#/responses/NoSuchVolume" // '500': // "$ref": "#/responses/InternalError" - r.Handle("/libpod/volumes/{name:..*}/json", APIHandler(s.Context, libpod.InspectVolume)).Methods(http.MethodGet) - // swagger:operation DELETE /volumes/{nameOrID} volumes removeVolume + r.Handle("/libpod/volumes/{name}/json", APIHandler(s.Context, libpod.InspectVolume)).Methods(http.MethodGet) + // swagger:operation DELETE /volumes/{name} volumes removeVolume // --- // summary: Remove volume // parameters: // - in: path - // name: nameOrID + // name: name + // type: string // required: true // description: the name or ID of the volume // - in: query // name: force - // type: bool + // type: boolean // description: force removal // produces: // - application/json // responses: - // '204': - // description: no error - // '400': - // "$ref": "#/responses/BadParamError" - // '404': - // "$ref": "#/responses/NoSuchVolume" - // '500': - // "$ref": "#/responses/InternalError" - r.Handle("/libpod/volumes/{name:..*}", APIHandler(s.Context, libpod.RemoveVolume)).Methods(http.MethodDelete) + // 204: + // description: no error + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchVolume" + // 500: + // $ref: "#/responses/InternalError" + r.Handle("/libpod/volumes/{name}", APIHandler(s.Context, libpod.RemoveVolume)).Methods(http.MethodDelete) return nil } diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index 2bda5ad01..847d11c3c 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -1,32 +1,3 @@ -// Package serviceapi Provides a Container compatible interface. -// -// This documentation describes the HTTP LibPod interface -// -// Schemes: http, https -// Host: podman.io -// BasePath: / -// Version: 0.0.1 -// License: Apache-2.0 https://opensource.org/licenses/Apache-2.0 -// Contact: Podman <podman@lists.podman.io> https://podman.io/community/ -// -// Consumes: -// - application/json -// - application/x-tar -// -// Produces: -// - application/json -// - text/plain -// - text/html -// -// tags: -// - name: "Containers" -// description: manage containers -// - name: "Images" -// description: manage images -// - name: "System" -// description: manage system resources -// -// swagger:meta package server import ( @@ -48,9 +19,9 @@ import ( ) type APIServer struct { - http.Server // Where the HTTP work happens + http.Server // The HTTP work happens here *schema.Decoder // Decoder for Query parameters to structs - context.Context // Context for graceful server shutdown + context.Context // Context to carry objects to handlers *libpod.Runtime // Where the real work happens net.Listener // mux for routing HTTP API calls to libpod routines context.CancelFunc // Stop APIServer @@ -58,14 +29,37 @@ type APIServer struct { time.Duration // Duration of client access sliding window } -// NewServer will create and configure a new API HTTP server +// Number of seconds to wait for next request, if exceeded shutdown server +const ( + DefaultServiceDuration = 300 * time.Second + UnlimitedServiceDuration = 0 * time.Second +) + +// NewServer will create and configure a new API server with all defaults func NewServer(runtime *libpod.Runtime) (*APIServer, error) { - listeners, err := activation.Listeners() - if err != nil { - return nil, errors.Wrap(err, "Cannot retrieve file descriptors from systemd") - } - if len(listeners) != 1 { - return nil, errors.Errorf("Wrong number of file descriptors from systemd for socket activation (%d != 1)", len(listeners)) + return newServer(runtime, DefaultServiceDuration, nil) +} + +// NewServerWithSettings will create and configure a new API server using provided settings +func NewServerWithSettings(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (*APIServer, error) { + return newServer(runtime, duration, listener) +} + +func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (*APIServer, error) { + // If listener not provided try socket activation protocol + if listener == nil { + if _, found := os.LookupEnv("LISTEN_FDS"); !found { + return nil, errors.Errorf("Cannot create Server, no listener provided and socket activation protocol is not active.") + } + + listeners, err := activation.Listeners() + if err != nil { + return nil, errors.Wrap(err, "Cannot retrieve file descriptors from systemd") + } + if len(listeners) != 1 { + return nil, errors.Errorf("Wrong number of file descriptors for socket activation protocol (%d != 1)", len(listeners)) + } + listener = &listeners[0] } router := mux.NewRouter() @@ -80,9 +74,9 @@ func NewServer(runtime *libpod.Runtime) (*APIServer, error) { Decoder: schema.NewDecoder(), Context: nil, Runtime: runtime, - Listener: listeners[0], + Listener: *listener, CancelFunc: nil, - Duration: 300 * time.Second, + Duration: duration, } server.Timer = time.AfterFunc(server.Duration, func() { if err := server.Shutdown(); err != nil { @@ -176,6 +170,11 @@ func (s *APIServer) Serve() error { // Shutdown is a clean shutdown waiting on existing clients func (s *APIServer) Shutdown() error { + // Duration == 0 flags no auto-shutdown of server + if s.Duration == 0 { + return nil + } + // We're still in the sliding service window if s.Timer.Stop() { s.Timer.Reset(s.Duration) diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go index dbf499ce7..f6643600a 100644 --- a/pkg/api/server/swagger.go +++ b/pkg/api/server/swagger.go @@ -41,7 +41,7 @@ type swagErrNoSuchPod struct { } } -// Internal error +// Internal server error // swagger:response InternalError type swagInternalError struct { // in:body @@ -59,7 +59,7 @@ type swagGenericError struct { } } -// Conflict error +// Conflict error in operation // swagger:response ConflictError type swagConflictError struct { // in:body @@ -68,7 +68,7 @@ type swagConflictError struct { } } -// Bad parameter +// Bad parameter in request // swagger:response BadParamError type swagBadParamError struct { // in:body @@ -134,3 +134,23 @@ type swagListContainers struct { // swagger:response tbd type swagTBD struct { } + +// Success +// swagger:response +type swag struct { + // in:body + Body struct { + // example: OK + ok string + } +} + +// Success +// swagger:response +type ok struct { + // in:body + Body struct { + // example: OK + ok string + } +} diff --git a/pkg/bindings/containers.go b/pkg/bindings/containers.go index 01f68f970..057580088 100644 --- a/pkg/bindings/containers.go +++ b/pkg/bindings/containers.go @@ -126,11 +126,11 @@ func (c Connection) ContainerExists(nameOrID string) (bool, error) { return false, nil } -func (c Connection) StopContainer(nameOrID string, timeout int) error { - // TODO we might need to distinguish whether a timeout is desired; a zero, the int - // zero value is valid; what do folks want to do? +func (c Connection) StopContainer(nameOrID string, timeout *int) error { params := make(map[string]string) - params["t"] = strconv.Itoa(timeout) + if timeout != nil { + params["t"] = strconv.Itoa(*timeout) + } response, err := c.newRequest(http.MethodPost, fmt.Sprintf("/containers/%s/stop", nameOrID), nil, params) if err != nil { return err diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index 6b28b2759..96786223d 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -97,8 +97,7 @@ type controllerHandler interface { } const ( - cgroupRoot = "/sys/fs/cgroup" - _cgroup2SuperMagic = 0x63677270 + cgroupRoot = "/sys/fs/cgroup" // CPU is the cpu controller CPU = "cpu" // CPUAcct is the cpuacct controller diff --git a/pkg/cgroups/cgroups_supported.go b/pkg/cgroups/cgroups_supported.go index 2a36777d4..a9fef38b9 100644 --- a/pkg/cgroups/cgroups_supported.go +++ b/pkg/cgroups/cgroups_supported.go @@ -12,6 +12,7 @@ import ( "syscall" "github.com/pkg/errors" + "golang.org/x/sys/unix" ) var ( @@ -27,7 +28,7 @@ func IsCgroup2UnifiedMode() (bool, error) { if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil { isUnified, isUnifiedErr = false, err } else { - isUnified, isUnifiedErr = st.Type == _cgroup2SuperMagic, nil + isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil } }) return isUnified, isUnifiedErr diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 193c788c0..041a161dc 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -266,6 +266,8 @@ static void __attribute__((constructor)) init() char path[PATH_MAX]; const char *const suffix = "/libpod/pause.pid"; char *cwd = getcwd (NULL, 0); + char uid_fmt[16]; + char gid_fmt[16]; if (cwd == NULL) { @@ -324,6 +326,13 @@ static void __attribute__((constructor)) init() exit (EXIT_FAILURE); } + sprintf (uid_fmt, "%d", uid); + sprintf (gid_fmt, "%d", gid); + + setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1); + setenv ("_CONTAINERS_ROOTLESS_UID", uid_fmt, 1); + setenv ("_CONTAINERS_ROOTLESS_GID", gid_fmt, 1); + r = setns (fd, 0); if (r < 0) { diff --git a/pkg/spec/namespaces.go b/pkg/spec/namespaces.go index e62d4ed0a..1f98e6e25 100644 --- a/pkg/spec/namespaces.go +++ b/pkg/spec/namespaces.go @@ -213,8 +213,8 @@ func (c *CgroupConfig) ToCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCre options = append(options, libpod.WithCgroupParent(c.CgroupParent)) } - if c.Cgroups == "disabled" { - options = append(options, libpod.WithNoCgroups()) + if c.Cgroups != "" { + options = append(options, libpod.WithCgroupsMode(c.Cgroups)) } return options, nil diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 7a220012f..cae055bb0 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -358,10 +358,10 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM return nil, errors.New("cannot specify resource limits when cgroups are disabled is specified") } configSpec.Linux.Resources = &spec.LinuxResources{} - case "enabled", "": + case "enabled", "no-conmon", "": // Do nothing default: - return nil, errors.New("unrecognized option for cgroups; supported are 'default' and 'disabled'") + return nil, errors.New("unrecognized option for cgroups; supported are 'default', 'disabled', 'no-conmon'") } // Add annotations diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemdgen/systemdgen.go index 745b708e4..26b3b3756 100644 --- a/pkg/systemdgen/systemdgen.go +++ b/pkg/systemdgen/systemdgen.go @@ -153,13 +153,14 @@ func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, erro if len(info.CreateCommand) < index+1 { return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand) } - // We're hard-coding the first four arguments and append the - // CreatCommand with a stripped command and subcomand. + // We're hard-coding the first five arguments and append the + // CreateCommand with a stripped command and subcomand. command := []string{ info.Executable, "run", "--conmon-pidfile", "/%t/%n-pid", "--cidfile", "/%t/%n-cid", + "--cgroups=no-conmon", } command = append(command, info.CreateCommand[index:]...) info.RunCommand = strings.Join(command, " ") diff --git a/pkg/systemdgen/systemdgen_test.go b/pkg/systemdgen/systemdgen_test.go index 9c6933d17..ee2429407 100644 --- a/pkg/systemdgen/systemdgen_test.go +++ b/pkg/systemdgen/systemdgen_test.go @@ -122,7 +122,7 @@ Documentation=man:podman-generate-systemd(1) [Service] Restart=always ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid -ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN +ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --cgroups=no-conmon --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN ExecStop=/usr/bin/podman stop --ignore --cidfile /%t/%n-cid -t 42 ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile /%t/%n-cid PIDFile=/%t/%n-pid |