Create api types package for structured responses
| ... | ... |
@@ -26,7 +26,7 @@ import ( |
| 26 | 26 |
|
| 27 | 27 |
log "github.com/Sirupsen/logrus" |
| 28 | 28 |
"github.com/docker/docker/api" |
| 29 |
- "github.com/docker/docker/api/stats" |
|
| 29 |
+ "github.com/docker/docker/api/types" |
|
| 30 | 30 |
"github.com/docker/docker/autogen/dockerversion" |
| 31 | 31 |
"github.com/docker/docker/engine" |
| 32 | 32 |
"github.com/docker/docker/graph" |
| ... | ... |
@@ -2133,7 +2133,7 @@ func (cid *cidFile) Write(id string) error {
|
| 2133 | 2133 |
return nil |
| 2134 | 2134 |
} |
| 2135 | 2135 |
|
| 2136 |
-func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (engine.Env, error) {
|
|
| 2136 |
+func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
|
|
| 2137 | 2137 |
containerValues := url.Values{}
|
| 2138 | 2138 |
if name != "" {
|
| 2139 | 2139 |
containerValues.Set("name", name)
|
| ... | ... |
@@ -2172,23 +2172,19 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc |
| 2172 | 2172 |
return nil, err |
| 2173 | 2173 |
} |
| 2174 | 2174 |
|
| 2175 |
- var result engine.Env |
|
| 2176 |
- if err := result.Decode(stream); err != nil {
|
|
| 2175 |
+ var response types.ContainerCreateResponse |
|
| 2176 |
+ if err := json.NewDecoder(stream).Decode(&response); err != nil {
|
|
| 2177 | 2177 |
return nil, err |
| 2178 | 2178 |
} |
| 2179 |
- |
|
| 2180 |
- for _, warning := range result.GetList("Warnings") {
|
|
| 2179 |
+ for _, warning := range response.Warnings {
|
|
| 2181 | 2180 |
fmt.Fprintf(cli.err, "WARNING: %s\n", warning) |
| 2182 | 2181 |
} |
| 2183 |
- |
|
| 2184 | 2182 |
if containerIDFile != nil {
|
| 2185 |
- if err = containerIDFile.Write(result.Get("Id")); err != nil {
|
|
| 2183 |
+ if err = containerIDFile.Write(response.ID); err != nil {
|
|
| 2186 | 2184 |
return nil, err |
| 2187 | 2185 |
} |
| 2188 | 2186 |
} |
| 2189 |
- |
|
| 2190 |
- return result, nil |
|
| 2191 |
- |
|
| 2187 |
+ return &response, nil |
|
| 2192 | 2188 |
} |
| 2193 | 2189 |
|
| 2194 | 2190 |
func (cli *DockerCli) CmdCreate(args ...string) error {
|
| ... | ... |
@@ -2207,14 +2203,11 @@ func (cli *DockerCli) CmdCreate(args ...string) error {
|
| 2207 | 2207 |
cmd.Usage() |
| 2208 | 2208 |
return nil |
| 2209 | 2209 |
} |
| 2210 |
- |
|
| 2211 |
- createResult, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) |
|
| 2210 |
+ response, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) |
|
| 2212 | 2211 |
if err != nil {
|
| 2213 | 2212 |
return err |
| 2214 | 2213 |
} |
| 2215 |
- |
|
| 2216 |
- fmt.Fprintf(cli.out, "%s\n", createResult.Get("Id"))
|
|
| 2217 |
- |
|
| 2214 |
+ fmt.Fprintf(cli.out, "%s\n", response.ID) |
|
| 2218 | 2215 |
return nil |
| 2219 | 2216 |
} |
| 2220 | 2217 |
|
| ... | ... |
@@ -2272,38 +2265,32 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 2272 | 2272 |
sigProxy = false |
| 2273 | 2273 |
} |
| 2274 | 2274 |
|
| 2275 |
- runResult, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) |
|
| 2275 |
+ createResponse, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) |
|
| 2276 | 2276 |
if err != nil {
|
| 2277 | 2277 |
return err |
| 2278 | 2278 |
} |
| 2279 |
- |
|
| 2280 | 2279 |
if sigProxy {
|
| 2281 |
- sigc := cli.forwardAllSignals(runResult.Get("Id"))
|
|
| 2280 |
+ sigc := cli.forwardAllSignals(createResponse.ID) |
|
| 2282 | 2281 |
defer signal.StopCatch(sigc) |
| 2283 | 2282 |
} |
| 2284 |
- |
|
| 2285 | 2283 |
var ( |
| 2286 | 2284 |
waitDisplayId chan struct{}
|
| 2287 | 2285 |
errCh chan error |
| 2288 | 2286 |
) |
| 2289 |
- |
|
| 2290 | 2287 |
if !config.AttachStdout && !config.AttachStderr {
|
| 2291 | 2288 |
// Make this asynchronous to allow the client to write to stdin before having to read the ID |
| 2292 | 2289 |
waitDisplayId = make(chan struct{})
|
| 2293 | 2290 |
go func() {
|
| 2294 | 2291 |
defer close(waitDisplayId) |
| 2295 |
- fmt.Fprintf(cli.out, "%s\n", runResult.Get("Id"))
|
|
| 2292 |
+ fmt.Fprintf(cli.out, "%s\n", createResponse.ID) |
|
| 2296 | 2293 |
}() |
| 2297 | 2294 |
} |
| 2298 |
- |
|
| 2299 | 2295 |
if *flAutoRemove && (hostConfig.RestartPolicy.Name == "always" || hostConfig.RestartPolicy.Name == "on-failure") {
|
| 2300 | 2296 |
return ErrConflictRestartPolicyAndAutoRemove |
| 2301 | 2297 |
} |
| 2302 |
- |
|
| 2303 | 2298 |
// We need to instantiate the chan because the select needs it. It can |
| 2304 | 2299 |
// be closed but can't be uninitialized. |
| 2305 | 2300 |
hijacked := make(chan io.Closer) |
| 2306 |
- |
|
| 2307 | 2301 |
// Block the return until the chan gets closed |
| 2308 | 2302 |
defer func() {
|
| 2309 | 2303 |
log.Debugf("End of CmdRun(), Waiting for hijack to finish.")
|
| ... | ... |
@@ -2311,7 +2298,6 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 2311 | 2311 |
log.Errorf("Hijack did not finish (chan still open)")
|
| 2312 | 2312 |
} |
| 2313 | 2313 |
}() |
| 2314 |
- |
|
| 2315 | 2314 |
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
|
| 2316 | 2315 |
var ( |
| 2317 | 2316 |
out, stderr io.Writer |
| ... | ... |
@@ -2319,7 +2305,6 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 2319 | 2319 |
v = url.Values{}
|
| 2320 | 2320 |
) |
| 2321 | 2321 |
v.Set("stream", "1")
|
| 2322 |
- |
|
| 2323 | 2322 |
if config.AttachStdin {
|
| 2324 | 2323 |
v.Set("stdin", "1")
|
| 2325 | 2324 |
in = cli.in |
| ... | ... |
@@ -2336,14 +2321,12 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 2336 | 2336 |
stderr = cli.err |
| 2337 | 2337 |
} |
| 2338 | 2338 |
} |
| 2339 |
- |
|
| 2340 | 2339 |
errCh = promise.Go(func() error {
|
| 2341 |
- return cli.hijack("POST", "/containers/"+runResult.Get("Id")+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked, nil)
|
|
| 2340 |
+ return cli.hijack("POST", "/containers/"+createResponse.ID+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked, nil)
|
|
| 2342 | 2341 |
}) |
| 2343 | 2342 |
} else {
|
| 2344 | 2343 |
close(hijacked) |
| 2345 | 2344 |
} |
| 2346 |
- |
|
| 2347 | 2345 |
// Acknowledge the hijack before starting |
| 2348 | 2346 |
select {
|
| 2349 | 2347 |
case closer := <-hijacked: |
| ... | ... |
@@ -2360,12 +2343,12 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 2360 | 2360 |
} |
| 2361 | 2361 |
|
| 2362 | 2362 |
//start the container |
| 2363 |
- if _, _, err = readBody(cli.call("POST", "/containers/"+runResult.Get("Id")+"/start", nil, false)); err != nil {
|
|
| 2363 |
+ if _, _, err = readBody(cli.call("POST", "/containers/"+createResponse.ID+"/start", nil, false)); err != nil {
|
|
| 2364 | 2364 |
return err |
| 2365 | 2365 |
} |
| 2366 | 2366 |
|
| 2367 | 2367 |
if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminalOut {
|
| 2368 |
- if err := cli.monitorTtySize(runResult.Get("Id"), false); err != nil {
|
|
| 2368 |
+ if err := cli.monitorTtySize(createResponse.ID, false); err != nil {
|
|
| 2369 | 2369 |
log.Errorf("Error monitoring TTY size: %s", err)
|
| 2370 | 2370 |
} |
| 2371 | 2371 |
} |
| ... | ... |
@@ -2390,26 +2373,26 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
| 2390 | 2390 |
if *flAutoRemove {
|
| 2391 | 2391 |
// Autoremove: wait for the container to finish, retrieve |
| 2392 | 2392 |
// the exit code and remove the container |
| 2393 |
- if _, _, err := readBody(cli.call("POST", "/containers/"+runResult.Get("Id")+"/wait", nil, false)); err != nil {
|
|
| 2393 |
+ if _, _, err := readBody(cli.call("POST", "/containers/"+createResponse.ID+"/wait", nil, false)); err != nil {
|
|
| 2394 | 2394 |
return err |
| 2395 | 2395 |
} |
| 2396 |
- if _, status, err = getExitCode(cli, runResult.Get("Id")); err != nil {
|
|
| 2396 |
+ if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
|
|
| 2397 | 2397 |
return err |
| 2398 | 2398 |
} |
| 2399 |
- if _, _, err := readBody(cli.call("DELETE", "/containers/"+runResult.Get("Id")+"?v=1", nil, false)); err != nil {
|
|
| 2399 |
+ if _, _, err := readBody(cli.call("DELETE", "/containers/"+createResponse.ID+"?v=1", nil, false)); err != nil {
|
|
| 2400 | 2400 |
return err |
| 2401 | 2401 |
} |
| 2402 | 2402 |
} else {
|
| 2403 | 2403 |
// No Autoremove: Simply retrieve the exit code |
| 2404 | 2404 |
if !config.Tty {
|
| 2405 | 2405 |
// In non-TTY mode, we can't detach, so we must wait for container exit |
| 2406 |
- if status, err = waitForExit(cli, runResult.Get("Id")); err != nil {
|
|
| 2406 |
+ if status, err = waitForExit(cli, createResponse.ID); err != nil {
|
|
| 2407 | 2407 |
return err |
| 2408 | 2408 |
} |
| 2409 | 2409 |
} else {
|
| 2410 | 2410 |
// In TTY mode, there is a race: if the process dies too slowly, the state could |
| 2411 | 2411 |
// be updated after the getExitCode call and result in the wrong exit code being reported |
| 2412 |
- if _, status, err = getExitCode(cli, runResult.Get("Id")); err != nil {
|
|
| 2412 |
+ if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
|
|
| 2413 | 2413 |
return err |
| 2414 | 2414 |
} |
| 2415 | 2415 |
} |
| ... | ... |
@@ -2653,7 +2636,7 @@ func (s *containerStats) Collect(cli *DockerCli) {
|
| 2653 | 2653 |
) |
| 2654 | 2654 |
go func() {
|
| 2655 | 2655 |
for {
|
| 2656 |
- var v *stats.Stats |
|
| 2656 |
+ var v *types.Stats |
|
| 2657 | 2657 |
if err := dec.Decode(&v); err != nil {
|
| 2658 | 2658 |
u <- err |
| 2659 | 2659 |
return |
| ... | ... |
@@ -2770,7 +2753,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
|
| 2770 | 2770 |
return nil |
| 2771 | 2771 |
} |
| 2772 | 2772 |
|
| 2773 |
-func calculateCpuPercent(previousCpu, previousSystem uint64, v *stats.Stats) float64 {
|
|
| 2773 |
+func calculateCpuPercent(previousCpu, previousSystem uint64, v *types.Stats) float64 {
|
|
| 2774 | 2774 |
var ( |
| 2775 | 2775 |
cpuPercent = 0.0 |
| 2776 | 2776 |
// calculate the change for the cpu usage of the container in between readings |
| ... | ... |
@@ -27,6 +27,7 @@ import ( |
| 27 | 27 |
|
| 28 | 28 |
log "github.com/Sirupsen/logrus" |
| 29 | 29 |
"github.com/docker/docker/api" |
| 30 |
+ "github.com/docker/docker/api/types" |
|
| 30 | 31 |
"github.com/docker/docker/daemon/networkdriver/portallocator" |
| 31 | 32 |
"github.com/docker/docker/engine" |
| 32 | 33 |
"github.com/docker/docker/pkg/listenbuffer" |
| ... | ... |
@@ -140,12 +141,22 @@ func httpError(w http.ResponseWriter, err error) {
|
| 140 | 140 |
} |
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 |
-func writeJSON(w http.ResponseWriter, code int, v engine.Env) error {
|
|
| 143 |
+// writeJSONEnv writes the engine.Env values to the http response stream as a |
|
| 144 |
+// json encoded body. |
|
| 145 |
+func writeJSONEnv(w http.ResponseWriter, code int, v engine.Env) error {
|
|
| 144 | 146 |
w.Header().Set("Content-Type", "application/json")
|
| 145 | 147 |
w.WriteHeader(code) |
| 146 | 148 |
return v.Encode(w) |
| 147 | 149 |
} |
| 148 | 150 |
|
| 151 |
+// writeJSON writes the value v to the http response stream as json with standard |
|
| 152 |
+// json encoding. |
|
| 153 |
+func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
|
|
| 154 |
+ w.Header().Set("Content-Type", "application/json")
|
|
| 155 |
+ w.WriteHeader(code) |
|
| 156 |
+ return json.NewEncoder(w).Encode(v) |
|
| 157 |
+} |
|
| 158 |
+ |
|
| 149 | 159 |
func streamJSON(job *engine.Job, w http.ResponseWriter, flush bool) {
|
| 150 | 160 |
w.Header().Set("Content-Type", "application/json")
|
| 151 | 161 |
if flush {
|
| ... | ... |
@@ -183,7 +194,7 @@ func postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter |
| 183 | 183 |
if status := engine.Tail(stdoutBuffer, 1); status != "" {
|
| 184 | 184 |
var env engine.Env |
| 185 | 185 |
env.Set("Status", status)
|
| 186 |
- return writeJSON(w, http.StatusOK, env) |
|
| 186 |
+ return writeJSONEnv(w, http.StatusOK, env) |
|
| 187 | 187 |
} |
| 188 | 188 |
w.WriteHeader(http.StatusNoContent) |
| 189 | 189 |
return nil |
| ... | ... |
@@ -526,7 +537,7 @@ func postCommit(eng *engine.Engine, version version.Version, w http.ResponseWrit |
| 526 | 526 |
return err |
| 527 | 527 |
} |
| 528 | 528 |
env.Set("Id", engine.Tail(stdoutBuffer, 1))
|
| 529 |
- return writeJSON(w, http.StatusCreated, env) |
|
| 529 |
+ return writeJSONEnv(w, http.StatusCreated, env) |
|
| 530 | 530 |
} |
| 531 | 531 |
|
| 532 | 532 |
// Creates an image from Pull or from Import |
| ... | ... |
@@ -705,18 +716,16 @@ func postContainersCreate(eng *engine.Engine, version version.Version, w http.Re |
| 705 | 705 |
if err := parseForm(r); err != nil {
|
| 706 | 706 |
return nil |
| 707 | 707 |
} |
| 708 |
+ if err := checkForJson(r); err != nil {
|
|
| 709 |
+ return err |
|
| 710 |
+ } |
|
| 708 | 711 |
var ( |
| 709 |
- out engine.Env |
|
| 710 | 712 |
job = eng.Job("create", r.Form.Get("name"))
|
| 711 | 713 |
outWarnings []string |
| 712 | 714 |
stdoutBuffer = bytes.NewBuffer(nil) |
| 713 | 715 |
warnings = bytes.NewBuffer(nil) |
| 714 | 716 |
) |
| 715 | 717 |
|
| 716 |
- if err := checkForJson(r); err != nil {
|
|
| 717 |
- return err |
|
| 718 |
- } |
|
| 719 |
- |
|
| 720 | 718 |
if err := job.DecodeEnv(r.Body); err != nil {
|
| 721 | 719 |
return err |
| 722 | 720 |
} |
| ... | ... |
@@ -732,10 +741,10 @@ func postContainersCreate(eng *engine.Engine, version version.Version, w http.Re |
| 732 | 732 |
for scanner.Scan() {
|
| 733 | 733 |
outWarnings = append(outWarnings, scanner.Text()) |
| 734 | 734 |
} |
| 735 |
- out.Set("Id", engine.Tail(stdoutBuffer, 1))
|
|
| 736 |
- out.SetList("Warnings", outWarnings)
|
|
| 737 |
- |
|
| 738 |
- return writeJSON(w, http.StatusCreated, out) |
|
| 735 |
+ return writeJSON(w, http.StatusCreated, &types.ContainerCreateResponse{
|
|
| 736 |
+ ID: engine.Tail(stdoutBuffer, 1), |
|
| 737 |
+ Warnings: outWarnings, |
|
| 738 |
+ }) |
|
| 739 | 739 |
} |
| 740 | 740 |
|
| 741 | 741 |
func postContainersRestart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| ... | ... |
@@ -878,7 +887,7 @@ func postContainersWait(eng *engine.Engine, version version.Version, w http.Resp |
| 878 | 878 |
} |
| 879 | 879 |
|
| 880 | 880 |
env.Set("StatusCode", engine.Tail(stdoutBuffer, 1))
|
| 881 |
- return writeJSON(w, http.StatusOK, env) |
|
| 881 |
+ return writeJSONEnv(w, http.StatusOK, env) |
|
| 882 | 882 |
} |
| 883 | 883 |
|
| 884 | 884 |
func postContainersResize(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| ... | ... |
@@ -1149,7 +1158,7 @@ func postContainerExecCreate(eng *engine.Engine, version version.Version, w http |
| 1149 | 1149 |
// Return the ID |
| 1150 | 1150 |
out.Set("Id", engine.Tail(stdoutBuffer, 1))
|
| 1151 | 1151 |
|
| 1152 |
- return writeJSON(w, http.StatusCreated, out) |
|
| 1152 |
+ return writeJSONEnv(w, http.StatusCreated, out) |
|
| 1153 | 1153 |
} |
| 1154 | 1154 |
|
| 1155 | 1155 |
// TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start. |
| 1156 | 1156 |
deleted file mode 100644 |
| ... | ... |
@@ -1,87 +0,0 @@ |
| 1 |
-// This package is used for API stability in the types and response to the |
|
| 2 |
-// consumers of the API stats endpoint. |
|
| 3 |
-package stats |
|
| 4 |
- |
|
| 5 |
-import "time" |
|
| 6 |
- |
|
| 7 |
-type ThrottlingData struct {
|
|
| 8 |
- // Number of periods with throttling active |
|
| 9 |
- Periods uint64 `json:"periods"` |
|
| 10 |
- // Number of periods when the container hit its throttling limit. |
|
| 11 |
- ThrottledPeriods uint64 `json:"throttled_periods"` |
|
| 12 |
- // Aggregate time the container was throttled for in nanoseconds. |
|
| 13 |
- ThrottledTime uint64 `json:"throttled_time"` |
|
| 14 |
-} |
|
| 15 |
- |
|
| 16 |
-// All CPU stats are aggregated since container inception. |
|
| 17 |
-type CpuUsage struct {
|
|
| 18 |
- // Total CPU time consumed. |
|
| 19 |
- // Units: nanoseconds. |
|
| 20 |
- TotalUsage uint64 `json:"total_usage"` |
|
| 21 |
- // Total CPU time consumed per core. |
|
| 22 |
- // Units: nanoseconds. |
|
| 23 |
- PercpuUsage []uint64 `json:"percpu_usage"` |
|
| 24 |
- // Time spent by tasks of the cgroup in kernel mode. |
|
| 25 |
- // Units: nanoseconds. |
|
| 26 |
- UsageInKernelmode uint64 `json:"usage_in_kernelmode"` |
|
| 27 |
- // Time spent by tasks of the cgroup in user mode. |
|
| 28 |
- // Units: nanoseconds. |
|
| 29 |
- UsageInUsermode uint64 `json:"usage_in_usermode"` |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-type CpuStats struct {
|
|
| 33 |
- CpuUsage CpuUsage `json:"cpu_usage"` |
|
| 34 |
- SystemUsage uint64 `json:"system_cpu_usage"` |
|
| 35 |
- ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-type MemoryStats struct {
|
|
| 39 |
- // current res_counter usage for memory |
|
| 40 |
- Usage uint64 `json:"usage"` |
|
| 41 |
- // maximum usage ever recorded. |
|
| 42 |
- MaxUsage uint64 `json:"max_usage"` |
|
| 43 |
- // TODO(vishh): Export these as stronger types. |
|
| 44 |
- // all the stats exported via memory.stat. |
|
| 45 |
- Stats map[string]uint64 `json:"stats"` |
|
| 46 |
- // number of times memory usage hits limits. |
|
| 47 |
- Failcnt uint64 `json:"failcnt"` |
|
| 48 |
- Limit uint64 `json:"limit"` |
|
| 49 |
-} |
|
| 50 |
- |
|
| 51 |
-type BlkioStatEntry struct {
|
|
| 52 |
- Major uint64 `json:"major"` |
|
| 53 |
- Minor uint64 `json:"minor"` |
|
| 54 |
- Op string `json:"op"` |
|
| 55 |
- Value uint64 `json:"value"` |
|
| 56 |
-} |
|
| 57 |
- |
|
| 58 |
-type BlkioStats struct {
|
|
| 59 |
- // number of bytes tranferred to and from the block device |
|
| 60 |
- IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"` |
|
| 61 |
- IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"` |
|
| 62 |
- IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"` |
|
| 63 |
- IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"` |
|
| 64 |
- IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"` |
|
| 65 |
- IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"` |
|
| 66 |
- IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"` |
|
| 67 |
- SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"` |
|
| 68 |
-} |
|
| 69 |
- |
|
| 70 |
-type Network struct {
|
|
| 71 |
- RxBytes uint64 `json:"rx_bytes"` |
|
| 72 |
- RxPackets uint64 `json:"rx_packets"` |
|
| 73 |
- RxErrors uint64 `json:"rx_errors"` |
|
| 74 |
- RxDropped uint64 `json:"rx_dropped"` |
|
| 75 |
- TxBytes uint64 `json:"tx_bytes"` |
|
| 76 |
- TxPackets uint64 `json:"tx_packets"` |
|
| 77 |
- TxErrors uint64 `json:"tx_errors"` |
|
| 78 |
- TxDropped uint64 `json:"tx_dropped"` |
|
| 79 |
-} |
|
| 80 |
- |
|
| 81 |
-type Stats struct {
|
|
| 82 |
- Read time.Time `json:"read"` |
|
| 83 |
- Network Network `json:"network,omitempty"` |
|
| 84 |
- CpuStats CpuStats `json:"cpu_stats,omitempty"` |
|
| 85 |
- MemoryStats MemoryStats `json:"memory_stats,omitempty"` |
|
| 86 |
- BlkioStats BlkioStats `json:"blkio_stats,omitempty"` |
|
| 87 |
-} |
| 88 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,87 @@ |
| 0 |
+// This package is used for API stability in the types and response to the |
|
| 1 |
+// consumers of the API stats endpoint. |
|
| 2 |
+package types |
|
| 3 |
+ |
|
| 4 |
+import "time" |
|
| 5 |
+ |
|
| 6 |
+type ThrottlingData struct {
|
|
| 7 |
+ // Number of periods with throttling active |
|
| 8 |
+ Periods uint64 `json:"periods"` |
|
| 9 |
+ // Number of periods when the container hit its throttling limit. |
|
| 10 |
+ ThrottledPeriods uint64 `json:"throttled_periods"` |
|
| 11 |
+ // Aggregate time the container was throttled for in nanoseconds. |
|
| 12 |
+ ThrottledTime uint64 `json:"throttled_time"` |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+// All CPU stats are aggregated since container inception. |
|
| 16 |
+type CpuUsage struct {
|
|
| 17 |
+ // Total CPU time consumed. |
|
| 18 |
+ // Units: nanoseconds. |
|
| 19 |
+ TotalUsage uint64 `json:"total_usage"` |
|
| 20 |
+ // Total CPU time consumed per core. |
|
| 21 |
+ // Units: nanoseconds. |
|
| 22 |
+ PercpuUsage []uint64 `json:"percpu_usage"` |
|
| 23 |
+ // Time spent by tasks of the cgroup in kernel mode. |
|
| 24 |
+ // Units: nanoseconds. |
|
| 25 |
+ UsageInKernelmode uint64 `json:"usage_in_kernelmode"` |
|
| 26 |
+ // Time spent by tasks of the cgroup in user mode. |
|
| 27 |
+ // Units: nanoseconds. |
|
| 28 |
+ UsageInUsermode uint64 `json:"usage_in_usermode"` |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+type CpuStats struct {
|
|
| 32 |
+ CpuUsage CpuUsage `json:"cpu_usage"` |
|
| 33 |
+ SystemUsage uint64 `json:"system_cpu_usage"` |
|
| 34 |
+ ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+type MemoryStats struct {
|
|
| 38 |
+ // current res_counter usage for memory |
|
| 39 |
+ Usage uint64 `json:"usage"` |
|
| 40 |
+ // maximum usage ever recorded. |
|
| 41 |
+ MaxUsage uint64 `json:"max_usage"` |
|
| 42 |
+ // TODO(vishh): Export these as stronger types. |
|
| 43 |
+ // all the stats exported via memory.stat. |
|
| 44 |
+ Stats map[string]uint64 `json:"stats"` |
|
| 45 |
+ // number of times memory usage hits limits. |
|
| 46 |
+ Failcnt uint64 `json:"failcnt"` |
|
| 47 |
+ Limit uint64 `json:"limit"` |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+type BlkioStatEntry struct {
|
|
| 51 |
+ Major uint64 `json:"major"` |
|
| 52 |
+ Minor uint64 `json:"minor"` |
|
| 53 |
+ Op string `json:"op"` |
|
| 54 |
+ Value uint64 `json:"value"` |
|
| 55 |
+} |
|
| 56 |
+ |
|
| 57 |
+type BlkioStats struct {
|
|
| 58 |
+ // number of bytes tranferred to and from the block device |
|
| 59 |
+ IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"` |
|
| 60 |
+ IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"` |
|
| 61 |
+ IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"` |
|
| 62 |
+ IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"` |
|
| 63 |
+ IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"` |
|
| 64 |
+ IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"` |
|
| 65 |
+ IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"` |
|
| 66 |
+ SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"` |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+type Network struct {
|
|
| 70 |
+ RxBytes uint64 `json:"rx_bytes"` |
|
| 71 |
+ RxPackets uint64 `json:"rx_packets"` |
|
| 72 |
+ RxErrors uint64 `json:"rx_errors"` |
|
| 73 |
+ RxDropped uint64 `json:"rx_dropped"` |
|
| 74 |
+ TxBytes uint64 `json:"tx_bytes"` |
|
| 75 |
+ TxPackets uint64 `json:"tx_packets"` |
|
| 76 |
+ TxErrors uint64 `json:"tx_errors"` |
|
| 77 |
+ TxDropped uint64 `json:"tx_dropped"` |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+type Stats struct {
|
|
| 81 |
+ Read time.Time `json:"read"` |
|
| 82 |
+ Network Network `json:"network,omitempty"` |
|
| 83 |
+ CpuStats CpuStats `json:"cpu_stats,omitempty"` |
|
| 84 |
+ MemoryStats MemoryStats `json:"memory_stats,omitempty"` |
|
| 85 |
+ BlkioStats BlkioStats `json:"blkio_stats,omitempty"` |
|
| 86 |
+} |
| 0 | 87 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,11 @@ |
| 0 |
+package types |
|
| 1 |
+ |
|
| 2 |
+// ContainerCreateResponse contains the information returned to a client on the |
|
| 3 |
+// creation of a new container. |
|
| 4 |
+type ContainerCreateResponse struct {
|
|
| 5 |
+ // ID is the ID of the created container. |
|
| 6 |
+ ID string `json:"Id"` |
|
| 7 |
+ |
|
| 8 |
+ // Warnings are any warnings encountered during the creation of the container. |
|
| 9 |
+ Warnings []string `json:"Warnings"` |
|
| 10 |
+} |
| ... | ... |
@@ -3,7 +3,7 @@ package daemon |
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 | 5 |
|
| 6 |
- "github.com/docker/docker/api/stats" |
|
| 6 |
+ "github.com/docker/docker/api/types" |
|
| 7 | 7 |
"github.com/docker/docker/daemon/execdriver" |
| 8 | 8 |
"github.com/docker/docker/engine" |
| 9 | 9 |
"github.com/docker/libcontainer" |
| ... | ... |
@@ -33,10 +33,10 @@ func (daemon *Daemon) ContainerStats(job *engine.Job) engine.Status {
|
| 33 | 33 |
|
| 34 | 34 |
// convertToAPITypes converts the libcontainer.ContainerStats to the api specific |
| 35 | 35 |
// structs. This is done to preserve API compatibility and versioning. |
| 36 |
-func convertToAPITypes(ls *libcontainer.ContainerStats) *stats.Stats {
|
|
| 37 |
- s := &stats.Stats{}
|
|
| 36 |
+func convertToAPITypes(ls *libcontainer.ContainerStats) *types.Stats {
|
|
| 37 |
+ s := &types.Stats{}
|
|
| 38 | 38 |
if ls.NetworkStats != nil {
|
| 39 |
- s.Network = stats.Network{
|
|
| 39 |
+ s.Network = types.Network{
|
|
| 40 | 40 |
RxBytes: ls.NetworkStats.RxBytes, |
| 41 | 41 |
RxPackets: ls.NetworkStats.RxPackets, |
| 42 | 42 |
RxErrors: ls.NetworkStats.RxErrors, |
| ... | ... |
@@ -49,7 +49,7 @@ func convertToAPITypes(ls *libcontainer.ContainerStats) *stats.Stats {
|
| 49 | 49 |
} |
| 50 | 50 |
cs := ls.CgroupStats |
| 51 | 51 |
if cs != nil {
|
| 52 |
- s.BlkioStats = stats.BlkioStats{
|
|
| 52 |
+ s.BlkioStats = types.BlkioStats{
|
|
| 53 | 53 |
IoServiceBytesRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceBytesRecursive), |
| 54 | 54 |
IoServicedRecursive: copyBlkioEntry(cs.BlkioStats.IoServicedRecursive), |
| 55 | 55 |
IoQueuedRecursive: copyBlkioEntry(cs.BlkioStats.IoQueuedRecursive), |
| ... | ... |
@@ -60,21 +60,21 @@ func convertToAPITypes(ls *libcontainer.ContainerStats) *stats.Stats {
|
| 60 | 60 |
SectorsRecursive: copyBlkioEntry(cs.BlkioStats.SectorsRecursive), |
| 61 | 61 |
} |
| 62 | 62 |
cpu := cs.CpuStats |
| 63 |
- s.CpuStats = stats.CpuStats{
|
|
| 64 |
- CpuUsage: stats.CpuUsage{
|
|
| 63 |
+ s.CpuStats = types.CpuStats{
|
|
| 64 |
+ CpuUsage: types.CpuUsage{
|
|
| 65 | 65 |
TotalUsage: cpu.CpuUsage.TotalUsage, |
| 66 | 66 |
PercpuUsage: cpu.CpuUsage.PercpuUsage, |
| 67 | 67 |
UsageInKernelmode: cpu.CpuUsage.UsageInKernelmode, |
| 68 | 68 |
UsageInUsermode: cpu.CpuUsage.UsageInUsermode, |
| 69 | 69 |
}, |
| 70 |
- ThrottlingData: stats.ThrottlingData{
|
|
| 70 |
+ ThrottlingData: types.ThrottlingData{
|
|
| 71 | 71 |
Periods: cpu.ThrottlingData.Periods, |
| 72 | 72 |
ThrottledPeriods: cpu.ThrottlingData.ThrottledPeriods, |
| 73 | 73 |
ThrottledTime: cpu.ThrottlingData.ThrottledTime, |
| 74 | 74 |
}, |
| 75 | 75 |
} |
| 76 | 76 |
mem := cs.MemoryStats |
| 77 |
- s.MemoryStats = stats.MemoryStats{
|
|
| 77 |
+ s.MemoryStats = types.MemoryStats{
|
|
| 78 | 78 |
Usage: mem.Usage, |
| 79 | 79 |
MaxUsage: mem.MaxUsage, |
| 80 | 80 |
Stats: mem.Stats, |
| ... | ... |
@@ -84,10 +84,10 @@ func convertToAPITypes(ls *libcontainer.ContainerStats) *stats.Stats {
|
| 84 | 84 |
return s |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
-func copyBlkioEntry(entries []cgroups.BlkioStatEntry) []stats.BlkioStatEntry {
|
|
| 88 |
- out := make([]stats.BlkioStatEntry, len(entries)) |
|
| 87 |
+func copyBlkioEntry(entries []cgroups.BlkioStatEntry) []types.BlkioStatEntry {
|
|
| 88 |
+ out := make([]types.BlkioStatEntry, len(entries)) |
|
| 89 | 89 |
for i, re := range entries {
|
| 90 |
- out[i] = stats.BlkioStatEntry{
|
|
| 90 |
+ out[i] = types.BlkioStatEntry{
|
|
| 91 | 91 |
Major: re.Major, |
| 92 | 92 |
Minor: re.Minor, |
| 93 | 93 |
Op: re.Op, |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"testing" |
| 10 | 10 |
"time" |
| 11 | 11 |
|
| 12 |
- "github.com/docker/docker/api/stats" |
|
| 12 |
+ "github.com/docker/docker/api/types" |
|
| 13 | 13 |
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" |
| 14 | 14 |
) |
| 15 | 15 |
|
| ... | ... |
@@ -311,7 +311,7 @@ func TestGetContainerStats(t *testing.T) {
|
| 311 | 311 |
} |
| 312 | 312 |
|
| 313 | 313 |
dec := json.NewDecoder(bytes.NewBuffer(sr.body)) |
| 314 |
- var s *stats.Stats |
|
| 314 |
+ var s *types.Stats |
|
| 315 | 315 |
// decode only one object from the stream |
| 316 | 316 |
if err := dec.Decode(&s); err != nil {
|
| 317 | 317 |
t.Fatal(err) |