summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers.go67
-rw-r--r--pkg/api/Makefile3
-rw-r--r--pkg/api/handlers/containers_top.go21
-rw-r--r--pkg/api/handlers/generic/config.go9
-rw-r--r--pkg/api/handlers/generic/containers_create.go6
-rw-r--r--pkg/api/handlers/generic/containers_stats.go76
-rw-r--r--pkg/api/handlers/generic/images.go2
-rw-r--r--pkg/api/handlers/generic/swagger.go23
-rw-r--r--pkg/api/handlers/libpod/containers.go9
-rw-r--r--pkg/api/handlers/swagger.go8
-rw-r--r--pkg/api/handlers/types.go1
-rw-r--r--pkg/api/handlers/utils/handler.go17
-rw-r--r--pkg/api/server/register_containers.go428
-rw-r--r--pkg/api/server/register_events.go2
-rw-r--r--pkg/api/server/register_images.go287
-rw-r--r--pkg/api/server/register_info.go14
-rw-r--r--pkg/api/server/register_pods.go73
-rw-r--r--pkg/api/server/register_volumes.go16
-rw-r--r--pkg/api/server/swagger.go11
-rw-r--r--pkg/api/tags.yaml13
-rw-r--r--pkg/apparmor/apparmor_linux_test.go2
-rw-r--r--pkg/bindings/connection.go62
-rw-r--r--pkg/bindings/containers.go6
-rw-r--r--pkg/bindings/errors.go46
-rw-r--r--pkg/bindings/images.go111
-rw-r--r--pkg/bindings/pods.go3
-rw-r--r--pkg/bindings/volumes.go2
-rw-r--r--pkg/hooks/1.0.0/when_test.go30
-rw-r--r--pkg/hooks/exec/exec_test.go6
-rw-r--r--pkg/hooks/exec/runtimeconfigfilter_test.go5
-rw-r--r--pkg/network/network_test.go5
-rw-r--r--pkg/network/subnet_test.go13
-rw-r--r--pkg/spec/config_linux_cgo.go12
-rw-r--r--pkg/spec/createconfig.go67
-rw-r--r--pkg/systemdgen/systemdgen_test.go18
-rw-r--r--pkg/tracing/tracing.go3
36 files changed, 934 insertions, 543 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 8b21d6b94..f66999ffa 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -27,7 +27,6 @@ import (
"github.com/containers/libpod/libpod/logs"
"github.com/containers/libpod/pkg/adapter/shortcuts"
"github.com/containers/libpod/pkg/systemdgen"
- "github.com/containers/psgo"
"github.com/containers/storage"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -913,71 +912,7 @@ func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
return nil, errors.Wrapf(err, "unable to lookup requested container")
}
- output, psgoErr := container.Top(descriptors)
- if psgoErr == nil {
- return output, nil
- }
-
- // If we encountered an ErrUnknownDescriptor error, fallback to executing
- // ps(1). This ensures backwards compatibility to users depending on ps(1)
- // and makes sure we're ~compatible with docker.
- if errors.Cause(psgoErr) != psgo.ErrUnknownDescriptor {
- return nil, psgoErr
- }
-
- output, err = r.execPS(container, descriptors)
- if err != nil {
- // Note: return psgoErr to guide users into using the AIX descriptors
- // instead of using ps(1).
- return nil, psgoErr
- }
-
- // Trick: filter the ps command from the output instead of
- // checking/requiring PIDs in the output.
- filtered := []string{}
- cmd := strings.Join(descriptors, " ")
- for _, line := range output {
- if !strings.Contains(line, cmd) {
- filtered = append(filtered, line)
- }
- }
-
- return filtered, nil
-}
-
-func (r *LocalRuntime) execPS(c *libpod.Container, args []string) ([]string, error) {
- rPipe, wPipe, err := os.Pipe()
- if err != nil {
- return nil, err
- }
- defer wPipe.Close()
- defer rPipe.Close()
-
- streams := new(libpod.AttachStreams)
- streams.OutputStream = wPipe
- streams.ErrorStream = wPipe
- streams.InputStream = bufio.NewReader(os.Stdin)
- streams.AttachOutput = true
- streams.AttachError = true
- streams.AttachInput = true
-
- psOutput := []string{}
- go func() {
- scanner := bufio.NewScanner(rPipe)
- for scanner.Scan() {
- psOutput = append(psOutput, scanner.Text())
- }
- }()
-
- cmd := append([]string{"ps"}, args...)
- ec, err := c.Exec(false, false, map[string]string{}, cmd, "", "", streams, 0, nil, "")
- if err != nil {
- return nil, err
- } else if ec != 0 {
- return nil, errors.Errorf("Runtime failed with exit status: %d and output: %s", ec, strings.Join(psOutput, " "))
- }
-
- return psOutput, nil
+ return container.Top(descriptors)
}
// ExecContainer executes a command in the container
diff --git a/pkg/api/Makefile b/pkg/api/Makefile
new file mode 100644
index 000000000..5fb4e7da5
--- /dev/null
+++ b/pkg/api/Makefile
@@ -0,0 +1,3 @@
+swagger:
+ swagger generate spec -o swagger.yaml -w ./
+ cat tags.yaml >> swagger.yaml
diff --git a/pkg/api/handlers/containers_top.go b/pkg/api/handlers/containers_top.go
index bab559da1..6b7688eb0 100644
--- a/pkg/api/handlers/containers_top.go
+++ b/pkg/api/handlers/containers_top.go
@@ -5,7 +5,6 @@ import (
"strings"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
@@ -16,10 +15,14 @@ func TopContainer(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
+ defaultValue := "-ef"
+ if utils.IsLibpodRequest(r) {
+ defaultValue = ""
+ }
query := struct {
PsArgs string `schema:"ps_args"`
}{
- PsArgs: "-ef",
+ PsArgs: defaultValue,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
@@ -28,23 +31,13 @@ func TopContainer(w http.ResponseWriter, r *http.Request) {
}
name := mux.Vars(r)["name"]
- ctnr, err := runtime.LookupContainer(name)
+ c, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
return
}
- state, err := ctnr.State()
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- if state != define.ContainerStateRunning {
- utils.ContainerNotRunning(w, name, errors.Errorf("Container %s must be running to perform top operation", name))
- return
- }
-
- output, err := ctnr.Top([]string{})
+ output, err := c.Top([]string{query.PsArgs})
if err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/handlers/generic/config.go b/pkg/api/handlers/generic/config.go
new file mode 100644
index 000000000..f715d25eb
--- /dev/null
+++ b/pkg/api/handlers/generic/config.go
@@ -0,0 +1,9 @@
+package generic
+
+// ContainerCreateResponse is the response struct for creating a container
+type ContainerCreateResponse struct {
+ // ID of the container created
+ Id string `json:"Id"`
+ // Warnings during container creation
+ Warnings []string `json:"Warnings"`
+}
diff --git a/pkg/api/handlers/generic/containers_create.go b/pkg/api/handlers/generic/containers_create.go
index ef5337abd..f98872690 100644
--- a/pkg/api/handlers/generic/containers_create.go
+++ b/pkg/api/handlers/generic/containers_create.go
@@ -71,11 +71,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
return
}
- type ctrCreateResponse struct {
- Id string `json:"Id"`
- Warnings []string `json:"Warnings"`
- }
- response := ctrCreateResponse{
+ response := ContainerCreateResponse{
Id: ctr.ID(),
Warnings: []string{}}
diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go
index 0c4efc1df..e33d37606 100644
--- a/pkg/api/handlers/generic/containers_stats.go
+++ b/pkg/api/handlers/generic/containers_stats.go
@@ -43,28 +43,26 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
return
}
+ // If the container isn't running, then let's not bother and return
+ // immediately.
state, err := ctnr.State()
if err != nil {
utils.InternalServerError(w, err)
return
}
if state != define.ContainerStateRunning && !query.Stream {
- utils.WriteJSON(w, http.StatusOK, &handlers.Stats{StatsJSON: docker.StatsJSON{
- Name: ctnr.Name(),
- ID: ctnr.ID(),
- }})
+ utils.InternalServerError(w, define.ErrCtrStateInvalid)
return
}
- var preRead time.Time
- var preCPUStats docker.CPUStats
-
stats, err := ctnr.GetContainerStats(&libpod.ContainerStats{})
if err != nil {
utils.InternalServerError(w, errors.Wrapf(err, "Failed to obtain Container %s stats", name))
return
}
+ var preRead time.Time
+ var preCPUStats docker.CPUStats
if query.Stream {
preRead = time.Now()
preCPUStats = docker.CPUStats{
@@ -78,25 +76,44 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
OnlineCPUs: 0,
ThrottlingData: docker.ThrottlingData{},
}
- time.Sleep(DefaultStatsPeriod)
}
- cgroupPath, _ := ctnr.CGroupPath()
- cgroup, _ := cgroups.Load(cgroupPath)
-
for ok := true; ok; ok = query.Stream {
- state, _ := ctnr.State()
- if state != define.ContainerStateRunning {
- time.Sleep(10 * time.Second)
- continue
+ // Container stats
+ stats, err := ctnr.GetContainerStats(stats)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ inspect, err := ctnr.Inspect(false)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ // Cgroup stats
+ cgroupPath, err := ctnr.CGroupPath()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ cgroup, err := cgroups.Load(cgroupPath)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ cgroupStat, err := cgroup.Stat()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
}
- stats, _ := ctnr.GetContainerStats(stats)
- cgroupStat, _ := cgroup.Stat()
- inspect, _ := ctnr.Inspect(false)
-
+ // FIXME: network inspection does not yet work entirely
net := make(map[string]docker.NetworkStats)
- net[inspect.NetworkSettings.EndpointID] = docker.NetworkStats{
+ networkName := inspect.NetworkSettings.EndpointID
+ if networkName == "" {
+ networkName = "network"
+ }
+ net[networkName] = docker.NetworkStats{
RxBytes: stats.NetInput,
RxPackets: 0,
RxErrors: 0,
@@ -127,13 +144,6 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
IoTimeRecursive: nil,
SectorsRecursive: nil,
},
- NumProcs: 0,
- StorageStats: docker.StorageStats{
- ReadCountNormalized: 0,
- ReadSizeBytes: 0,
- WriteCountNormalized: 0,
- WriteSizeBytes: 0,
- },
CPUStats: docker.CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: cgroupStat.CPU.Usage.Total,
@@ -174,17 +184,21 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
preRead = s.Read
bits, err := json.Marshal(s.CPUStats)
if err != nil {
- logrus.Errorf("unable to marshal cpu stats: %q", err)
+ logrus.Errorf("Unable to marshal cpu stats: %q", err)
}
if err := json.Unmarshal(bits, &preCPUStats); err != nil {
- logrus.Errorf("unable to unmarshal previous stats: %q", err)
+ logrus.Errorf("Unable to unmarshal previous stats: %q", err)
+ }
+
+ // Only sleep when we're streaming.
+ if query.Stream {
+ time.Sleep(DefaultStatsPeriod)
}
- time.Sleep(DefaultStatsPeriod)
}
}
func toBlkioStatEntry(entries []cgroups.BlkIOEntry) []docker.BlkioStatEntry {
- results := make([]docker.BlkioStatEntry, 0, len(entries))
+ results := make([]docker.BlkioStatEntry, len(entries))
for i, e := range entries {
bits, err := json.Marshal(e)
if err != nil {
diff --git a/pkg/api/handlers/generic/images.go b/pkg/api/handlers/generic/images.go
index 8029ee861..395f64064 100644
--- a/pkg/api/handlers/generic/images.go
+++ b/pkg/api/handlers/generic/images.go
@@ -350,7 +350,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Failed get images"))
return
}
- var summaries = make([]*handlers.ImageSummary, len(images))
+ var summaries = make([]*handlers.ImageSummary, len(images)+1)
for j, img := range images {
is, err := handlers.ImageToImageSummary(img)
if err != nil {
diff --git a/pkg/api/handlers/generic/swagger.go b/pkg/api/handlers/generic/swagger.go
new file mode 100644
index 000000000..27e1fc18d
--- /dev/null
+++ b/pkg/api/handlers/generic/swagger.go
@@ -0,0 +1,23 @@
+package generic
+
+// Create container
+// swagger:response ContainerCreateResponse
+type swagCtrCreateResponse struct {
+ // in:body
+ Body struct {
+ ContainerCreateResponse
+ }
+}
+
+// Wait container
+// swagger:response ContainerWaitResponse
+type swagCtrWaitResponse struct {
+ // in:body
+ Body struct {
+ // container exit code
+ StatusCode int
+ Error struct {
+ Message string
+ }
+ }
+}
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index bfb028b1b..388be24b6 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -30,11 +30,6 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) {
}
func RemoveContainer(w http.ResponseWriter, r *http.Request) {
- // 204 no error
- // 400 bad param
- // 404 no such container
- // 409 conflict
- // 500 internal error
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
@@ -143,9 +138,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
// timestamps
// tail string
}
-func StatsContainer(w http.ResponseWriter, r *http.Request) {
- //stream
-}
+
func CreateContainer(w http.ResponseWriter, r *http.Request) {
}
diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go
index b677a5a0b..c845c8195 100644
--- a/pkg/api/handlers/swagger.go
+++ b/pkg/api/handlers/swagger.go
@@ -57,9 +57,7 @@ type swagLibpodInspectImageResponse struct {
// swagger:response DocsContainerPruneReport
type swagContainerPruneReport struct {
// in: body
- Body struct {
- ContainersPruneReport
- }
+ Body []ContainersPruneReport
}
// Inspect container
@@ -84,9 +82,7 @@ type swagDockerTopResponse struct {
// swagger:response LibpodListContainersResponse
type swagLibpodListContainersResponse struct {
// in:body
- Body struct {
- shared.PsContainerOutput
- }
+ Body []shared.PsContainerOutput
}
// Inspect container
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 9edbbdccc..2526a3317 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -135,7 +135,6 @@ type Stats struct {
type ContainerTopOKBody struct {
dockerContainer.ContainerTopOKBody
- ID string `json:"Id"`
}
type PodCreateConfig struct {
diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go
index 8c2110f97..2fd9bffba 100644
--- a/pkg/api/handlers/utils/handler.go
+++ b/pkg/api/handlers/utils/handler.go
@@ -6,10 +6,18 @@ import (
"io"
"net/http"
"os"
+ "strings"
- log "github.com/sirupsen/logrus"
+ "github.com/sirupsen/logrus"
)
+// IsLibpodRequest returns true if the request related to a libpod endpoint
+// (e.g., /v2/libpod/...).
+func IsLibpodRequest(r *http.Request) bool {
+ split := strings.Split(r.URL.String(), "/")
+ return len(split) >= 3 && split[2] == "libpod"
+}
+
// WriteResponse encodes the given value as JSON or string and renders it for http client
func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
switch v := value.(type) {
@@ -18,14 +26,14 @@ func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
w.WriteHeader(code)
if _, err := fmt.Fprintln(w, v); err != nil {
- log.Errorf("unable to send string response: %q", err)
+ logrus.Errorf("unable to send string response: %q", err)
}
case *os.File:
w.Header().Set("Content-Type", "application/octet; charset=us-ascii")
w.WriteHeader(code)
if _, err := io.Copy(w, v); err != nil {
- log.Errorf("unable to copy to response: %q", err)
+ logrus.Errorf("unable to copy to response: %q", err)
}
default:
WriteJSON(w, code, value)
@@ -33,12 +41,13 @@ func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
}
func WriteJSON(w http.ResponseWriter, code int, value interface{}) {
+ // FIXME: we don't need to write the header in all/some circumstances.
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
coder := json.NewEncoder(w)
coder.SetEscapeHTML(true)
if err := coder.Encode(value); err != nil {
- log.Errorf("unable to write json: %q", err)
+ logrus.Errorf("unable to write json: %q", err)
}
}
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index af1881624..b275fa4d1 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -10,58 +10,80 @@ import (
)
func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
- // swagger:operation POST /containers/create containers createContainer
- //
- // Create a container
- //
+ // swagger:operation POST /containers/create compat containerCreate
// ---
- // produces:
- // - application/json
+ // summary: Create a container
+ // tags:
+ // - containers (compat)
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: query
+ // name: name
+ // type: string
+ // description: container name
+ // responses:
+ // '201':
+ // $ref: "#/responses/ContainerCreateResponse"
+ // '400':
+ // "$ref": "#/responses/BadParamError"
+ // '404':
+ // "$ref": "#/responses/NoSuchContainer"
+ // '409':
+ // "$ref": "#/responses/ConflictError"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/containers/create"), APIHandler(s.Context, generic.CreateContainer)).Methods(http.MethodPost)
+ // swagger:operation GET /containers/json compat listContainers
+ // ---
+ // tags:
+ // - containers (compat)
+ // summary: List containers
+ // description: Returns a list of containers
// parameters:
// - in: query
- // name: name
+ // name: filters
// type: string
- // description: container name
- // responses:
- // '201':
- // description: tbd
- // '400':
- // "$ref": "#/responses/BadParamError"
- // '404':
- // "$ref": "#/responses/NoSuchContainer"
- // '409':
- // "$ref": "#/types/ConflictError"
- // '500':
- // "$ref": "#/types/InternalError"
- r.HandleFunc(VersionedPath("/containers/create"), APIHandler(s.Context, generic.CreateContainer)).Methods(http.MethodPost)
- // swagger:operation GET /containers/json containers listContainers
- //
- // List containers
- //
- // ---
+ // description: |
+ // Returns a list of containers.
+ // - ancestor=(<image-name>[:<tag>], <image id>, or <image@digest>)
+ // - before=(<container id> or <container name>)
+ // - expose=(<port>[/<proto>]|<startport-endport>/[<proto>])
+ // - exited=<int> containers with exit code of <int>
+ // - health=(starting|healthy|unhealthy|none)
+ // - id=<ID> a container's ID
+ // - is-task=(true|false)
+ // - label=key or label="key=value" of a container label
+ // - name=<name> a container's name
+ // - network=(<network id> or <network name>)
+ // - publish=(<port>[/<proto>]|<startport-endport>/[<proto>])
+ // - since=(<container id> or <container name>)
+ // - status=(created|restarting|running|removing|paused|exited|dead)
+ // - volume=(<volume name> or <mount point destination>)
// produces:
// - application/json
// responses:
// '200':
- // schema:
- // type: array
- // items:
- // "$ref": "#/responses/Container"
+ // "$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 containers pruneContainers
- //
- // Prune unused containers
- //
+ // swagger:operation POST /containers/prune compat pruneContainers
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Delete stopped containers
+ // description: Remove containers not in use
// parameters:
// - in: query
// name: filters
- // type: map[string][]string
- // description: something
+ // type: string
+ // description: |
+ // Filters to process on the prune list, encoded as JSON (a `map[string][]string`). Available filters:
+ // - `until=<timestamp>` Prune containers created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
+ // - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune containers with (or without, in case `label!=...` is used) the specified labels.
// produces:
// - application/json
// responses:
@@ -70,11 +92,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/prune"), APIHandler(s.Context, generic.PruneContainers)).Methods(http.MethodPost)
- // swagger:operation DELETE /containers/{nameOrID} containers removeContainer
- //
- // Delete container
- //
+ // swagger:operation DELETE /containers/{nameOrID} compat removeContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Remove a container
// parameters:
// - in: path
// name: nameOrID
@@ -83,11 +105,13 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// - in: query
// name: force
// type: bool
- // description: need something
+ // default: false
+ // description: If the container is running, kill it before removing it.
// - in: query
// name: v
// type: bool
- // description: need something
+ // default: false
+ // description: Remove the volumes associated with the container.
// - in: query
// name: link
// type: bool
@@ -106,16 +130,22 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}"), APIHandler(s.Context, generic.RemoveContainer)).Methods(http.MethodDelete)
- // swagger:operation GET /containers/{nameOrID}/json containers getContainer
- //
- // Inspect Container
- //
+ // swagger:operation GET /containers/{nameOrID}/json compat getContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Inspect container
+ // description: Return low-level information about a container.
// parameters:
// - in: path
// name: nameOrID
// required: true
- // description: the name or ID of the container
+ // description: the name or id of the container
+ // - in: query
+ // name: size
+ // type: bool
+ // default: false
+ // description: include the size of the container
// produces:
// - application/json
// responses:
@@ -126,11 +156,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/json"), APIHandler(s.Context, generic.GetContainer)).Methods(http.MethodGet)
- // swagger:operation POST /containers/{nameOrID}/kill containers killContainer
- //
- // Kill Container
- //
+ // swagger:operation post /containers/{nameOrID}/kill compat killcontainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Kill container
+ // description: Signal to send to the container as an integer or string (e.g. SIGINT)
// parameters:
// - in: path
// name: nameOrID
@@ -152,11 +183,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/kill"), APIHandler(s.Context, generic.KillContainer)).Methods(http.MethodPost)
- // swagger:operation GET /containers/{nameOrID}/logs containers LogsFromContainer
- //
- // Get logs from container
- //
+ // swagger:operation GET /containers/{nameOrID}/logs compat LogsFromContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Get container logs
+ // description: Get stdout and stderr logs from a container.
// parameters:
// - in: path
// name: nameOrID
@@ -165,46 +197,49 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// - in: query
// name: follow
// type: bool
- // description: needs description
+ // description: Keep connection after returning logs.
// - in: query
// name: stdout
// type: bool
- // description: needs description
+ // description: not supported
// - in: query
// name: stderr
// type: bool
- // description: needs description
+ // description: not supported?
// - in: query
// name: since
// type: string
- // description: needs description
+ // description: Only return logs since this time, as a UNIX timestamp
// - in: query
// name: until
// type: string
- // description: needs description
+ // description: Only return logs before this time, as a UNIX timestamp
// - in: query
// name: timestamps
// type: bool
- // description: needs description
+ // default: false
+ // description: Add timestamps to every log line
// - in: query
// name: tail
// type: string
- // description: needs description
+ // description: Only return this number of log lines from the end of the logs
+ // default: all
// produces:
// - application/json
// responses:
// '200':
- // description: tbd
+ // 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 containers pauseContainer
- //
- // Pause Container
- //
+ // swagger:operation POST /containers/{nameOrID}/pause compat pauseContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Pause container
+ // description: Use the cgroups freezer to suspend all processes in a container.
// parameters:
// - in: path
// name: nameOrID
@@ -221,11 +256,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/pause"), APIHandler(s.Context, handlers.PauseContainer)).Methods(http.MethodPost)
r.HandleFunc(VersionedPath("/containers/{name:..*}/rename"), APIHandler(s.Context, handlers.UnsupportedHandler)).Methods(http.MethodPost)
- // swagger:operation POST /containers/{nameOrID}/restart containers restartContainer
- //
- // Restart Container
- //
+ // swagger:operation POST /containers/{nameOrID}/restart compat restartContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Restart container
// parameters:
// - in: path
// name: nameOrID
@@ -245,11 +280,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost)
- // swagger:operation POST /containers/{nameOrID}/start containers startContainer
- //
- // Start a container
- //
+ // swagger:operation POST /containers/{nameOrID}/start compat startContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Start a container
// parameters:
// - in: path
// name: nameOrID
@@ -271,11 +306,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost)
- // swagger:operation GET /containers/{nameOrID}/stats containers statsContainer
- //
- // Get stats for a container
- //
+ // swagger:operation GET /containers/{nameOrID}/stats compat statsContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Get stats for a container
+ // description: This returns a live stream of a container’s resource usage statistics.
// parameters:
// - in: path
// name: nameOrID
@@ -284,24 +320,23 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// - in: query
// name: stream
// type: bool
- // description: needs description
+ // default: true
+ // description: Stream the output
// produces:
// - application/json
// responses:
- // '204':
- // description: tbd
- // '304':
- // "$ref": "#/responses/ContainerAlreadyStartedError"
+ // '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 containers stopContainer
- //
- // Stop a container
- //
+ // swagger:operation POST /containers/{nameOrID}/stop compat stopContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Stop a container
// parameters:
// - in: path
// name: nameOrID
@@ -323,11 +358,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost)
- // swagger:operation GET /containers/{nameOrID}/top containers topContainer
- //
- // List processes running inside a container
- //
+ // swagger:operation GET /containers/{nameOrID}/top compat topContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: List processes running inside a container
// parameters:
// - in: path
// name: nameOrID
@@ -336,7 +371,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// - in: query
// name: ps_args
// type: string
- // description: arguments to pass to ps such as aux
+ // 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:
@@ -347,11 +382,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet)
- // swagger:operation POST /containers/{nameOrID}/unpause containers unpauseContainer
- //
- // Unpause Container
- //
+ // swagger:operation POST /containers/{nameOrID}/unpause compat unpauseContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Unpause container
+ // description: Resume a paused container
// parameters:
// - in: path
// name: nameOrID
@@ -362,17 +398,17 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// responses:
// '204':
// description: no error
- // schema:
// '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 containers waitContainer
- //
- // Wait on a container to exit
- //
+ // swagger:operation POST /containers/{nameOrID}/wait compat waitContainer
// ---
+ // tags:
+ // - containers (compat)
+ // summary: Wait on a container to exit
+ // description: Block until a container stops, then returns the exit code.
// parameters:
// - in: path
// name: nameOrID
@@ -385,8 +421,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// produces:
// - application/json
// responses:
- // '204':
- // description: no error
+ // '200':
+ // $ref: "#/responses/ContainerWaitResponse"
// '404':
// "$ref": "#/responses/NoSuchContainer"
// '500':
@@ -398,29 +434,29 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
*/
r.HandleFunc(VersionedPath("/libpod/containers/create"), APIHandler(s.Context, libpod.CreateContainer)).Methods(http.MethodPost)
- // swagger:operation GET /libpod/containers/json containers listContainers
- //
- // List containers
- //
+ // swagger:operation GET /libpod/containers/json libpod libpodListContainers
// ---
+ // tags:
+ // - containers
+ // summary: List containers
+ // description: Returns a list of containers
// produces:
// - application/json
// responses:
// '200':
// schema:
- // type: array
- // items:
// "$ref": "#/responses/LibpodListContainersResponse"
// '400':
// "$ref": "#/responses/BadParamError"
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/json"), APIHandler(s.Context, libpod.ListContainers)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/containers/prune containers pruneContainers
- //
- // Prune unused containers
- //
+ // swagger:operation POST /libpod/containers/prune libpod libpodPruneContainers
// ---
+ // tags:
+ // - containers
+ // summary: Prune unused containers
+ // description: Remove stopped and exited containers
// parameters:
// - in: query
// name: force
@@ -428,21 +464,25 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// description: something
// - in: query
// name: filters
- // type: map[string][]string
- // description: something
+ // type: string
+ // description: |
+ // Filters to process on the prune list, encoded as JSON (a `map[string][]string`). Available filters:
+ // - `until=<timestamp>` Prune containers created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
+ // - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune containers with (or without, in case `label!=...` is used) the specified labels.
// produces:
// - application/json
// responses:
// '200':
- // description: TBD
+ // description: to be determined
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/prune"), APIHandler(s.Context, libpod.PruneContainers)).Methods(http.MethodPost)
- // swagger:operation GET /libpod/containers/showmounted containers showMounterContainers
- //
- // Show mounted containers
- //
+ // swagger:operation GET /libpod/containers/showmounted libpod showMounterContainers
// ---
+ // tags:
+ // - containers
+ // summary: Show mounted containers
+ // description: Lists all mounted containers mount points
// produces:
// - application/json
// responses:
@@ -455,11 +495,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/showmounted"), APIHandler(s.Context, libpod.ShowMountedContainers)).Methods(http.MethodGet)
- // swagger:operation DELETE /libpod/containers/json containers removeContainer
- //
- // Delete container
- //
+ // swagger:operation DELETE /libpod/containers/json libpod libpodRemoveContainer
// ---
+ // tags:
+ // - containers
+ // summary: Delete container
// parameters:
// - in: path
// name: nameOrID
@@ -472,7 +512,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// - in: query
// name: v
// type: bool
- // description: need something
+ // description: delete volumes
// produces:
// - application/json
// responses:
@@ -487,11 +527,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}"), APIHandler(s.Context, libpod.RemoveContainer)).Methods(http.MethodDelete)
- // swagger:operation GET /libpod/containers/{nameOrID}/json containers getContainer
- //
- // Inspect Container
- //
+ // swagger:operation GET /libpod/containers/{nameOrID}/json libpod libpodGetContainer
// ---
+ // tags:
+ // - containers
+ // summary: Inspect container
+ // description: Return low-level information about a container.
// parameters:
// - in: path
// name: nameOrID
@@ -511,11 +552,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/json"), APIHandler(s.Context, libpod.GetContainer)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/containers/{nameOrID}/kill containers killContainer
- //
- // Kill Container
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/kill libpod libpodKillContainer
// ---
+ // tags:
+ // - containers
+ // summary: Kill container
+ // description: send a signal to a container, defaults to killing the container
// parameters:
// - in: path
// name: nameOrID
@@ -538,11 +580,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/kill"), APIHandler(s.Context, libpod.KillContainer)).Methods(http.MethodGet)
- // swagger:operation GET /libpod/containers/{nameOrID}/mount containers mountContainer
- //
- // Mount a container
- //
+ // swagger:operation GET /libpod/containers/{nameOrID}/mount libpod mountContainer
// ---
+ // tags:
+ // - containers
+ // summary: Mount a container
+ // description: Mount a container to the filesystem
// parameters:
// - in: path
// name: nameOrID
@@ -563,11 +606,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/mount"), APIHandler(s.Context, libpod.MountContainer)).Methods(http.MethodPost)
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/logs"), APIHandler(s.Context, libpod.LogsFromContainer)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/containers/{nameOrID}/pause containers pauseContainer
- //
- // Pause Container
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/pause libpod libpodPauseContainer
// ---
+ // tags:
+ // - containers
+ // summary: Pause a container
+ // description: Use the cgroups freezer to suspend all processes in a container.
// parameters:
// - in: path
// name: nameOrID
@@ -583,11 +627,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/pause"), APIHandler(s.Context, handlers.PauseContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{nameOrID}/restart containers restartContainer
- //
- // Restart Container
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/restart libpod libpodRestartContainer
// ---
+ // tags:
+ // - containers
+ // summary: Restart a container
// parameters:
// - in: path
// name: nameOrID
@@ -607,11 +651,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{nameOrID}/start containers startContainer
- //
- // Start a container
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/start libpod libpodStartContainer
// ---
+ // tags:
+ // - containers
+ // summary: Start a container
// parameters:
// - in: path
// name: nameOrID
@@ -633,11 +677,35 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost)
- r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/stats"), APIHandler(s.Context, libpod.StatsContainer)).Methods(http.MethodGet)
- r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/containers/{nameOrID}/unpause containers unpauseContainer
+ // swagger:operation GET /libpod/containers/{nameOrID}/stats libpod statsContainer
+ // ---
+ // tags:
+ // - containers
+ // summary: Get stats for a container
+ // description: This returns a live stream of a container’s resource usage statistics.
+ // parameters:
+ // - in: path
+ // name: nameOrID
+ // required: true
+ // description: the name or ID of the container
+ // - in: query
+ // name: stream
+ // type: bool
+ // 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("/libpod/containers/{name:..*}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/containers/{nameOrID}/top containers topContainer
//
- // Unpause Container
+ // List processes running inside a container. Note
//
// ---
// parameters:
@@ -645,6 +713,35 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// name: nameOrID
// required: true
// description: the name or ID of the container
+ // - in: query
+ // name: stream
+ // type: bool
+ // default: true
+ // description: Stream the output
+ // name: ps_args
+ // type: string
+ // 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':
+ // description: no error
+ // "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
+ // ---
+ // tags:
+ // - containers
+ // summary: Unpause Container
+ // parameters:
+ // - in: path
+ // name: nameOrID
+ // required: true
+ // description: the name or ID of the container
// produces:
// - application/json
// responses:
@@ -655,11 +752,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{nameOrID}/wait containers waitContainer
- //
- // Wait on a container to exit
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/wait libpod libpodWaitContainer
// ---
+ // tags:
+ // - containers
+ // summary: Wait on a container to exit
// parameters:
// - in: path
// name: nameOrID
@@ -679,11 +776,12 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/wait"), APIHandler(s.Context, libpod.WaitContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{nameOrID}/exists containers containerExists
- //
- // Check if container exists
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/exists libpod containerExists
// ---
+ // tags:
+ // - containers
+ // summary: Check if container exists
+ // description: Quick way to determine if a container exists by name or ID
// parameters:
// - in: path
// name: nameOrID
@@ -699,11 +797,11 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/exists"), APIHandler(s.Context, libpod.ContainerExists)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/containers/{nameOrID}/stop containers stopContainer
- //
- // Stop a container
- //
+ // swagger:operation POST /libpod/containers/{nameOrID}/stop libpod libpodStopContainer
// ---
+ // tags:
+ // - containers
+ // summary: Stop a container
// parameters:
// - in: path
// name: nameOrID
diff --git a/pkg/api/server/register_events.go b/pkg/api/server/register_events.go
index d764fdbb4..56cf96de1 100644
--- a/pkg/api/server/register_events.go
+++ b/pkg/api/server/register_events.go
@@ -26,7 +26,7 @@ func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error {
// description: OK
// "500":
// description: Failed
- // "$ref": "#/types/errorModel"
+ // "$ref": "#/responses/InternalError"
r.Handle(VersionedPath("/events"), APIHandler(s.Context, handlers.GetEvents))
return nil
}
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 488427f3c..cd42afe71 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -10,11 +10,13 @@ import (
)
func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
- // swagger:operation POST /images/create images createImage
- //
- // Create an image from an image
+ // swagger:operation POST /images/create compat createImage
//
// ---
+ // tags:
+ // - images (compat)
+ // summary: Create an image from an image
+ // description: Create an image by either pulling it from a registry or importing it.
// produces:
// - application/json
// parameters:
@@ -30,21 +32,22 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '200':
// schema:
// items:
- // $ref: "TBD"
+ // $ref: "to be determined"
// '404':
// description: repo or image does not exist
// schema:
- // $ref: "#/responses/generalError"
+ // $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 images createImage
- //
- // Create an image from Source
- //
+ // 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:
@@ -54,27 +57,28 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: needs description
// - in: query
// name: changes
- // type: TBD
+ // type: to be determined
// description: needs description
// responses:
// '200':
// schema:
// items:
- // $ref: "TBD"
+ // $ref: "to be determined"
// '404':
// description: repo or image does not exist
// schema:
- // $ref: "#/responses/generalError"
+ // $ref: "#/responses/InternalError"
// '500':
// description: unexpected error
// schema:
// $ref: '#/responses/GenericError'
r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromSrc)).Methods(http.MethodPost).Queries("fromSrc", "{fromSrc}")
- // swagger:operation GET /images/json images listImages
- //
- // List Images
- //
+ // swagger:operation GET /images/json compat listImages
// ---
+ // tags:
+ // - images (compat)
+ // summary: List Images
+ // description: Returns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image.
// produces:
// - application/json
// responses:
@@ -87,34 +91,47 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/images/json"), APIHandler(s.Context, generic.GetImages)).Methods(http.MethodGet)
- // swagger:operation POST /images/load images loadImage
- //
- // Import image
+ // swagger:operation POST /images/load compat loadImage
//
// ---
+ // tags:
+ // - images (compat)
+ // summary: Import image
+ // description: Load a set of images and tags into a repository.
// parameters:
// - in: query
// name: quiet
// type: bool
// description: not supported
+ // - in: body
+ // description: tarball of container image
+ // type: string
+ // format: binary
// produces:
// - application/json
// responses:
// '200':
- // description: TBD
+ // description: no error
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost)
- // swagger:operation POST /images/prune images pruneImages
- //
- // Prune unused images
- //
+ // swagger:operation POST /images/prune compat pruneImages
// ---
+ // tags:
+ // - images (compat)
+ // summary: Prune unused images
+ // description: Remove images from local storage that are not being used by a container
// parameters:
// - in: query
// name: filters
- // type: map[string][]string
- // description: not supported
+ // type: string
+ // description: |
+ // filters to apply to image pruning, encoded as JSON (map[string][]string). Available filters:
+ // - `dangling=<boolean>` When set to `true` (or `1`), prune only
+ // unused *and* untagged images. When set to `false`
+ // (or `0`), all unused images are pruned.
+ // - `until=<string>` Prune images created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
+ // - `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.
// produces:
// - application/json
// responses:
@@ -125,11 +142,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/images/prune"), APIHandler(s.Context, generic.PruneImages)).Methods(http.MethodPost)
- // swagger:operation GET /images/search images searchImages
- //
- // Search images
- //
+ // swagger:operation GET /images/search compat searchImages
// ---
+ // tags:
+ // - images (compat)
+ // summary: Search images
+ // description: Search registries for an image
// parameters:
// - in: query
// name: term
@@ -141,8 +159,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: maximum number of results
// - in: query
// name: filters
- // type: map[string][]string
- // description: TBD
+ // type: string
+ // description: |
+ // A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
+ // - `is-automated=(true|false)`
+ // - `is-official=(true|false)`
+ // - `stars=<number>` Matches images that has at least 'number' stars.
// produces:
// - application/json
// responses:
@@ -151,11 +173,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet)
- // swagger:operation DELETE /images/{nameOrID} images removeImage
- //
- // Remove Image
- //
+ // swagger:operation DELETE /images/{nameOrID} compat removeImage
// ---
+ // tags:
+ // - images (compat)
+ // summary: Remove Image
+ // description: Delete an image from local storage
// parameters:
// - in: query
// name: force
@@ -164,24 +187,25 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - in: query
// name: noprune
// type: bool
- // description: not supported
+ // description: not supported. will be logged as an invalid parameter if enabled
// produces:
// - application/json
// responses:
// '200':
// $ref: "#/responses/DocsImageDeleteResponse"
- // '404':
+ // '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 images exportImage
- //
- // Export an image
- //
+ // swagger:operation GET /images/{nameOrID}/get compat exportImage
// ---
+ // tags:
+ // - images (compat)
+ // summary: Export an image
+ // description: Export an image in tarball format
// parameters:
// - in: path
// name: nameOrID
@@ -191,17 +215,19 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - application/json
// responses:
// '200':
+ // description: no error
// schema:
- // $ref: "TBD"
- // description: TBD
+ // 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 images imageHistory
- //
- // History of an image
- //
+ // swagger:operation GET /images/{nameOrID}/history compat imageHistory
// ---
+ // tags:
+ // - images (compat)
+ // summary: History of an image
+ // description: Return parent layers of an image.
// parameters:
// - in: path
// name: nameOrID
@@ -217,11 +243,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: "#/responses/InternalError"
r.Handle(VersionedPath("/images/{name:..*}/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet)
- // swagger:operation GET /images/{nameOrID}/json images inspectImage
- //
- // Inspect an image
- //
+ // swagger:operation GET /images/{nameOrID}/json compat inspectImage
// ---
+ // tags:
+ // - images (compat)
+ // summary: Inspect an image
+ // description: Return low-level information about an image.
// parameters:
// - in: path
// name: nameOrID
@@ -237,11 +264,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: "#/responses/InternalError"
r.Handle(VersionedPath("/images/{name:..*}/json"), APIHandler(s.Context, generic.GetImage))
- // swagger:operation POST /images/{nameOrID}/tag images tagImage
- //
- // Tag an image
- //
+ // swagger:operation POST /images/{nameOrID}/tag compat tagImage
// ---
+ // tags:
+ // - images (compat)
+ // summary: Tag an image
+ // description: Tag an image so that it becomes part of a repository.
// parameters:
// - in: path
// name: nameOrID
@@ -269,11 +297,11 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/images/{name:..*}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost)
- // swagger:operation POST /commit/ commit commitContainer
- //
- // Create a new image from a container
- //
+ // swagger:operation POST /commit/ compat commitContainer
// ---
+ // tags:
+ // - commit (compat)
+ // summary: Create a new image from a container
// parameters:
// - in: query
// name: container
@@ -318,11 +346,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
libpod endpoints
*/
- // swagger:operation POST /libpod/images/{nameOrID}/exists images imageExists
- //
- // Check if image exists in local store
- //
+ // swagger:operation POST /libpod/images/{nameOrID}/exists libpod libpodImageExists
// ---
+ // tags:
+ // - images
+ // summary: Image exists
+ // description: Check if image exists in local store
// parameters:
// - in: path
// name: nameOrID
@@ -330,15 +359,6 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: the name or ID of the container
// produces:
// - application/json
- // parameters:
- // - in: query
- // name: fromImage
- // type: string
- // description: needs description
- // - in: query
- // name: tag
- // type: string
- // description: needs description
// responses:
// '204':
// description: image exists
@@ -348,11 +368,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/{name:..*}/exists"), APIHandler(s.Context, libpod.ImageExists))
r.Handle(VersionedPath("/libpod/images/{name:..*}/tree"), APIHandler(s.Context, libpod.ImageTree))
- // swagger:operation GET /libpod/images/{nameOrID}/history images imageHistory
- //
- // History of an image
- //
+ // swagger:operation GET /libpod/images/{nameOrID}/history libpod libpodImageHistory
// ---
+ // tags:
+ // - images
+ // summary: History of an image
+ // description: Return parent layers of an image.
// parameters:
// - in: path
// name: nameOrID
@@ -370,49 +391,60 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet)
- // swagger:operation GET /libpod/images/json images listImages
- //
- // List Images
- //
+ // swagger:operation GET /libpod/images/json libpod libpodListImages
// ---
+ // tags:
+ // - images
+ // summary: List Images
+ // description: Returns a list of images on the server
// produces:
// - application/json
// responses:
// '200':
- // schema:
- // items:
// $ref: "#/responses/DockerImageSummary"
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/json"), APIHandler(s.Context, libpod.GetImages)).Methods(http.MethodGet)
- // swagger:operation POST /libpod/images/load images loadImage
- //
- // Import image
- //
+ // swagger:operation POST /libpod/images/load libpod libpodLoadImage
// ---
+ // tags:
+ // - images
+ // summary: Import image
+ // description: Load a set of images and tags into a repository.
// parameters:
// - in: query
// name: quiet
// type: bool
// description: not supported
+ // - in: body
+ // description: tarball of container image
+ // type: string
+ // format: binary
// produces:
// - application/json
// responses:
// '200':
- // description: TBD
+ // description: no error
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/images/prune images pruneImages
- //
- // Prune unused images
- //
+ // swagger:operation POST /libpod/images/prune libpod libpodPruneImages
// ---
+ // tags:
+ // - images
+ // summary: Prune unused images
+ // description: Remove images that are not being used by a container
// parameters:
// - in: query
// name: filters
- // type: map[string][]string
- // description: image filters
+ // type: string
+ // description: |
+ // filters to apply to image pruning, encoded as JSON (map[string][]string). Available filters:
+ // - `dangling=<boolean>` When set to `true` (or `1`), prune only
+ // unused *and* untagged images. When set to `false`
+ // (or `0`), all unused images are pruned.
+ // - `until=<string>` Prune images created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
+ // - `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
@@ -421,17 +453,17 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - application/json
// responses:
// '200':
- // schema:
// items:
// $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 images searchImages
- //
- // Search images
- //
+ // swagger:operation GET /libpod/images/search libpod libpodSearchImages
// ---
+ // tags:
+ // - images
+ // summary: Search images
+ // description: Search registries for images
// parameters:
// - in: query
// name: term
@@ -443,8 +475,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: maximum number of results
// - in: query
// name: filters
- // type: map[string][]string
- // description: TBD
+ // type: string
+ // description: |
+ // A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
+ // - `is-automated=(true|false)`
+ // - `is-official=(true|false)`
+ // - `stars=<number>` Matches images that has at least 'number' stars.
// produces:
// - application/json
// responses:
@@ -455,20 +491,17 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet)
- // swagger:operation DELETE /libpod/images/{nameOrID} images removeImage
- //
- // Remove Image
- //
+ // swagger:operation DELETE /libpod/images/{nameOrID} libpod libpodRemoveImage
// ---
+ // tags:
+ // - images
+ // summary: Remove Image
+ // description: Delete an image from local store
// parameters:
// - in: query
// name: force
// type: bool
// description: remove the image even if used by containers or has other tags
- // - in: query
- // name: noprune
- // type: bool
- // description: not supported
// produces:
// - application/json
// responses:
@@ -476,6 +509,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// schema:
// items:
// $ref: "#/responses/DocsIageDeleteResponse"
+ // '400':
+ // $ref: "#/responses/BadParamError"
// '404':
// $ref: '#/responses/NoSuchImage'
// '409':
@@ -483,11 +518,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// '500':
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/{name:..*}"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete)
- // swagger:operation GET /libpod/images/{nameOrID}/get images exportImage
- //
- // Export an image
- //
+ // swagger:operation GET /libpod/images/{nameOrID}/get libpod libpoodExportImage
// ---
+ // tags:
+ // - images
+ // summary: Export an image
+ // description: Export an image as a tarball
// parameters:
// - in: path
// name: nameOrID
@@ -505,17 +541,21 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - application/json
// responses:
// '200':
- // description: TBD
+ // 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 images inspectImage
- //
- // Inspect an image
- //
+ // swagger:operation GET /libpod/images/{nameOrID}/json libpod libpodInspectImage
// ---
+ // tags:
+ // - images
+ // summary: Inspect an image
+ // description: Obtain low-level information about an image
// parameters:
// - in: path
// name: nameOrID
@@ -525,19 +565,18 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - application/json
// responses:
// '200':
- // schema:
- // items:
// $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 images tagImage
- //
- // Tag an image
- //
+ // swagger:operation POST /libpod/images/{nameOrID}/tag libpod libpodTagImage
// ---
+ // tags:
+ // - images
+ // summary: Tag an image
+ // description: Tag an image so that it becomes part of a repository.
// parameters:
// - in: path
// name: nameOrID
diff --git a/pkg/api/server/register_info.go b/pkg/api/server/register_info.go
index 797158553..a7fb18721 100644
--- a/pkg/api/server/register_info.go
+++ b/pkg/api/server/register_info.go
@@ -8,21 +8,17 @@ import (
)
func (s *APIServer) registerInfoHandlers(r *mux.Router) error {
- // swagger:operation GET /info libpod getInfo
- //
- // Returns information on the system and libpod configuration
- //
+ // swagger:operation GET /info libpod libpodGetInfo
// ---
+ // summary: Get info
+ // description: Returns information on the system and libpod configuration
// produces:
// - application/json
// responses:
// '200':
- // schema:
- // "$ref": "#/types/Info"
+ // description: to be determined
// '500':
- // description: unexpected error
- // schema:
- // "$ref": "#/types/ErrorModel"
+ // "$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 c2e10277e..5069326b6 100644
--- a/pkg/api/server/register_pods.go
+++ b/pkg/api/server/register_pods.go
@@ -9,10 +9,8 @@ import (
func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// swagger:operation GET /libpod/pods/json pods ListPods
- //
- // List Pods
- //
// ---
+ // summary: List pods
// produces:
// - application/json
// parameters:
@@ -21,23 +19,25 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// descriptions: needs description and plumbing for filters
// responses:
// '200':
- // $ref: "#/responses/ListPodsResponse"
+ // properties:
+ // items:
+ // $ref: "#/responses/ListPodsResponse"
+ // type: array
// '400':
// $ref: "#/responses/BadParamError"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Prune unused pods
- //
// ---
+ // summary: Prune unused pods
// parameters:
// - in: query
// name: force
// description: force delete
// type: bool
+ // default: false
// produces:
// - application/json
// responses:
@@ -46,13 +46,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '400':
// $ref: "#/responses/BadParamError"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Remove Pod
- //
// ---
+ // summary: Remove pod
// produces:
// - application/json
// parameters:
@@ -72,13 +70,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Inspect Pod
- //
// ---
+ // summary: Inspect pod
// produces:
// - application/json
// parameters:
@@ -92,13 +88,12 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Inspect Pod
- //
// ---
+ // summary: Pod exists
+ // description: Check if a pod exists by name or ID
// produces:
// - application/json
// parameters:
@@ -112,13 +107,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Kill a pod
- //
// ---
+ // summary: Kill a pod
// produces:
// - application/json
// parameters:
@@ -140,13 +133,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '409':
// $ref: "#/responses/ConflictError"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Pause a pod
- //
// ---
+ // summary: Pause a pod
// produces:
// - application/json
// parameters:
@@ -160,13 +151,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Restart a pod
- //
// ---
+ // summary: Restart a pod
// produces:
// - application/json
// parameters:
@@ -180,13 +169,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Start a pod
- //
// ---
+ // summary: Start a pod
// produces:
// - application/json
// parameters:
@@ -202,13 +189,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Stop a pod
- //
// ---
+ // summary: Stop a pod
// produces:
// - application/json
// parameters:
@@ -230,13 +215,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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
- //
- // Unpause a pod
- //
// ---
+ // summary: Unpause a pod
// produces:
// - application/json
// parameters:
@@ -250,7 +233,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// '404':
// $ref: "#/responses/NoSuchPod"
// '500':
- // $ref: "#responses/InternalError"
+ // $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 8fe5a67e4..34138cfbf 100644
--- a/pkg/api/server/register_volumes.go
+++ b/pkg/api/server/register_volumes.go
@@ -9,10 +9,8 @@ import (
func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// swagger:operation POST /libpod/volumes/create volumes createVolume
- //
- // Create a volume
- //
// ---
+ // summary: Create a volume
// produces:
// - application/json
// responses:
@@ -23,10 +21,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
r.Handle("/libpod/volumes/create", APIHandler(s.Context, libpod.CreateVolume)).Methods(http.MethodPost)
r.Handle("/libpod/volumes/json", APIHandler(s.Context, libpod.ListVolumes)).Methods(http.MethodGet)
// swagger:operation POST /volumes/prune volumes pruneVolumes
- //
- // Prune volumes
- //
// ---
+ // summary: Prune volumes
// produces:
// - application/json
// responses:
@@ -36,10 +32,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// "$ref": "#/responses/InternalError"
r.Handle("/libpod/volumes/prune", APIHandler(s.Context, libpod.PruneVolumes)).Methods(http.MethodPost)
// swagger:operation GET /volumes/{nameOrID}/json volumes inspectVolume
- //
- // Inspect volume
- //
// ---
+ // summary: Inspect volume
// parameters:
// - in: path
// name: nameOrID
@@ -56,10 +50,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// "$ref": "#/responses/InternalError"
r.Handle("/libpod/volumes/{name:..*}/json", APIHandler(s.Context, libpod.InspectVolume)).Methods(http.MethodGet)
// swagger:operation DELETE /volumes/{nameOrID} volumes removeVolume
- //
- // Inspect volume
- //
// ---
+ // summary: Remove volume
// parameters:
// - in: path
// name: nameOrID
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 0eb57ebab..dbf499ce7 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -117,9 +117,7 @@ type swagPodAlreadyStopped struct {
// swagger:response DockerImageSummary
type swagImageSummary struct {
// in:body
- Body struct {
- handlers.ImageSummary
- }
+ Body []handlers.ImageSummary
}
// List Containers
@@ -128,6 +126,11 @@ type swagListContainers struct {
// in:body
Body struct {
// This causes go-swagger to crash
- //handlers.Container
+ // handlers.Container
}
}
+
+// To be determined
+// swagger:response tbd
+type swagTBD struct {
+}
diff --git a/pkg/api/tags.yaml b/pkg/api/tags.yaml
new file mode 100644
index 000000000..ad0de656f
--- /dev/null
+++ b/pkg/api/tags.yaml
@@ -0,0 +1,13 @@
+tags:
+ - name: containers
+ description: Actions related to containers
+ - name: images
+ description: Actions related to images
+ - name: pods
+ description: Actions related to pods
+ - name: volumes
+ description: Actions related to volumes
+ - name: containers (compat)
+ description: Actions related to containers for the compatibility endpoints
+ - name: images (compat)
+ description: Actions related to images for the compatibility endpoints
diff --git a/pkg/apparmor/apparmor_linux_test.go b/pkg/apparmor/apparmor_linux_test.go
index e94293d87..3ff6e18bc 100644
--- a/pkg/apparmor/apparmor_linux_test.go
+++ b/pkg/apparmor/apparmor_linux_test.go
@@ -134,7 +134,7 @@ func TestDefaultContent(t *testing.T) {
if _, err := os.Stat(aapath); err != nil {
t.Skip("AppArmor isn't available in this environment")
}
- if err := DefaultContent(profile); err != nil {
+ if _, err := DefaultContent(profile); err != nil {
t.Fatalf("Couldn't retrieve default AppArmor profile content '%s': %v", profile, err)
}
}
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
new file mode 100644
index 000000000..551a63c62
--- /dev/null
+++ b/pkg/bindings/connection.go
@@ -0,0 +1,62 @@
+package bindings
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const (
+ defaultConnection string = "http://localhost:8080/v1.24/libpod"
+ pingConnection string = "http://localhost:8080/_ping"
+)
+
+type APIResponse struct {
+ *http.Response
+ Request *http.Request
+}
+
+type Connection struct {
+ url string
+ client *http.Client
+}
+
+func NewConnection(url string) (Connection, error) {
+ if len(url) < 1 {
+ url = defaultConnection
+ }
+ newConn := Connection{
+ url: url,
+ client: &http.Client{},
+ }
+ response, err := http.Get(pingConnection)
+ if err != nil {
+ return newConn, err
+ }
+ if err := response.Body.Close(); err != nil {
+ return newConn, err
+ }
+ return newConn, err
+}
+
+func (c Connection) makeEndpoint(u string) string {
+ return fmt.Sprintf("%s%s", defaultConnection, u)
+}
+
+func (c Connection) newRequest(httpMethod, endpoint string, httpBody io.Reader, params map[string]string) (*APIResponse, error) {
+ e := c.makeEndpoint(endpoint)
+ req, err := http.NewRequest(httpMethod, e, httpBody)
+ if err != nil {
+ return nil, err
+ }
+ if len(params) > 0 {
+ // if more desirable we could use url to form the encoded endpoint with params
+ r := req.URL.Query()
+ for k, v := range params {
+ r.Add(k, v)
+ }
+ req.URL.RawQuery = r.Encode()
+ }
+ response, err := c.client.Do(req) // nolint
+ return &APIResponse{response, req}, err
+}
diff --git a/pkg/bindings/containers.go b/pkg/bindings/containers.go
index cd0b09767..01f68f970 100644
--- a/pkg/bindings/containers.go
+++ b/pkg/bindings/containers.go
@@ -109,12 +109,14 @@ func (c Connection) UnpauseContainer(nameOrID string) error {
}
func (c Connection) WaitContainer(nameOrID string) error {
- _, err := http.Post(c.makeEndpoint(fmt.Sprintf("containers/%s/wait", nameOrID)), "application/json", nil)
+ // TODO when returns are ironed out, we can should use the newRequest approach
+ _, err := http.Post(c.makeEndpoint(fmt.Sprintf("containers/%s/wait", nameOrID)), "application/json", nil) // nolint
return err
}
func (c Connection) ContainerExists(nameOrID string) (bool, error) {
- response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/containers/%s/exists", nameOrID)))
+ response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/containers/%s/exists", nameOrID))) // nolint
+ defer closeResponseBody(response)
if err != nil {
return false, err
}
diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go
new file mode 100644
index 000000000..9a02925a3
--- /dev/null
+++ b/pkg/bindings/errors.go
@@ -0,0 +1,46 @@
+package bindings
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+var (
+ ErrNotImplemented = errors.New("function not implemented")
+)
+
+func handleError(data []byte) error {
+ e := utils.ErrorModel{}
+ if err := json.Unmarshal(data, &e); err != nil {
+ return err
+ }
+ return e
+}
+
+func (a APIResponse) Process(unmarshalInto interface{}) error {
+ data, err := ioutil.ReadAll(a.Response.Body)
+ if err != nil {
+ return errors.Wrap(err, "unable to process API response")
+ }
+ if a.Response.StatusCode == http.StatusOK {
+ if unmarshalInto != nil {
+ return json.Unmarshal(data, unmarshalInto)
+ }
+ return nil
+ }
+ // TODO should we add a debug here with the response code?
+ return handleError(data)
+}
+
+func closeResponseBody(r *http.Response) {
+ if r != nil {
+ if err := r.Body.Close(); err != nil {
+ logrus.Error(errors.Wrap(err, "unable to close response body"))
+ }
+ }
+}
diff --git a/pkg/bindings/images.go b/pkg/bindings/images.go
new file mode 100644
index 000000000..3abc8c372
--- /dev/null
+++ b/pkg/bindings/images.go
@@ -0,0 +1,111 @@
+package bindings
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "strconv"
+
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/inspect"
+)
+
+func (c Connection) ImageExists(nameOrID string) (bool, error) {
+ response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/images/%s/exists", nameOrID))) // nolint
+ defer closeResponseBody(response)
+ if err != nil {
+ return false, err
+ }
+ if response.StatusCode == http.StatusOK {
+ return true, nil
+ }
+ return false, nil
+}
+
+func (c Connection) ListImages() ([]handlers.ImageSummary, error) {
+ imageSummary := []handlers.ImageSummary{}
+ response, err := c.newRequest(http.MethodGet, "/images/json", nil, nil)
+ if err != nil {
+ return imageSummary, err
+ }
+ return imageSummary, response.Process(&imageSummary)
+}
+
+func (c Connection) GetImage(nameOrID string) (*inspect.ImageData, error) {
+ inspectedData := inspect.ImageData{}
+ response, err := c.newRequest(http.MethodGet, fmt.Sprintf("/images/%s/json", nameOrID), nil, nil)
+ if err != nil {
+ return &inspectedData, err
+ }
+ return &inspectedData, response.Process(&inspectedData)
+}
+
+func (c Connection) ImageTree(nameOrId string) error {
+ return ErrNotImplemented
+}
+
+func (c Connection) ImageHistory(nameOrID string) ([]handlers.HistoryResponse, error) {
+ history := []handlers.HistoryResponse{}
+ response, err := c.newRequest(http.MethodGet, fmt.Sprintf("/images/%s/history", nameOrID), nil, nil)
+ if err != nil {
+ return history, err
+ }
+ return history, response.Process(&history)
+}
+
+func (c Connection) LoadImage(r io.Reader) error {
+ // TODO this still needs error handling added
+ _, err := http.Post(c.makeEndpoint("/images/loads"), "application/json", r) //nolint
+ return err
+}
+
+func (c Connection) RemoveImage(nameOrID string, force bool) ([]map[string]string, error) {
+ deletes := []map[string]string{}
+ params := make(map[string]string)
+ params["force"] = strconv.FormatBool(force)
+ response, err := c.newRequest(http.MethodDelete, fmt.Sprintf("/images/%s", nameOrID), nil, params)
+ if err != nil {
+ return nil, err
+ }
+ return deletes, response.Process(&deletes)
+}
+
+func (c Connection) ExportImage(nameOrID string, w io.Writer, format string, compress bool) error {
+ params := make(map[string]string)
+ params["format"] = format
+ params["compress"] = strconv.FormatBool(compress)
+ response, err := c.newRequest(http.MethodGet, fmt.Sprintf("/images/%s/get", nameOrID), nil, params)
+ if err != nil {
+ return err
+ }
+ if err := response.Process(nil); err != nil {
+ return err
+ }
+ _, err = io.Copy(w, response.Body)
+ return err
+}
+
+func (c Connection) PruneImages(all bool, filters []string) ([]string, error) {
+ var (
+ deleted []string
+ )
+ params := make(map[string]string)
+ // FIXME How do we do []strings?
+ //params["filters"] = format
+ response, err := c.newRequest(http.MethodPost, "/images/prune", nil, params)
+ if err != nil {
+ return deleted, err
+ }
+ return deleted, response.Process(nil)
+}
+
+func (c Connection) TagImage(nameOrID string) error {
+ var ()
+ response, err := c.newRequest(http.MethodPost, fmt.Sprintf("/images/%s/tag", nameOrID), nil, nil)
+ if err != nil {
+ return err
+ }
+ return response.Process(nil)
+}
+
+func (c Connection) BuildImage(nameOrId string) {}
diff --git a/pkg/bindings/pods.go b/pkg/bindings/pods.go
index eac9d2ef5..704d71477 100644
--- a/pkg/bindings/pods.go
+++ b/pkg/bindings/pods.go
@@ -14,7 +14,8 @@ func (c Connection) CreatePod() error {
}
func (c Connection) PodExists(nameOrID string) (bool, error) {
- response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/pods/%s/exists", nameOrID)))
+ response, err := http.Get(c.makeEndpoint(fmt.Sprintf("/pods/%s/exists", nameOrID))) // nolint
+ defer closeResponseBody(response)
if err != nil {
return false, err
}
diff --git a/pkg/bindings/volumes.go b/pkg/bindings/volumes.go
index 27e6f9efa..219f924e7 100644
--- a/pkg/bindings/volumes.go
+++ b/pkg/bindings/volumes.go
@@ -52,7 +52,7 @@ func (c Connection) PruneVolumes() ([]string, error) {
func (c Connection) RemoveVolume(nameOrID string, force bool) error {
params := make(map[string]string)
params["force"] = strconv.FormatBool(force)
- response, err := c.newRequest(http.MethodPost, fmt.Sprintf("/volumes/prune", nameOrID), nil, params)
+ response, err := c.newRequest(http.MethodPost, "/volumes/prune", nil, params)
if err != nil {
return err
}
diff --git a/pkg/hooks/1.0.0/when_test.go b/pkg/hooks/1.0.0/when_test.go
index a749063ff..94b0c3830 100644
--- a/pkg/hooks/1.0.0/when_test.go
+++ b/pkg/hooks/1.0.0/when_test.go
@@ -10,7 +10,8 @@ import (
func TestNoMatch(t *testing.T) {
config := &rspec.Spec{}
- for _, or := range []bool{true, false} {
+ for _, o := range []bool{true, false} {
+ or := o
t.Run(fmt.Sprintf("or %t", or), func(t *testing.T) {
when := When{Or: or}
match, err := when.Match(config, map[string]string{}, false)
@@ -27,9 +28,12 @@ func TestAlways(t *testing.T) {
processStruct := &rspec.Process{
Args: []string{"/bin/sh", "a", "b"},
}
- for _, always := range []bool{true, false} {
- for _, or := range []bool{true, false} {
- for _, process := range []*rspec.Process{processStruct, nil} {
+ for _, a := range []bool{true, false} {
+ always := a
+ for _, o := range []bool{true, false} {
+ or := o
+ for _, p := range []*rspec.Process{processStruct, nil} {
+ process := p
t.Run(fmt.Sprintf("always %t, or %t, has process %t", always, or, process != nil), func(t *testing.T) {
config.Process = process
when := When{Always: &always, Or: or}
@@ -48,7 +52,8 @@ func TestHasBindMountsAnd(t *testing.T) {
hasBindMounts := true
when := When{HasBindMounts: &hasBindMounts}
config := &rspec.Spec{}
- for _, containerHasBindMounts := range []bool{false, true} {
+ for _, b := range []bool{false, true} {
+ containerHasBindMounts := b
t.Run(fmt.Sprintf("%t", containerHasBindMounts), func(t *testing.T) {
match, err := when.Match(config, map[string]string{}, containerHasBindMounts)
if err != nil {
@@ -63,7 +68,8 @@ func TestHasBindMountsOr(t *testing.T) {
hasBindMounts := true
when := When{HasBindMounts: &hasBindMounts, Or: true}
config := &rspec.Spec{}
- for _, containerHasBindMounts := range []bool{false, true} {
+ for _, b := range []bool{false, true} {
+ containerHasBindMounts := b
t.Run(fmt.Sprintf("%t", containerHasBindMounts), func(t *testing.T) {
match, err := when.Match(config, map[string]string{}, containerHasBindMounts)
if err != nil {
@@ -82,7 +88,7 @@ func TestAnnotations(t *testing.T) {
},
}
config := &rspec.Spec{}
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
annotations map[string]string
or bool
@@ -131,6 +137,7 @@ func TestAnnotations(t *testing.T) {
match: false,
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
when.Or = test.or
match, err := when.Match(config, test.annotations, false)
@@ -149,7 +156,7 @@ func TestCommands(t *testing.T) {
},
}
config := &rspec.Spec{}
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
process *rspec.Process
match bool
@@ -173,6 +180,7 @@ func TestCommands(t *testing.T) {
match: false,
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
config.Process = test.process
match, err := when.Match(config, map[string]string{}, false)
@@ -209,7 +217,7 @@ func TestHasBindMountsAndCommands(t *testing.T) {
},
}
config := &rspec.Spec{Process: &rspec.Process{}}
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
command string
hasBindMounts bool
@@ -273,6 +281,7 @@ func TestHasBindMountsAndCommands(t *testing.T) {
match: false,
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
config.Process.Args = []string{test.command}
when.Or = test.or
@@ -287,7 +296,7 @@ func TestHasBindMountsAndCommands(t *testing.T) {
func TestInvalidRegexp(t *testing.T) {
config := &rspec.Spec{Process: &rspec.Process{Args: []string{"/bin/sh"}}}
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
when When
expected string
@@ -308,6 +317,7 @@ func TestInvalidRegexp(t *testing.T) {
expected: "^command: error parsing regexp: .*",
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
_, err := test.when.Match(config, map[string]string{"a": "b"}, false)
if err == nil {
diff --git a/pkg/hooks/exec/exec_test.go b/pkg/hooks/exec/exec_test.go
index 7aac315cb..1e105373d 100644
--- a/pkg/hooks/exec/exec_test.go
+++ b/pkg/hooks/exec/exec_test.go
@@ -94,7 +94,7 @@ func TestRunEnvironment(t *testing.T) {
Path: path,
Args: []string{"sh", "-c", "env"},
}
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
env []string
expected map[string]string
@@ -120,6 +120,7 @@ func TestRunEnvironment(t *testing.T) {
},
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
var stderr, stdout bytes.Buffer
hook.Env = test.env
@@ -147,7 +148,7 @@ func TestRunCancel(t *testing.T) {
Args: []string{"sh", "-c", "echo waiting; sleep 2; echo done"},
}
one := 1
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
contextTimeout time.Duration
hookTimeout *int
@@ -174,6 +175,7 @@ func TestRunCancel(t *testing.T) {
expectedRunError: context.DeadlineExceeded,
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
ctx := context.Background()
var stderr, stdout bytes.Buffer
diff --git a/pkg/hooks/exec/runtimeconfigfilter_test.go b/pkg/hooks/exec/runtimeconfigfilter_test.go
index 52d590d14..48dd2f998 100644
--- a/pkg/hooks/exec/runtimeconfigfilter_test.go
+++ b/pkg/hooks/exec/runtimeconfigfilter_test.go
@@ -25,9 +25,9 @@ func pointerFileMode(value os.FileMode) *os.FileMode {
}
func TestRuntimeConfigFilter(t *testing.T) {
- unexpectedEndOfJSONInput := json.Unmarshal([]byte("{\n"), nil)
+ unexpectedEndOfJSONInput := json.Unmarshal([]byte("{\n"), nil) //nolint
- for _, test := range []struct {
+ for _, tt := range []struct {
name string
contextTimeout time.Duration
hooks []spec.Hook
@@ -244,6 +244,7 @@ func TestRuntimeConfigFilter(t *testing.T) {
expectedRunError: unexpectedEndOfJSONInput,
},
} {
+ test := tt
t.Run(test.name, func(t *testing.T) {
ctx := context.Background()
if test.contextTimeout > 0 {
diff --git a/pkg/network/network_test.go b/pkg/network/network_test.go
index dbffc33ad..1969e792c 100644
--- a/pkg/network/network_test.go
+++ b/pkg/network/network_test.go
@@ -25,9 +25,10 @@ func Test_networkIntersect(t *testing.T) {
{"Two 24s", args{n1: parseCIDR("192.168.1.0/24"), n2: parseCIDR("192.168.2.0/24")}, false},
}
for _, tt := range tests {
+ test := tt
t.Run(tt.name, func(t *testing.T) {
- if got := networkIntersect(tt.args.n1, tt.args.n2); got != tt.want {
- t.Errorf("networkIntersect() = %v, want %v", got, tt.want)
+ if got := networkIntersect(test.args.n1, test.args.n2); got != test.want {
+ t.Errorf("networkIntersect() = %v, want %v", got, test.want)
}
})
}
diff --git a/pkg/network/subnet_test.go b/pkg/network/subnet_test.go
index 6ecfd2d17..917c3be88 100644
--- a/pkg/network/subnet_test.go
+++ b/pkg/network/subnet_test.go
@@ -20,14 +20,15 @@ func TestNextSubnet(t *testing.T) {
{"class c", args{subnet: parseCIDR("192.168.1.0/24")}, parseCIDR("192.168.2.0/24"), false},
}
for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := NextSubnet(tt.args.subnet)
- if (err != nil) != tt.wantErr {
- t.Errorf("NextSubnet() error = %v, wantErr %v", err, tt.wantErr)
+ test := tt
+ t.Run(test.name, func(t *testing.T) {
+ got, err := NextSubnet(test.args.subnet)
+ if (err != nil) != test.wantErr {
+ t.Errorf("NextSubnet() error = %v, wantErr %v", err, test.wantErr)
return
}
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("NextSubnet() got = %v, want %v", got, tt.want)
+ if !reflect.DeepEqual(got, test.want) {
+ t.Errorf("NextSubnet() got = %v, want %v", got, test.want)
}
})
}
diff --git a/pkg/spec/config_linux_cgo.go b/pkg/spec/config_linux_cgo.go
index c47156456..ae83c9d52 100644
--- a/pkg/spec/config_linux_cgo.go
+++ b/pkg/spec/config_linux_cgo.go
@@ -8,13 +8,24 @@ import (
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
seccomp "github.com/seccomp/containers-golang"
+ "github.com/sirupsen/logrus"
)
func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.LinuxSeccomp, error) {
var seccompConfig *spec.LinuxSeccomp
var err error
+ if config.SeccompPolicy == SeccompPolicyImage && config.SeccompProfileFromImage != "" {
+ logrus.Debug("Loading seccomp profile from the security config")
+ seccompConfig, err = seccomp.LoadProfile(config.SeccompProfileFromImage, configSpec)
+ if err != nil {
+ return nil, errors.Wrap(err, "loading seccomp profile failed")
+ }
+ return seccompConfig, nil
+ }
+
if config.SeccompProfilePath != "" {
+ logrus.Debugf("Loading seccomp profile from %q", config.SeccompProfilePath)
seccompProfile, err := ioutil.ReadFile(config.SeccompProfilePath)
if err != nil {
return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath)
@@ -24,6 +35,7 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu
return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath)
}
} else {
+ logrus.Debug("Loading default seccomp profile")
seccompConfig, err = seccomp.GetDefaultProfile(configSpec)
if err != nil {
return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath)
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 6d058229b..fb222083b 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -2,6 +2,7 @@ package createconfig
import (
"os"
+ "sort"
"strconv"
"strings"
"syscall"
@@ -106,19 +107,63 @@ type NetworkConfig struct {
PublishAll bool //publish-all
}
+// SeccompPolicy determines which seccomp profile gets applied to the container.
+type SeccompPolicy int
+
+const (
+ // SeccompPolicyDefault - if set use SecurityConfig.SeccompProfilePath,
+ // otherwise use the default profile. The SeccompProfilePath might be
+ // explicitly set by the user.
+ SeccompPolicyDefault SeccompPolicy = iota
+ // SeccompPolicyImage - if set use SecurityConfig.SeccompProfileFromImage,
+ // otherwise follow SeccompPolicyDefault.
+ SeccompPolicyImage
+)
+
+// Map for easy lookups of supported policies.
+var supportedSeccompPolicies = map[string]SeccompPolicy{
+ "": SeccompPolicyDefault,
+ "default": SeccompPolicyDefault,
+ "image": SeccompPolicyImage,
+}
+
+// LookupSeccompPolicy looksup the corresponding SeccompPolicy for the specified
+// string. If none is found, an errors is returned including the list of
+// supported policies.
+// Note that an empty string resolved to SeccompPolicyDefault.
+func LookupSeccompPolicy(s string) (SeccompPolicy, error) {
+ policy, exists := supportedSeccompPolicies[s]
+ if exists {
+ return policy, nil
+ }
+
+ // Sort the keys first as maps are non-deterministic.
+ keys := []string{}
+ for k := range supportedSeccompPolicies {
+ if k != "" {
+ keys = append(keys, k)
+ }
+ }
+ sort.Strings(keys)
+
+ return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys)
+}
+
// SecurityConfig configures the security features for the container
type SecurityConfig struct {
- CapAdd []string // cap-add
- CapDrop []string // cap-drop
- LabelOpts []string //SecurityOpts
- NoNewPrivs bool //SecurityOpts
- ApparmorProfile string //SecurityOpts
- SeccompProfilePath string //SecurityOpts
- SecurityOpts []string
- Privileged bool //privileged
- ReadOnlyRootfs bool //read-only
- ReadOnlyTmpfs bool //read-only-tmpfs
- Sysctl map[string]string //sysctl
+ CapAdd []string // cap-add
+ CapDrop []string // cap-drop
+ LabelOpts []string //SecurityOpts
+ NoNewPrivs bool //SecurityOpts
+ ApparmorProfile string //SecurityOpts
+ SeccompProfilePath string //SecurityOpts
+ SeccompProfileFromImage string // seccomp profile from the container image
+ SeccompPolicy SeccompPolicy
+ SecurityOpts []string
+ Privileged bool //privileged
+ ReadOnlyRootfs bool //read-only
+ ReadOnlyTmpfs bool //read-only-tmpfs
+ Sysctl map[string]string //sysctl
}
// CreateConfig is a pre OCI spec structure. It represents user input from varlink or the CLI
diff --git a/pkg/systemdgen/systemdgen_test.go b/pkg/systemdgen/systemdgen_test.go
index e1da7e8e0..3894a0205 100644
--- a/pkg/systemdgen/systemdgen_test.go
+++ b/pkg/systemdgen/systemdgen_test.go
@@ -24,9 +24,10 @@ func TestValidateRestartPolicy(t *testing.T) {
{"failblank", ContainerInfo{restart: ""}, true},
}
for _, tt := range tests {
+ test := tt
t.Run(tt.name, func(t *testing.T) {
- if err := validateRestartPolicy(tt.ContainerInfo.restart); (err != nil) != tt.wantErr {
- t.Errorf("ValidateRestartPolicy() error = %v, wantErr %v", err, tt.wantErr)
+ if err := validateRestartPolicy(test.ContainerInfo.restart); (err != nil) != test.wantErr {
+ t.Errorf("ValidateRestartPolicy() error = %v, wantErr %v", err, test.wantErr)
}
})
}
@@ -221,18 +222,19 @@ WantedBy=multi-user.target`
},
}
for _, tt := range tests {
+ test := tt
t.Run(tt.name, func(t *testing.T) {
opts := Options{
Files: false,
- New: tt.info.New,
+ New: test.info.New,
}
- got, err := CreateContainerSystemdUnit(&tt.info, opts)
- if (err != nil) != tt.wantErr {
- t.Errorf("CreateContainerSystemdUnit() error = \n%v, wantErr \n%v", err, tt.wantErr)
+ got, err := CreateContainerSystemdUnit(&test.info, opts)
+ if (err != nil) != test.wantErr {
+ t.Errorf("CreateContainerSystemdUnit() error = \n%v, wantErr \n%v", err, test.wantErr)
return
}
- if got != tt.want {
- t.Errorf("CreateContainerSystemdUnit() = \n%v\n---------> want\n%v", got, tt.want)
+ if got != test.want {
+ t.Errorf("CreateContainerSystemdUnit() = \n%v\n---------> want\n%v", got, test.want)
}
})
}
diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go
index d028ddf8f..5be24faaa 100644
--- a/pkg/tracing/tracing.go
+++ b/pkg/tracing/tracing.go
@@ -12,6 +12,7 @@ import (
// Init returns an instance of Jaeger Tracer that samples 100% of traces and logs all spans to stdout.
func Init(service string) (opentracing.Tracer, io.Closer) {
cfg := &config.Configuration{
+ ServiceName: service,
Sampler: &config.SamplerConfig{
Type: "const",
Param: 1,
@@ -20,7 +21,7 @@ func Init(service string) (opentracing.Tracer, io.Closer) {
LogSpans: true,
},
}
- tracer, closer, err := cfg.New(service, config.Logger(jaeger.StdLogger))
+ tracer, closer, err := cfg.NewTracer(config.Logger(jaeger.StdLogger))
if err != nil {
panic(fmt.Sprintf("ERROR: cannot init Jaeger: %v\n", err))
}