diff options
Diffstat (limited to 'pkg/api/handlers/compat')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 25 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_create.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_logs.go | 21 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_stats.go | 43 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images.go | 14 | ||||
-rw-r--r-- | pkg/api/handlers/compat/volumes.go | 23 |
6 files changed, 108 insertions, 20 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index b1ef08cda..3a904ba87 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -17,6 +17,7 @@ import ( "github.com/docker/go-connections/nat" "github.com/gorilla/schema" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) func RemoveContainer(w http.ResponseWriter, r *http.Request) { @@ -44,8 +45,25 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) name := utils.GetName(r) con, err := runtime.LookupContainer(name) - if err != nil { - utils.ContainerNotFound(w, name, err) + if err != nil && errors.Cause(err) == define.ErrNoSuchCtr { + // Failed to get container. If force is specified, get the container's ID + // and evict it + if !query.Force { + utils.ContainerNotFound(w, name, err) + return + } + + if _, err := runtime.EvictContainer(r.Context(), name, query.Vols); err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + logrus.Debugf("Ignoring error (--allow-missing): %q", err) + w.WriteHeader(http.StatusNoContent) + return + } + logrus.Warn(errors.Wrapf(err, "Failed to evict container: %q", name)) + utils.InternalServerError(w, err) + return + } + w.WriteHeader(http.StatusNoContent) return } @@ -85,7 +103,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - if _, found := r.URL.Query()["limit"]; found && query.Limit != -1 { + if _, found := r.URL.Query()["limit"]; found && query.Limit > 0 { last := query.Limit if len(containers) > last { containers = containers[len(containers)-last:] @@ -175,6 +193,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) { err = con.Kill(signal) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "unable to kill Container %s", name)) + return } // Docker waits for the container to stop if the signal is 0 or diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 93e4fe540..1d0b4c45d 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -210,7 +210,7 @@ func makeCreateConfig(ctx context.Context, containerConfig *config.Config, input ImageID: newImage.ID(), BuiltinImgVolumes: nil, // podman ImageVolumeType: "", // podman - Interactive: false, + Interactive: input.OpenStdin, // IpcMode: input.HostConfig.IpcMode, Labels: input.Labels, LogDriver: input.HostConfig.LogConfig.Type, // is this correct diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go index f6d4a518e..d24b7d959 100644 --- a/pkg/api/handlers/compat/containers_logs.go +++ b/pkg/api/handlers/compat/containers_logs.go @@ -105,6 +105,18 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { var frame strings.Builder header := make([]byte, 8) + + writeHeader := true + // Docker does not write stream headers iff the container has a tty. + if !utils.IsLibpodRequest(r) { + inspectData, err := ctnr.Inspect(false) + if err != nil { + utils.InternalServerError(w, errors.Wrapf(err, "Failed to obtain logs for Container '%s'", name)) + return + } + writeHeader = !inspectData.Config.Tty + } + for line := range logChannel { if _, found := r.URL.Query()["until"]; found { if line.Time.After(until) { @@ -138,10 +150,13 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { } frame.WriteString(line.Msg) - binary.BigEndian.PutUint32(header[4:], uint32(frame.Len())) - if _, err := w.Write(header[0:8]); err != nil { - log.Errorf("unable to write log output header: %q", err) + if writeHeader { + binary.BigEndian.PutUint32(header[4:], uint32(frame.Len())) + if _, err := w.Write(header[0:8]); err != nil { + log.Errorf("unable to write log output header: %q", err) + } } + if _, err := io.WriteString(w, frame.String()); err != nil { log.Errorf("unable to write frame string: %q", err) } diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 3d7d49ad3..16bd0518a 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -75,32 +75,48 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { } } - for ok := true; ok; ok = query.Stream { + // Write header and content type. + w.WriteHeader(http.StatusOK) + w.Header().Add("Content-Type", "application/json") + if flusher, ok := w.(http.Flusher); ok { + flusher.Flush() + } + + // Setup JSON encoder for streaming. + coder := json.NewEncoder(w) + coder.SetEscapeHTML(true) + +streamLabel: // A label to flatten the scope + select { + case <-r.Context().Done(): + logrus.Debugf("Client connection (container stats) cancelled") + + default: // Container stats stats, err := ctnr.GetContainerStats(stats) if err != nil { - utils.InternalServerError(w, err) + logrus.Errorf("Unable to get container stats: %v", err) return } inspect, err := ctnr.Inspect(false) if err != nil { - utils.InternalServerError(w, err) + logrus.Errorf("Unable to inspect container: %v", err) return } // Cgroup stats cgroupPath, err := ctnr.CGroupPath() if err != nil { - utils.InternalServerError(w, err) + logrus.Errorf("Unable to get cgroup path of container: %v", err) return } cgroup, err := cgroups.Load(cgroupPath) if err != nil { - utils.InternalServerError(w, err) + logrus.Errorf("Unable to load cgroup: %v", err) return } cgroupStat, err := cgroup.Stat() if err != nil { - utils.InternalServerError(w, err) + logrus.Errorf("Unable to get cgroup stats: %v", err) return } @@ -175,11 +191,18 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { Networks: net, } - utils.WriteJSON(w, http.StatusOK, s) + if err := coder.Encode(s); err != nil { + logrus.Errorf("Unable to encode stats: %v", err) + return + } if flusher, ok := w.(http.Flusher); ok { flusher.Flush() } + if !query.Stream { + return + } + preRead = s.Read bits, err := json.Marshal(s.CPUStats) if err != nil { @@ -189,10 +212,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { logrus.Errorf("Unable to unmarshal previous stats: %q", err) } - // Only sleep when we're streaming. - if query.Stream { - time.Sleep(DefaultStatsPeriod) - } + time.Sleep(DefaultStatsPeriod) + goto streamLabel } } diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index c1ba9ca66..0900d1793 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/containers/buildah" + "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" "github.com/containers/podman/v2/libpod" image2 "github.com/containers/podman/v2/libpod/image" @@ -17,7 +18,6 @@ import ( "github.com/containers/podman/v2/pkg/api/handlers/utils" "github.com/containers/podman/v2/pkg/auth" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/containers/podman/v2/pkg/util" "github.com/docker/docker/api/types" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -268,6 +268,16 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { if sys := runtime.SystemContext(); sys != nil { registryOpts.DockerCertPath = sys.DockerCertPath } + rtc, err := runtime.GetConfig() + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + return + } + pullPolicy, err := config.ValidatePullPolicy(rtc.Engine.PullPolicy) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + return + } img, err := runtime.ImageRuntime().New(r.Context(), fromImage, "", // signature policy @@ -276,7 +286,7 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { ®istryOpts, image2.SigningOptions{}, nil, // label - util.PullImageMissing, + pullPolicy, ) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go index 976c52acb..a45509fdb 100644 --- a/pkg/api/handlers/compat/volumes.go +++ b/pkg/api/handlers/compat/volumes.go @@ -93,6 +93,29 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { return } + // See if the volume exists already + existingVolume, err := runtime.GetVolume(input.Name) + if err != nil && errors.Cause(err) != define.ErrNoSuchVolume { + utils.InternalServerError(w, err) + return + } + + // if using the compat layer and the volume already exists, we + // must return a 201 with the same information as create + if existingVolume != nil && !utils.IsLibpodRequest(r) { + response := docker_api_types.Volume{ + CreatedAt: existingVolume.CreatedTime().Format(time.RFC3339), + Driver: existingVolume.Driver(), + Labels: existingVolume.Labels(), + Mountpoint: existingVolume.MountPoint(), + Name: existingVolume.Name(), + Options: existingVolume.Options(), + Scope: existingVolume.Scope(), + } + utils.WriteResponse(w, http.StatusCreated, response) + return + } + if len(input.Name) > 0 { volumeOptions = append(volumeOptions, libpod.WithVolumeName(input.Name)) } |