summaryrefslogtreecommitdiff
path: root/pkg/api/handlers/compat/containers.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers/compat/containers.go')
-rw-r--r--pkg/api/handlers/compat/containers.go127
1 files changed, 84 insertions, 43 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index aa12afc82..b41987800 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -22,6 +22,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
+ "github.com/docker/go-units"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -31,11 +32,11 @@ import (
func RemoveContainer(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
- All bool `schema:"all"`
- Force bool `schema:"force"`
- Ignore bool `schema:"ignore"`
- Link bool `schema:"link"`
- Volumes bool `schema:"v"`
+ Force bool `schema:"force"`
+ Ignore bool `schema:"ignore"`
+ Link bool `schema:"link"`
+ DockerVolumes bool `schema:"v"`
+ LibpodVolumes bool `schema:"volumes"`
}{
// override any golang type defaults
}
@@ -46,10 +47,19 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
return
}
- if query.Link && !utils.IsLibpodRequest(r) {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- utils.ErrLinkNotSupport)
- return
+ options := entities.RmOptions{
+ Force: query.Force,
+ Ignore: query.Ignore,
+ }
+ if utils.IsLibpodRequest(r) {
+ options.Volumes = query.LibpodVolumes
+ } else {
+ if query.Link {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.ErrLinkNotSupport)
+ return
+ }
+ options.Volumes = query.DockerVolumes
}
runtime := r.Context().Value("runtime").(*libpod.Runtime)
@@ -57,12 +67,6 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
// code.
containerEngine := abi.ContainerEngine{Libpod: runtime}
name := utils.GetName(r)
- options := entities.RmOptions{
- All: query.All,
- Force: query.Force,
- Volumes: query.Volumes,
- Ignore: query.Ignore,
- }
report, err := containerEngine.ContainerRm(r.Context(), []string{name}, options)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
@@ -73,7 +77,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- if report[0].Err != nil {
+ if len(report) > 0 && report[0].Err != nil {
utils.InternalServerError(w, report[0].Err)
return
}
@@ -193,45 +197,48 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
return
}
- sig, err := signal.ParseSignalNameOrNumber(query.Signal)
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
+ // Now use the ABI implementation to prevent us from having duplicate
+ // code.
+ containerEngine := abi.ContainerEngine{Libpod: runtime}
name := utils.GetName(r)
- con, err := runtime.LookupContainer(name)
- if err != nil {
- utils.ContainerNotFound(w, name, err)
- return
+ options := entities.KillOptions{
+ Signal: query.Signal,
}
-
- state, err := con.State()
+ report, err := containerEngine.ContainerKill(r.Context(), []string{name}, options)
if err != nil {
- utils.InternalServerError(w, err)
- return
- }
+ if errors.Cause(err) == define.ErrCtrStateInvalid ||
+ errors.Cause(err) == define.ErrCtrStopped {
+ utils.Error(w, fmt.Sprintf("Container %s is not running", name), http.StatusConflict, err)
+ return
+ }
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ utils.ContainerNotFound(w, name, err)
+ return
+ }
- // If the Container is stopped already, send a 409
- if state == define.ContainerStateStopped || state == define.ContainerStateExited {
- utils.Error(w, fmt.Sprintf("Container %s is not running", name), http.StatusConflict, errors.New(fmt.Sprintf("Cannot kill Container %s, it is not running", name)))
+ utils.InternalServerError(w, err)
return
}
- signal := uint(sig)
-
- err = con.Kill(signal)
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "unable to kill Container %s", name))
+ if len(report) > 0 && report[0].Err != nil {
+ utils.InternalServerError(w, report[0].Err)
return
}
-
// Docker waits for the container to stop if the signal is 0 or
// SIGKILL.
- if !utils.IsLibpodRequest(r) && (signal == 0 || syscall.Signal(signal) == syscall.SIGKILL) {
- if _, err = con.Wait(); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to wait for Container %s", con.ID()))
+ if !utils.IsLibpodRequest(r) {
+ sig, err := signal.ParseSignalNameOrNumber(query.Signal)
+ if err != nil {
+ utils.InternalServerError(w, err)
return
}
+ if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
+ var opts entities.WaitOptions
+ if _, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ return
+ }
+ }
}
// Success
utils.WriteResponse(w, http.StatusNoContent, nil)
@@ -242,6 +249,10 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) {
// /{version}/containers/(name)/wait
exitCode, err := utils.WaitContainer(w, r)
if err != nil {
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ logrus.Warnf("container not found %q: %v", utils.GetName(r), err)
+ return
+ }
logrus.Warnf("failed to wait on container %q: %v", mux.Vars(r)["name"], err)
return
}
@@ -264,6 +275,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
sizeRootFs int64
sizeRW int64
state define.ContainerStatus
+ status string
)
if state, err = l.State(); err != nil {
@@ -274,6 +286,35 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
stateStr = "created"
}
+ if state == define.ContainerStateConfigured || state == define.ContainerStateCreated {
+ status = "Created"
+ } else if state == define.ContainerStateStopped || state == define.ContainerStateExited {
+ exitCode, _, err := l.ExitCode()
+ if err != nil {
+ return nil, err
+ }
+ finishedTime, err := l.FinishedTime()
+ if err != nil {
+ return nil, err
+ }
+ status = fmt.Sprintf("Exited (%d) %s ago", exitCode, units.HumanDuration(time.Since(finishedTime)))
+ } else if state == define.ContainerStateRunning || state == define.ContainerStatePaused {
+ startedTime, err := l.StartedTime()
+ if err != nil {
+ return nil, err
+ }
+ status = fmt.Sprintf("Up %s", units.HumanDuration(time.Since(startedTime)))
+ if state == define.ContainerStatePaused {
+ status += " (Paused)"
+ }
+ } else if state == define.ContainerStateRemoving {
+ status = "Removal In Progress"
+ } else if state == define.ContainerStateStopping {
+ status = "Stopping"
+ } else {
+ status = "Unknown"
+ }
+
if sz {
if sizeRW, err = l.RWSize(); err != nil {
return nil, err
@@ -295,7 +336,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
SizeRootFs: sizeRootFs,
Labels: l.Labels(),
State: stateStr,
- Status: "",
+ Status: status,
HostConfig: struct {
NetworkMode string `json:",omitempty"`
}{