diff options
Diffstat (limited to 'pkg/adapter')
-rw-r--r-- | pkg/adapter/containers.go | 72 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 79 | ||||
-rw-r--r-- | pkg/adapter/pods.go | 51 | ||||
-rw-r--r-- | pkg/adapter/pods_remote.go | 44 | ||||
-rw-r--r-- | pkg/adapter/runtime.go | 28 | ||||
-rw-r--r-- | pkg/adapter/runtime_remote.go | 12 |
6 files changed, 249 insertions, 37 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 5279f11b2..8481a0cec 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -92,6 +92,9 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa if errors.Cause(err) == libpod.ErrCtrStopped { logrus.Debugf("Container %s is already stopped", c.ID()) return nil + } else if cli.All && errors.Cause(err) == libpod.ErrCtrStateInvalid { + logrus.Debugf("Container %s is not running, could not stop", c.ID()) + return nil } logrus.Debugf("Failed to stop container %s: %s", c.ID(), err.Error()) } @@ -694,3 +697,72 @@ func (r *LocalRuntime) UnpauseContainers(ctx context.Context, cli *cliconfig.Unp } return pool.Run() } + +// Restart containers without or without a timeout +func (r *LocalRuntime) Restart(ctx context.Context, c *cliconfig.RestartValues) ([]string, map[string]error, error) { + var ( + containers []*libpod.Container + restartContainers []*libpod.Container + err error + ) + useTimeout := c.Flag("timeout").Changed || c.Flag("time").Changed + inputTimeout := c.Timeout + + // Handle --latest + if c.Latest { + lastCtr, err := r.Runtime.GetLatestContainer() + if err != nil { + return nil, nil, errors.Wrapf(err, "unable to get latest container") + } + restartContainers = append(restartContainers, lastCtr) + } else if c.Running { + containers, err = r.GetRunningContainers() + if err != nil { + return nil, nil, err + } + restartContainers = append(restartContainers, containers...) + } else if c.All { + containers, err = r.Runtime.GetAllContainers() + if err != nil { + return nil, nil, err + } + restartContainers = append(restartContainers, containers...) + } else { + for _, id := range c.InputArgs { + ctr, err := r.Runtime.LookupContainer(id) + if err != nil { + return nil, nil, err + } + restartContainers = append(restartContainers, ctr) + } + } + + maxWorkers := shared.DefaultPoolSize("restart") + if c.GlobalIsSet("max-workers") { + maxWorkers = c.GlobalFlags.MaxWorks + } + + logrus.Debugf("Setting maximum workers to %d", maxWorkers) + + // We now have a slice of all the containers to be restarted. Iterate them to + // create restart Funcs with a timeout as needed + pool := shared.NewPool("restart", maxWorkers, len(restartContainers)) + for _, c := range restartContainers { + ctr := c + timeout := ctr.StopTimeout() + if useTimeout { + timeout = inputTimeout + } + pool.Add(shared.Job{ + ID: ctr.ID(), + Fn: func() error { + err := ctr.RestartWithTimeout(ctx, timeout) + if err != nil { + logrus.Debugf("Failed to restart container %s: %s", ctr.ID(), err.Error()) + } + return err + }, + }) + } + return pool.Run() +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index cb61871bf..e8f221eaf 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -45,6 +45,12 @@ func (c *Container) ID() string { return c.config.ID } +// Restart a single container +func (c *Container) Restart(timeout int64) error { + _, err := iopodman.RestartContainer().Call(c.Runtime.Conn, c.ID(), timeout) + return err +} + // Pause a container func (c *Container) Pause() error { _, err := iopodman.PauseContainer().Call(c.Runtime.Conn, c.ID()) @@ -132,6 +138,23 @@ func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { }, nil } +// GetAllContainers returns all containers in a slice +func (r *LocalRuntime) GetAllContainers() ([]*Container, error) { + var containers []*Container + ctrs, err := iopodman.GetContainersByContext().Call(r.Conn, true, false, []string{}) + if err != nil { + return nil, err + } + for _, ctr := range ctrs { + container, err := r.LookupContainer(ctr) + if err != nil { + return nil, err + } + containers = append(containers, container) + } + return containers, nil +} + func (r *LocalRuntime) LookupContainersWithStatus(filters []string) ([]*Container, error) { var containers []*Container ctrs, err := iopodman.GetContainersByStatus().Call(r.Conn, filters) @@ -753,3 +776,59 @@ func (r *LocalRuntime) UnpauseContainers(ctx context.Context, cli *cliconfig.Unp } return ok, failures, nil } + +// Restart restarts a container over varlink +func (r *LocalRuntime) Restart(ctx context.Context, c *cliconfig.RestartValues) ([]string, map[string]error, error) { + var ( + containers []*Container + restartContainers []*Container + err error + ok = []string{} + failures = map[string]error{} + ) + useTimeout := c.Flag("timeout").Changed || c.Flag("time").Changed + inputTimeout := c.Timeout + + if c.Latest { + lastCtr, err := r.GetLatestContainer() + if err != nil { + return nil, nil, errors.Wrapf(err, "unable to get latest container") + } + restartContainers = append(restartContainers, lastCtr) + } else if c.Running { + containers, err = r.LookupContainersWithStatus([]string{libpod.ContainerStateRunning.String()}) + if err != nil { + return nil, nil, err + } + restartContainers = append(restartContainers, containers...) + } else if c.All { + containers, err = r.GetAllContainers() + if err != nil { + return nil, nil, err + } + restartContainers = append(restartContainers, containers...) + } else { + for _, id := range c.InputArgs { + ctr, err := r.LookupContainer(id) + if err != nil { + return nil, nil, err + } + restartContainers = append(restartContainers, ctr) + } + } + + for _, c := range restartContainers { + c := c + timeout := c.config.StopTimeout + if useTimeout { + timeout = inputTimeout + } + err := c.Restart(int64(timeout)) + if err != nil { + failures[c.ID()] = err + } else { + ok = append(ok, c.ID()) + } + } + return ok, failures, nil +} diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go index 901c1857b..bb7d9cce6 100644 --- a/pkg/adapter/pods.go +++ b/pkg/adapter/pods.go @@ -4,20 +4,16 @@ package adapter import ( "context" - "github.com/pkg/errors" "strings" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/adapter/shortcuts" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) -// Pod ... -type Pod struct { - *libpod.Pod -} - // PodContainerStats is struct containing an adapter Pod and a libpod // ContainerStats and is used primarily for outputing pod stats. type PodContainerStats struct { @@ -25,6 +21,49 @@ type PodContainerStats struct { ContainerStats map[string]*libpod.ContainerStats } +// PrunePods removes pods +func (r *LocalRuntime) PrunePods(ctx context.Context, cli *cliconfig.PodPruneValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ) + + maxWorkers := shared.DefaultPoolSize("rm") + if cli.GlobalIsSet("max-workers") { + maxWorkers = cli.GlobalFlags.MaxWorks + } + logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) + + states := []string{shared.PodStateStopped, shared.PodStateExited} + if cli.Force { + states = append(states, shared.PodStateRunning) + } + + pods, err := r.GetPodsByStatus(states) + if err != nil { + return ok, failures, err + } + if len(pods) < 1 { + return ok, failures, nil + } + + pool := shared.NewPool("pod_prune", maxWorkers, len(pods)) + for _, p := range pods { + p := p + + pool.Add(shared.Job{p.ID(), + func() error { + err := r.Runtime.RemovePod(ctx, p, cli.Force, cli.Force) + if err != nil { + logrus.Debugf("Failed to remove pod %s: %s", p.ID(), err.Error()) + } + return err + }, + }) + } + return pool.Run() +} + // RemovePods ... func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) { var ( diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go index 00a5d9a32..7cf38aac0 100644 --- a/pkg/adapter/pods_remote.go +++ b/pkg/adapter/pods_remote.go @@ -14,13 +14,9 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/varlinkapi" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) -// Pod ... -type Pod struct { - remotepod -} - // PodContainerStats is struct containing an adapter Pod and a libpod // ContainerStats and is used primarily for outputing pod stats. type PodContainerStats struct { @@ -28,13 +24,6 @@ type PodContainerStats struct { ContainerStats map[string]*libpod.ContainerStats } -type remotepod struct { - config *libpod.PodConfig - state *libpod.PodInspectState - containers []libpod.PodContainerInfo - Runtime *LocalRuntime -} - // RemovePods removes one or more based on the cli context. func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) { var ( @@ -539,3 +528,34 @@ func (r *LocalRuntime) RemovePod(ctx context.Context, p *Pod, removeCtrs, force } return nil } + +// PrunePods... +func (r *LocalRuntime) PrunePods(ctx context.Context, cli *cliconfig.PodPruneValues) ([]string, map[string]error, error) { + var ( + ok = []string{} + failures = map[string]error{} + ) + states := []string{shared.PodStateStopped, shared.PodStateExited} + if cli.Force { + states = append(states, shared.PodStateRunning) + } + + ids, err := iopodman.GetPodsByStatus().Call(r.Conn, states) + if err != nil { + return ok, failures, err + } + if len(ids) < 1 { + return ok, failures, nil + } + + for _, id := range ids { + _, err := iopodman.RemovePod().Call(r.Conn, id, cli.Force) + if err != nil { + logrus.Debugf("Failed to remove pod %s: %s", id, err.Error()) + failures[id] = err + } else { + ok = append(ok, id) + } + } + return ok, failures, nil +} diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index 6ed9cee77..753f7c944 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -7,7 +7,6 @@ import ( "context" "io" "io/ioutil" - "k8s.io/api/core/v1" "os" "text/template" @@ -25,6 +24,7 @@ import ( "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage/pkg/archive" "github.com/pkg/errors" + "k8s.io/api/core/v1" ) // LocalRuntime describes a typical libpod runtime @@ -43,6 +43,11 @@ type Container struct { *libpod.Container } +// Pod encapsulates the libpod.Pod structure, helps with remote vs. local +type Pod struct { + *libpod.Pod +} + // Volume ... type Volume struct { *libpod.Volume @@ -371,8 +376,7 @@ func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, * } // GetPodsByStatus returns a slice of pods filtered by a libpod status -func (r *LocalRuntime) GetPodsByStatus(statuses []string) ([]*Pod, error) { - var adapterPods []*Pod +func (r *LocalRuntime) GetPodsByStatus(statuses []string) ([]*libpod.Pod, error) { filterFunc := func(p *libpod.Pod) bool { state, _ := shared.GetPodStatus(p) @@ -383,25 +387,11 @@ func (r *LocalRuntime) GetPodsByStatus(statuses []string) ([]*Pod, error) { } return false } + pods, err := r.Runtime.Pods(filterFunc) if err != nil { return nil, err } - for _, p := range pods { - adapterPod := Pod{ - p, - } - adapterPods = append(adapterPods, &adapterPod) - } - return adapterPods, nil -} -// RemovePod removes a pod -// If removeCtrs is specified, containers will be removed -// Otherwise, a pod that is not empty will return an error and not be removed -// If force is specified with removeCtrs, all containers will be stopped before -// being removed -// Otherwise, the pod will not be removed if any containers are running -func (r *LocalRuntime) RemovePod(ctx context.Context, p *Pod, removeCtrs, force bool) error { - return r.Runtime.RemovePod(ctx, p.Pod, removeCtrs, force) + return pods, nil } diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 71f7380db..dcb0924ce 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -99,6 +99,18 @@ type remoteContainer struct { state *libpod.ContainerState } +// Pod ... +type Pod struct { + remotepod +} + +type remotepod struct { + config *libpod.PodConfig + state *libpod.PodInspectState + containers []libpod.PodContainerInfo + Runtime *LocalRuntime +} + type VolumeFilter func(*Volume) bool // Volume is embed for libpod volumes |