diff options
Diffstat (limited to 'pkg/domain/infra/abi/pods.go')
-rw-r--r-- | pkg/domain/infra/abi/pods.go | 229 |
1 files changed, 167 insertions, 62 deletions
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go index 32deb20e0..9a16f7fcd 100644 --- a/pkg/domain/infra/abi/pods.go +++ b/pkg/domain/infra/abi/pods.go @@ -2,14 +2,18 @@ package abi import ( "context" + "errors" + "fmt" + "strconv" + "strings" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" dfilters "github.com/containers/podman/v4/pkg/domain/filters" "github.com/containers/podman/v4/pkg/signal" + "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgen/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -46,7 +50,7 @@ func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) { _, err := ic.Libpod.LookupPod(nameOrID) - if err != nil && errors.Cause(err) != define.ErrNoSuchPod { + if err != nil && !errors.Is(err, define.ErrNoSuchPod) { return nil, err } return &entities.BoolReport{Value: err == nil}, nil @@ -66,14 +70,14 @@ func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, opt for _, p := range pods { report := entities.PodKillReport{Id: p.ID()} conErrs, err := p.Kill(ctx, uint(sig)) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} reports = append(reports, &report) continue } if len(conErrs) > 0 { for id, err := range conErrs { - report.Errs = append(report.Errs, errors.Wrapf(err, "error killing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error killing container %s: %w", id, err)) } reports = append(reports, &report) continue @@ -107,7 +111,7 @@ func (ic *ContainerEngine) PodLogs(ctx context.Context, nameOrID string, options } } if !ctrFound { - return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not in pod %s", options.ContainerName, nameOrID) + return fmt.Errorf("container %s is not in pod %s: %w", options.ContainerName, nameOrID, define.ErrNoSuchCtr) } } else { // No container name specified select all containers @@ -132,13 +136,13 @@ func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, op for _, p := range pods { report := entities.PodPauseReport{Id: p.ID()} errs, err := p.Pause(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error pausing container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -155,15 +159,23 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, return nil, err } for _, p := range pods { + status, err := p.GetPodStatus() + if err != nil { + return nil, err + } + // If the pod is not paused or degraded, there is no need to attempt an unpause on it + if status != define.PodStatePaused && status != define.PodStateDegraded { + continue + } report := entities.PodUnpauseReport{Id: p.ID()} errs, err := p.Unpause(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error unpausing container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -176,19 +188,19 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) { reports := []*entities.PodStopReport{} pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) - if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchPod)) { return nil, err } for _, p := range pods { report := entities.PodStopReport{Id: p.ID()} errs, err := p.StopWithTimeout(ctx, false, options.Timeout) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error stopping container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error stopping container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -207,14 +219,14 @@ func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, for _, p := range pods { report := entities.PodRestartReport{Id: p.ID()} errs, err := p.Restart(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} reports = append(reports, &report) continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error restarting container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error restarting container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -234,14 +246,14 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op for _, p := range pods { report := entities.PodStartReport{Id: p.ID()} errs, err := p.Start(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} reports = append(reports, &report) continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error starting container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error starting container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -253,7 +265,7 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) { pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) - if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchPod)) { return nil, err } reports := make([]*entities.PodRmReport, 0, len(pods)) @@ -295,6 +307,88 @@ func (ic *ContainerEngine) PodCreate(ctx context.Context, specg entities.PodSpec return &entities.PodCreateReport{Id: pod.ID()}, nil } +func (ic *ContainerEngine) PodClone(ctx context.Context, podClone entities.PodCloneOptions) (*entities.PodCloneReport, error) { + spec := specgen.NewPodSpecGenerator() + p, err := generate.PodConfigToSpec(ic.Libpod, spec, &podClone.InfraOptions, podClone.ID) + if err != nil { + return nil, err + } + + if len(podClone.CreateOpts.Name) > 0 { + spec.Name = podClone.CreateOpts.Name + } else { + n := p.Name() + _, err := ic.Libpod.LookupPod(n + "-clone") + if err == nil { + n += "-clone" + } + switch { + case strings.Contains(n, "-clone"): // meaning this name is taken! + ind := strings.Index(n, "-clone") + 6 + num, err := strconv.Atoi(n[ind:]) + if num == 0 && err != nil { // meaning invalid + _, err = ic.Libpod.LookupPod(n + "1") + if err != nil { + spec.Name = n + "1" + break + } + } else { // else we already have a number + n = n[0:ind] + } + err = nil + count := num + for err == nil { // until we cannot find a pod w/ this name, increment num and try again + count++ + tempN := n + strconv.Itoa(count) + _, err = ic.Libpod.LookupPod(tempN) + } + n += strconv.Itoa(count) + spec.Name = n + default: + spec.Name = p.Name() + "-clone" + } + } + + podSpec := entities.PodSpec{PodSpecGen: *spec} + pod, err := generate.MakePod(&podSpec, ic.Libpod) + if err != nil { + return nil, err + } + + ctrs, err := p.AllContainers() + if err != nil { + return nil, err + } + for _, ctr := range ctrs { + if ctr.IsInfra() { + continue // already copied infra + } + + podClone.PerContainerOptions.Pod = pod.ID() + _, err := ic.ContainerClone(ctx, entities.ContainerCloneOptions{ID: ctr.ID(), CreateOpts: podClone.PerContainerOptions}) + if err != nil { + return nil, err + } + } + + if podClone.Destroy { + var timeout *uint + err = ic.Libpod.RemovePod(ctx, p, true, true, timeout) + if err != nil { + return &entities.PodCloneReport{Id: pod.ID()}, err + } + } + + if podClone.Start { + _, err := ic.PodStart(ctx, []string{pod.ID()}, entities.PodStartOptions{}) + if err != nil { + return &entities.PodCloneReport{Id: pod.ID()}, err + } + } + + return &entities.PodCloneReport{Id: pod.ID()}, nil +} + func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOptions) (*entities.StringSliceReport, error) { var ( pod *libpod.Pod @@ -308,7 +402,7 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp pod, err = ic.Libpod.LookupPod(options.NameOrID) } if err != nil { - return nil, errors.Wrap(err, "unable to lookup requested container") + return nil, fmt.Errorf("unable to look up requested container: %w", err) } // Run Top. @@ -317,6 +411,56 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp return report, err } +func (ic *ContainerEngine) listPodReportFromPod(p *libpod.Pod) (*entities.ListPodsReport, error) { + status, err := p.GetPodStatus() + if err != nil { + return nil, err + } + cons, err := p.AllContainers() + if err != nil { + return nil, err + } + lpcs := make([]*entities.ListPodContainer, len(cons)) + for i, c := range cons { + state, err := c.State() + if err != nil { + return nil, err + } + lpcs[i] = &entities.ListPodContainer{ + Id: c.ID(), + Names: c.Name(), + Status: state.String(), + } + } + infraID, err := p.InfraContainerID() + if err != nil { + return nil, err + } + networks := []string{} + if len(infraID) > 0 { + infra, err := p.InfraContainer() + if err != nil { + return nil, err + } + networks, err = infra.Networks() + if err != nil { + return nil, err + } + } + return &entities.ListPodsReport{ + Cgroup: p.CgroupParent(), + Containers: lpcs, + Created: p.CreatedTime(), + Id: p.ID(), + InfraId: infraID, + Name: p.Name(), + Namespace: p.Namespace(), + Networks: networks, + Status: status, + Labels: p.Labels(), + }, nil +} + func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) { var ( err error @@ -346,53 +490,14 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti reports := make([]*entities.ListPodsReport, 0, len(pds)) for _, p := range pds { - var lpcs []*entities.ListPodContainer - status, err := p.GetPodStatus() + r, err := ic.listPodReportFromPod(p) if err != nil { - return nil, err - } - cons, err := p.AllContainers() - if err != nil { - return nil, err - } - for _, c := range cons { - state, err := c.State() - if err != nil { - return nil, err + if errors.Is(err, define.ErrNoSuchPod) || errors.Is(err, define.ErrNoSuchCtr) { + continue } - lpcs = append(lpcs, &entities.ListPodContainer{ - Id: c.ID(), - Names: c.Name(), - Status: state.String(), - }) - } - infraID, err := p.InfraContainerID() - if err != nil { return nil, err } - networks := []string{} - if len(infraID) > 0 { - infra, err := p.InfraContainer() - if err != nil { - return nil, err - } - networks, err = infra.Networks() - if err != nil { - return nil, err - } - } - reports = append(reports, &entities.ListPodsReport{ - Cgroup: p.CgroupParent(), - Containers: lpcs, - Created: p.CreatedTime(), - Id: p.ID(), - InfraId: infraID, - Name: p.Name(), - Namespace: p.Namespace(), - Networks: networks, - Status: status, - Labels: p.Labels(), - }) + reports = append(reports, r) } return reports, nil } @@ -409,7 +514,7 @@ func (ic *ContainerEngine) PodInspect(ctx context.Context, options entities.PodI pod, err = ic.Libpod.LookupPod(options.NameOrID) } if err != nil { - return nil, errors.Wrap(err, "unable to lookup requested container") + return nil, fmt.Errorf("unable to look up requested container: %w", err) } inspect, err := pod.Inspect() if err != nil { |