summaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/compat/containers.go7
-rw-r--r--pkg/api/handlers/compat/images.go12
-rw-r--r--pkg/api/handlers/compat/images_build.go6
-rw-r--r--pkg/api/handlers/utils/containers.go35
4 files changed, 45 insertions, 15 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 263d64a7b..6bc02dd2b 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -379,6 +379,11 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
if err != nil {
return nil, err
}
+ // Docker uses UTC
+ if inspect != nil && inspect.State != nil {
+ inspect.State.StartedAt = inspect.State.StartedAt.UTC()
+ inspect.State.FinishedAt = inspect.State.FinishedAt.UTC()
+ }
i, err := json.Marshal(inspect.State)
if err != nil {
return nil, err
@@ -425,7 +430,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
cb := types.ContainerJSONBase{
ID: l.ID(),
- Created: l.CreatedTime().Format(time.RFC3339Nano),
+ Created: l.CreatedTime().UTC().Format(time.RFC3339Nano), // Docker uses UTC
Path: inspect.Path,
Args: inspect.Args,
State: &state,
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 4b7a2a71c..3f4320efa 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -324,7 +324,11 @@ loop: // break out of for/select infinite loop
flush()
case <-runCtx.Done():
if !failed {
- report.Status = "Pull complete"
+ if utils.IsLibpodRequest(r) {
+ report.Status = "Pull complete"
+ } else {
+ report.Status = "Download complete"
+ }
report.Id = img[0:12]
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
@@ -455,10 +459,6 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, fmt.Errorf("no images to download"))
return
}
- if len(query.Names) > 1 {
- utils.Error(w, "Something went wrong.", http.StatusNotImplemented, fmt.Errorf("getting multiple image is not supported yet"))
- return
- }
images := query.Names
tmpfile, err := ioutil.TempFile("", "api.tar")
@@ -474,7 +474,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
- saveOptions := entities.ImageSaveOptions{Format: "docker-archive", Output: tmpfile.Name()}
+ saveOptions := entities.ImageSaveOptions{Format: "docker-archive", Output: tmpfile.Name(), MultiImageArchive: true}
if err := imageEngine.Save(r.Context(), images[0], images[1:], saveOptions); err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index ec40fdd2d..6ff557291 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -24,7 +24,7 @@ import (
"github.com/containers/podman/v3/pkg/channel"
"github.com/containers/storage/pkg/archive"
"github.com/gorilla/schema"
- specs "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -553,6 +553,10 @@ loop:
}
}
break loop
+ case <-r.Context().Done():
+ cancel()
+ logrus.Infof("Client disconnect reported for build %q / %q.", registry, query.Dockerfile)
+ return
}
}
}
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index c4c9cc2ea..6c708f74e 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -7,6 +7,7 @@ import (
"strconv"
"time"
+ "github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -175,7 +176,7 @@ func waitDockerCondition(ctx context.Context, containerName string, interval tim
var code int32
switch dockerCondition {
case "next-exit":
- code, err = waitNextExit(containerWait)
+ code, err = waitNextExit(ctx, containerName)
case "removed":
code, err = waitRemoved(containerWait)
case "not-running", "":
@@ -202,12 +203,32 @@ func waitRemoved(ctrWait containerWaitFn) (int32, error) {
return code, err
}
-func waitNextExit(ctrWait containerWaitFn) (int32, error) {
- _, err := ctrWait(define.ContainerStateRunning)
- if err != nil {
- return -1, err
- }
- return ctrWait(notRunningStates...)
+func waitNextExit(ctx context.Context, containerName string) (int32, error) {
+ runtime := ctx.Value("runtime").(*libpod.Runtime)
+ containerEngine := &abi.ContainerEngine{Libpod: runtime}
+ eventChannel := make(chan *events.Event)
+ errChannel := make(chan error)
+ opts := entities.EventsOptions{
+ EventChan: eventChannel,
+ Filter: []string{"event=died", fmt.Sprintf("container=%s", containerName)},
+ Stream: true,
+ }
+
+ // ctx is used to cancel event watching goroutine
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+ go func() {
+ errChannel <- containerEngine.Events(ctx, opts)
+ }()
+
+ evt, ok := <-eventChannel
+ if ok {
+ return int32(evt.ContainerExitCode), nil
+ }
+ // if ok == false then containerEngine.Events() has exited
+ // it may happen if request was canceled (e.g. client closed connection prematurely) or
+ // the server is in process of shutting down
+ return -1, <-errChannel
}
func waitNotRunning(ctrWait containerWaitFn) (int32, error) {