summaryrefslogtreecommitdiff
path: root/pkg/api/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers')
-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
10 files changed, 102 insertions, 70 deletions
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)
}
}