moby--moby/api/client/container/utils.go

93 lines
2.3 KiB
Go

package container
import (
"fmt"
"strconv"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/client"
"github.com/docker/docker/api/client/system"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
clientapi "github.com/docker/docker/client"
)
func waitExitOrRemoved(dockerCli *client.DockerCli, ctx context.Context, containerID string, waitRemove bool) (chan int, error) {
if len(containerID) == 0 {
// containerID can never be empty
panic("Internal Error: waitExitOrRemoved needs a containerID as parameter")
}
statusChan := make(chan int)
exitCode := 125
eventProcessor := func(e events.Message, err error) error {
if err != nil {
statusChan <- exitCode
return fmt.Errorf("failed to decode event: %v", err)
}
stopProcessing := false
switch e.Status {
case "die":
if v, ok := e.Actor.Attributes["exitCode"]; ok {
code, cerr := strconv.Atoi(v)
if cerr != nil {
logrus.Errorf("failed to convert exitcode '%q' to int: %v", v, cerr)
} else {
exitCode = code
}
}
if !waitRemove {
stopProcessing = true
}
case "detach":
exitCode = 0
stopProcessing = true
case "destroy":
stopProcessing = true
}
if stopProcessing {
statusChan <- exitCode
// stop the loop processing
return fmt.Errorf("done")
}
return nil
}
// Get events via Events API
f := filters.NewArgs()
f.Add("type", "container")
f.Add("container", containerID)
options := types.EventsOptions{
Filters: f,
}
resBody, err := dockerCli.Client().Events(ctx, options)
if err != nil {
return nil, fmt.Errorf("can't get events from daemon: %v", err)
}
go system.DecodeEvents(resBody, eventProcessor)
return statusChan, nil
}
// getExitCode performs an inspect on the container. It returns
// the running state and the exit code.
func getExitCode(dockerCli *client.DockerCli, ctx context.Context, containerID string) (bool, int, error) {
c, err := dockerCli.Client().ContainerInspect(ctx, containerID)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != clientapi.ErrConnectionFailed {
return false, -1, err
}
return false, -1, nil
}
return c.State.Running, c.State.ExitCode, nil
}