diff options
Diffstat (limited to 'pkg/api')
-rw-r--r-- | pkg/api/handlers/decoder.go | 13 | ||||
-rw-r--r-- | pkg/api/handlers/generic/containers_stats.go | 16 | ||||
-rw-r--r-- | pkg/api/handlers/generic/types.go | 55 | ||||
-rw-r--r-- | pkg/api/handlers/images.go | 1 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 39 | ||||
-rw-r--r-- | pkg/api/handlers/types.go | 8 | ||||
-rw-r--r-- | pkg/api/server/register_containers.go | 42 | ||||
-rw-r--r-- | pkg/api/server/register_images.go | 1 |
8 files changed, 125 insertions, 50 deletions
diff --git a/pkg/api/handlers/decoder.go b/pkg/api/handlers/decoder.go index 890d77ecc..03b86275d 100644 --- a/pkg/api/handlers/decoder.go +++ b/pkg/api/handlers/decoder.go @@ -3,8 +3,10 @@ package handlers import ( "encoding/json" "reflect" + "syscall" "time" + "github.com/containers/libpod/pkg/util" "github.com/gorilla/schema" "github.com/sirupsen/logrus" ) @@ -17,6 +19,9 @@ func NewAPIDecoder() *schema.Decoder { d.IgnoreUnknownKeys(true) d.RegisterConverter(map[string][]string{}, convertUrlValuesString) d.RegisterConverter(time.Time{}, convertTimeString) + + var Signal syscall.Signal + d.RegisterConverter(Signal, convertSignal) return d } @@ -89,3 +94,11 @@ func convertTimeString(query string) reflect.Value { func ParseDateTime(query string) time.Time { return convertTimeString(query).Interface().(time.Time) } + +func convertSignal(query string) reflect.Value { + signal, err := util.ParseSignal(query) + if err != nil { + logrus.Infof("convertSignal: Failed to parse %s: %s", query, err.Error()) + } + return reflect.ValueOf(signal) +} diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go index 19e2cc882..977979741 100644 --- a/pkg/api/handlers/generic/containers_stats.go +++ b/pkg/api/handlers/generic/containers_stats.go @@ -7,7 +7,6 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/cgroups" docker "github.com/docker/docker/api/types" @@ -58,17 +57,18 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { } var preRead time.Time - var preCPUStats docker.CPUStats + var preCPUStats CPUStats if query.Stream { preRead = time.Now() systemUsage, _ := cgroups.GetSystemCPUUsage() - preCPUStats = docker.CPUStats{ + preCPUStats = CPUStats{ CPUUsage: docker.CPUUsage{ TotalUsage: stats.CPUNano, PercpuUsage: stats.PerCPU, UsageInKernelmode: stats.CPUSystemNano, UsageInUsermode: stats.CPUNano - stats.CPUSystemNano, }, + CPU: stats.CPU, SystemUsage: systemUsage, OnlineCPUs: 0, ThrottlingData: docker.ThrottlingData{}, @@ -124,9 +124,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { } systemUsage, _ := cgroups.GetSystemCPUUsage() - - s := handlers.Stats{StatsJSON: docker.StatsJSON{ - Stats: docker.Stats{ + s := StatsJSON{ + Stats: Stats{ Read: time.Now(), PreRead: preRead, PidsStats: docker.PidsStats{ @@ -143,13 +142,14 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { IoTimeRecursive: nil, SectorsRecursive: nil, }, - CPUStats: docker.CPUStats{ + CPUStats: CPUStats{ CPUUsage: docker.CPUUsage{ TotalUsage: cgroupStat.CPU.Usage.Total, PercpuUsage: cgroupStat.CPU.Usage.PerCPU, UsageInKernelmode: cgroupStat.CPU.Usage.Kernel, UsageInUsermode: cgroupStat.CPU.Usage.Total - cgroupStat.CPU.Usage.Kernel, }, + CPU: stats.CPU, SystemUsage: systemUsage, OnlineCPUs: uint32(len(cgroupStat.CPU.Usage.PerCPU)), ThrottlingData: docker.ThrottlingData{ @@ -173,7 +173,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { Name: stats.Name, ID: stats.ContainerID, Networks: net, - }} + } utils.WriteJSON(w, http.StatusOK, s) if flusher, ok := w.(http.Flusher); ok { diff --git a/pkg/api/handlers/generic/types.go b/pkg/api/handlers/generic/types.go new file mode 100644 index 000000000..f068ac011 --- /dev/null +++ b/pkg/api/handlers/generic/types.go @@ -0,0 +1,55 @@ +package generic + +import ( + "time" + + docker "github.com/docker/docker/api/types" +) + +// CPUStats aggregates and wraps all CPU related info of container +type CPUStats struct { + // CPU Usage. Linux and Windows. + CPUUsage docker.CPUUsage `json:"cpu_usage"` + + // System Usage. Linux only. + SystemUsage uint64 `json:"system_cpu_usage,omitempty"` + + // Online CPUs. Linux only. + OnlineCPUs uint32 `json:"online_cpus,omitempty"` + + // Usage of CPU in %. Linux only. + CPU float64 `json:"cpu"` + + // Throttling Data. Linux only. + ThrottlingData docker.ThrottlingData `json:"throttling_data,omitempty"` +} + +// Stats is Ultimate struct aggregating all types of stats of one container +type Stats struct { + // Common stats + Read time.Time `json:"read"` + PreRead time.Time `json:"preread"` + + // Linux specific stats, not populated on Windows. + PidsStats docker.PidsStats `json:"pids_stats,omitempty"` + BlkioStats docker.BlkioStats `json:"blkio_stats,omitempty"` + + // Windows specific stats, not populated on Linux. + NumProcs uint32 `json:"num_procs"` + StorageStats docker.StorageStats `json:"storage_stats,omitempty"` + + // Shared stats + CPUStats CPUStats `json:"cpu_stats,omitempty"` + PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous" + MemoryStats docker.MemoryStats `json:"memory_stats,omitempty"` +} + +type StatsJSON struct { + Stats + + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + + // Networks request version >=1.21 + Networks map[string]docker.NetworkStats `json:"networks,omitempty"` +} diff --git a/pkg/api/handlers/images.go b/pkg/api/handlers/images.go index e4e394d68..96bcbdc96 100644 --- a/pkg/api/handlers/images.go +++ b/pkg/api/handlers/images.go @@ -156,6 +156,7 @@ func SearchImages(w http.ResponseWriter, r *http.Request) { results, err := image.SearchImages(query.Term, options) if err != nil { utils.BadRequest(w, "term", query.Term, err) + return } utils.WriteResponse(w, http.StatusOK, results) } diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index eac0e4dad..71603e6cc 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "strconv" + "strings" "github.com/containers/image/v5/docker" "github.com/containers/image/v5/docker/reference" @@ -133,11 +134,16 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { var libpodFilters = []string{} if _, found := r.URL.Query()["filters"]; found { - all, err = strconv.ParseBool(query.Filters["all"][0]) - if err != nil { - utils.InternalServerError(w, err) - return + dangling := query.Filters["all"] + if len(dangling) > 0 { + all, err = strconv.ParseBool(query.Filters["all"][0]) + if err != nil { + utils.InternalServerError(w, err) + return + } } + // dangling is special and not implemented in the libpod side of things + delete(query.Filters, "dangling") for k, v := range query.Filters { libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", k, v[0])) } @@ -157,7 +163,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { Compress bool `schema:"compress"` Format string `schema:"format"` }{ - // override any golang type defaults + Format: "docker-archive", } if err := decoder.Decode(&query, r.URL.Query()); err != nil { @@ -166,11 +172,6 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { return } - if len(query.Format) < 1 { - utils.InternalServerError(w, errors.New("format parameter cannot be empty.")) - return - } - tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) @@ -186,6 +187,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { utils.ImageNotFound(w, name, err) return } + if err := newImage.Save(r.Context(), name, query.Format, tmpfile.Name(), []string{}, false, query.Compress); err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err) return @@ -234,8 +236,20 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image")) return } - - utils.WriteResponse(w, http.StatusOK, []handlers.LibpodImagesLoadReport{{ID: loadedImage}}) + split := strings.Split(loadedImage, ",") + newImage, err := runtime.ImageRuntime().NewFromLocal(split[0]) + if err != nil { + utils.InternalServerError(w, err) + return + } + // TODO this should go into libpod proper at some point. + if len(query.Reference) > 0 { + if err := newImage.TagImage(query.Reference); err != nil { + utils.InternalServerError(w, err) + return + } + } + utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesLoadReport{ID: loadedImage}) } func ImagesImport(w http.ResponseWriter, r *http.Request) { @@ -275,7 +289,6 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { tmpfile.Close() source = tmpfile.Name() } - importedImage, err := runtime.Import(context.Background(), source, query.Reference, query.Changes, query.Message, true) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import image")) diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 6268028f5..c72b0f817 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -78,10 +78,6 @@ type Container struct { docker.ContainerCreateConfig } -type ContainerStats struct { - docker.ContainerStats -} - type Version struct { docker.Version } @@ -143,10 +139,6 @@ type IDResponse struct { ID string `json:"id"` } -type Stats struct { - docker.StatsJSON -} - type ContainerTopOKBody struct { dockerContainer.ContainerTopOKBody } diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 6007a2d00..6a2ba4b1e 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -550,7 +550,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { libpod endpoints */ - // swagger:operation POST /containers/create libpod libpodContainerCreate + // swagger:operation POST /libpod/containers/create libpod libpodCreateContainer // --- // summary: Create a container // tags: @@ -615,21 +615,21 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // name: filters // type: string // 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>) + // A JSON encoded value of the filters (a `map[string][]string`) to process on the containers list. Available filters: + // - `ancestor`=(`<image-name>[:<tag>]`, `<image id>`, or `<image@digest>`) + // - `before`=(`<container id>` or `<container name>`) + // - `expose`=(`<port>[/<proto>]` or `<startport-endport>/[<proto>]`) + // - `exited=<int>` containers with exit code of `<int>` + // - `health`=(`starting`, `healthy`, `unhealthy` or `none`) + // - `id=<ID>` a container's ID + // - `is-task`=(`true` or `false`) + // - `label`=(`key` or `"key=value"`) of an container label + // - `name=<name>` a container's name + // - `network`=(`<network id>` or `<network name>`) + // - `publish`=(`<port>[/<proto>]` or `<startport-endport>/[<proto>]`) + // - `since`=(`<container id>` or `<container name>`) + // - `status`=(`created`, `restarting`, `running`, `removing`, `paused`, `exited` or `dead`) + // - `volume`=(`<volume name>` or `<mount point destination>`) // produces: // - application/json // responses: @@ -662,7 +662,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/prune"), s.APIHandler(handlers.PruneContainers)).Methods(http.MethodPost) - // swagger:operation GET /libpod/containers/showmounted libpod showMountedContainers + // swagger:operation GET /libpod/containers/showmounted libpod libpodShowMountedContainers // --- // tags: // - containers @@ -769,7 +769,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/kill"), s.APIHandler(libpod.KillContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{name}/mount libpod mountContainer + // swagger:operation POST /libpod/containers/{name}/mount libpod libpodMountContainer // --- // tags: // - containers @@ -1047,7 +1047,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/wait"), s.APIHandler(libpod.WaitContainer)).Methods(http.MethodPost) - // swagger:operation GET /libpod/containers/{name}/exists libpod containerExists + // swagger:operation GET /libpod/containers/{name}/exists libpod libpodContainerExists // --- // tags: // - containers @@ -1096,7 +1096,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/stop"), s.APIHandler(handlers.StopContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{name}/attach libpod libpodAttach + // swagger:operation POST /libpod/containers/{name}/attach libpod libpodAttachContainer // --- // tags: // - containers @@ -1151,7 +1151,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/attach"), s.APIHandler(handlers.AttachContainer)).Methods(http.MethodPost) - // swagger:operation POST /libpod/containers/{name}/resize libpod libpodResize + // swagger:operation POST /libpod/containers/{name}/resize libpod libpodResizeContainer // --- // tags: // - containers diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 4c8f05385..db04ecdc9 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -648,6 +648,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - `dangling=true` // - `label=key` or `label="key=value"` of an image label // - `reference`=(`<image-name>[:<tag>]`) + // - `id`=(`<image-id>`) // - `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) // type: string // produces: |