diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 3 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 62 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/events.go | 32 | ||||
-rw-r--r-- | pkg/varlinkapi/system.go | 8 |
4 files changed, 92 insertions, 13 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index b1ef08cda..63c44eaef 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -85,7 +85,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 +175,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/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index d0f90d900..7ea3b16a6 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -481,27 +481,67 @@ func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, input, func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { reports := []*entities.ContainerStartReport{} - for _, name := range namesOrIds { + var exitCode = define.ExecErrorCodeGeneric + ctrs, err := getContainersByContext(ic.ClientCxt, false, false, namesOrIds) + if err != nil { + return nil, err + } + // There can only be one container if attach was used + for i, ctr := range ctrs { + name := ctr.ID report := entities.ContainerStartReport{ Id: name, - RawInput: name, - ExitCode: 125, + RawInput: namesOrIds[i], + ExitCode: exitCode, } + ctrRunning := ctr.State == define.ContainerStateRunning.String() if options.Attach { - report.Err = startAndAttach(ic, name, &options.DetachKeys, options.Stdin, options.Stdout, options.Stderr) - if report.Err == nil { - exitCode, err := containers.Wait(ic.ClientCxt, name, nil) - if err == nil { - report.ExitCode = int(exitCode) + err = startAndAttach(ic, name, &options.DetachKeys, options.Stdin, options.Stdout, options.Stderr) + if err == define.ErrDetach { + // User manually detached + // Exit cleanly immediately + report.Err = err + reports = append(reports, &report) + return reports, nil + } + if ctrRunning { + reports = append(reports, &report) + return reports, nil + } + + if err != nil { + report.ExitCode = define.ExitCode(report.Err) + report.Err = err + reports = append(reports, &report) + return reports, errors.Wrapf(report.Err, "unable to start container %s", name) + } + exitCode, err := containers.Wait(ic.ClientCxt, name, nil) + if err == define.ErrNoSuchCtr { + // Check events + event, err := ic.GetLastContainerEvent(ctx, name, events.Exited) + if err != nil { + logrus.Errorf("Cannot get exit code: %v", err) + report.ExitCode = define.ExecErrorCodeNotFound + } else { + report.ExitCode = event.ContainerExitCode } } else { - report.ExitCode = define.ExitCode(report.Err) + report.ExitCode = int(exitCode) } reports = append(reports, &report) return reports, nil } - report.Err = containers.Start(ic.ClientCxt, name, &options.DetachKeys) - report.ExitCode = define.ExitCode(report.Err) + // Start the container if it's not running already. + if !ctrRunning { + err = containers.Start(ic.ClientCxt, name, &options.DetachKeys) + if err != nil { + report.Err = errors.Wrapf(err, "unable to start container %q", name) + report.ExitCode = define.ExitCode(err) + reports = append(reports, &report) + continue + } + } + report.ExitCode = 0 reports = append(reports, &report) } return reports, nil diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go index e6f4834b9..53bae6cef 100644 --- a/pkg/domain/infra/tunnel/events.go +++ b/pkg/domain/infra/tunnel/events.go @@ -2,8 +2,10 @@ package tunnel import ( "context" + // "fmt" "strings" + "github.com/containers/podman/v2/libpod/events" "github.com/containers/podman/v2/pkg/bindings/system" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/pkg/errors" @@ -29,3 +31,33 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio }() return system.Events(ic.ClientCxt, binChan, nil, &opts.Since, &opts.Until, filters, &opts.Stream) } + +// GetLastContainerEvent takes a container name or ID and an event status and returns +// the last occurrence of the container event +func (ic *ContainerEngine) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) { + // check to make sure the event.Status is valid + if _, err := events.StringToStatus(containerEvent.String()); err != nil { + return nil, err + } + var event events.Event + return &event, nil + + /* + FIXME: We need new bindings for this section + filters := []string{ + fmt.Sprintf("container=%s", nameOrID), + fmt.Sprintf("event=%s", containerEvent), + "type=container", + } + + containerEvents, err := system.GetEvents(ctx, entities.EventsOptions{Filter: filters}) + if err != nil { + return nil, err + } + if len(containerEvents) < 1 { + return nil, errors.Wrapf(events.ErrEventNotFound, "%s not found", containerEvent.String()) + } + // return the last element in the slice + return containerEvents[len(containerEvents)-1], nil + */ +} diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go index 9e4db2611..e5c766a6d 100644 --- a/pkg/varlinkapi/system.go +++ b/pkg/varlinkapi/system.go @@ -7,6 +7,7 @@ import ( "fmt" "os" goruntime "runtime" + "strconv" "time" "github.com/containers/image/v5/pkg/sysregistriesv2" @@ -22,13 +23,18 @@ func (i *VarlinkAPI) GetVersion(call iopodman.VarlinkCall) error { return err } + int64APIVersion, err := strconv.ParseInt(versionInfo.APIVersion, 10, 64) + if err != nil { + return err + } + return call.ReplyGetVersion( versionInfo.Version, versionInfo.GoVersion, versionInfo.GitCommit, time.Unix(versionInfo.Built, 0).Format(time.RFC3339), versionInfo.OsArch, - versionInfo.APIVersion, + int64APIVersion, ) } |