diff options
Diffstat (limited to 'pkg/api')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 7 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images.go | 12 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_build.go | 6 | ||||
-rw-r--r-- | pkg/api/handlers/utils/containers.go | 35 |
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) { |