diff options
Diffstat (limited to 'pkg/domain/infra/abi/containers.go')
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 280 |
1 files changed, 155 insertions, 125 deletions
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 783224e9c..535c4a613 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -4,10 +4,8 @@ import ( "context" "errors" "fmt" - "io/ioutil" "os" "strconv" - "strings" "sync" "time" @@ -40,6 +38,7 @@ import ( // is specified. It also returns a list of the corresponding input name used to lookup each container. func getContainersAndInputByContext(all, latest bool, names []string, filters map[string][]string, runtime *libpod.Runtime) (ctrs []*libpod.Container, rawInput []string, err error) { var ctr *libpod.Container + var filteredCtrs []*libpod.Container ctrs = []*libpod.Container{} filterFuncs := make([]libpod.ContainerFilter, 0, len(filters)) @@ -58,7 +57,17 @@ func getContainersAndInputByContext(all, latest bool, names []string, filters ma } rawInput = []string{} for _, candidate := range ctrs { - rawInput = append(rawInput, candidate.ID()) + if len(names) > 0 { + for _, name := range names { + if candidate.ID() == name || candidate.Name() == name { + rawInput = append(rawInput, candidate.ID()) + filteredCtrs = append(filteredCtrs, candidate) + } + } + ctrs = filteredCtrs + } else { + rawInput = append(rawInput, candidate.ID()) + } } case all: ctrs, err = runtime.GetAllContainers() @@ -142,10 +151,10 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri if err != nil { return nil, err } - ctrMap := map[string]string{} + idToRawInput := map[string]string{} if len(rawInputs) == len(ctrs) { for i := range ctrs { - ctrMap[ctrs[i].ID()] = rawInputs[i] + idToRawInput[ctrs[i].ID()] = rawInputs[i] } } reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) @@ -158,7 +167,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri reports = append(reports, &entities.PauseUnpauseReport{ Id: c.ID(), Err: err, - RawInput: ctrMap[c.ID()], + RawInput: idToRawInput[c.ID()], }) } return reports, nil @@ -169,10 +178,10 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st if err != nil { return nil, err } - ctrMap := map[string]string{} + idToRawInput := map[string]string{} if len(rawInputs) == len(ctrs) { for i := range ctrs { - ctrMap[ctrs[i].ID()] = rawInputs[i] + idToRawInput[ctrs[i].ID()] = rawInputs[i] } } reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) @@ -185,7 +194,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st reports = append(reports, &entities.PauseUnpauseReport{ Id: c.ID(), Err: err, - RawInput: ctrMap[c.ID()], + RawInput: idToRawInput[c.ID()], }) } return reports, nil @@ -196,10 +205,10 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) { return nil, err } - ctrMap := map[string]string{} + idToRawInput := map[string]string{} if len(rawInputs) == len(ctrs) { for i := range ctrs { - ctrMap[ctrs[i].ID()] = rawInputs[i] + idToRawInput[ctrs[i].ID()] = rawInputs[i] } } errMap, err := parallelctr.ContainerOp(ctx, ctrs, func(c *libpod.Container) error { @@ -245,7 +254,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin if options.All { report.RawInput = ctr.ID() } else { - report.RawInput = ctrMap[ctr.ID()] + report.RawInput = idToRawInput[ctr.ID()] } report.Err = err reports = append(reports, report) @@ -275,10 +284,10 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin if err != nil { return nil, err } - ctrMap := map[string]string{} + idToRawInput := map[string]string{} if len(rawInputs) == len(ctrs) { for i := range ctrs { - ctrMap[ctrs[i].ID()] = rawInputs[i] + idToRawInput[ctrs[i].ID()] = rawInputs[i] } } reports := make([]*entities.KillReport, 0, len(ctrs)) @@ -291,7 +300,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin reports = append(reports, &entities.KillReport{ Id: con.ID(), Err: err, - RawInput: ctrMap[con.ID()], + RawInput: idToRawInput[con.ID()], }) } return reports, nil @@ -299,31 +308,42 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) { var ( - ctrs []*libpod.Container - err error + ctrs []*libpod.Container + err error + rawInputs = []string{} ) if options.Running { ctrs, err = ic.Libpod.GetRunningContainers() + for _, candidate := range ctrs { + rawInputs = append(rawInputs, candidate.ID()) + } + if err != nil { return nil, err } } else { - ctrs, err = getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + ctrs, rawInputs, err = getContainersAndInputByContext(options.All, options.Latest, namesOrIds, options.Filters, ic.Libpod) if err != nil { return nil, err } } - + idToRawInput := map[string]string{} + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } reports := make([]*entities.RestartReport, 0, len(ctrs)) - for _, con := range ctrs { - timeout := con.StopTimeout() + for _, c := range ctrs { + timeout := c.StopTimeout() if options.Timeout != nil { timeout = *options.Timeout } reports = append(reports, &entities.RestartReport{ - Id: con.ID(), - Err: con.RestartWithTimeout(ctx, timeout), + Id: c.ID(), + Err: c.RestartWithTimeout(ctx, timeout), + RawInput: idToRawInput[c.ID()], }) } return reports, nil @@ -381,7 +401,16 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, } names = tmpNames - ctrs, err := getContainersByContext(options.All, options.Latest, names, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, names, options.Filters, ic.Libpod) + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) { + return nil, err + } + idToRawInput := map[string]string{} + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) { // Failed to get containers. If force is specified, get the containers ID // and evict them @@ -391,7 +420,10 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, for _, ctr := range names { logrus.Debugf("Evicting container %q", ctr) - report := reports.RmReport{Id: ctr} + report := reports.RmReport{ + Id: ctr, + RawInput: idToRawInput[ctr], + } _, err := ic.Libpod.EvictContainer(ctx, ctr, options.Volumes) if err != nil { if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) { @@ -461,6 +493,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, report := new(reports.RmReport) report.Id = ctr.ID() report.Err = err + report.RawInput = idToRawInput[ctr.ID()] rmReports = append(rmReports, report) } return rmReports, nil @@ -598,8 +631,9 @@ func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrID string, func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, options entities.CheckpointOptions) ([]*entities.CheckpointReport, error) { var ( - err error - cons []*libpod.Container + ctrs []*libpod.Container + rawInputs []string + err error ) checkOpts := libpod.ContainerCheckpointOptions{ Keep: options.Keep, @@ -616,24 +650,34 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ CreateImage: options.CreateImage, } + idToRawInput := map[string]string{} if options.All { running := func(c *libpod.Container) bool { state, _ := c.State() return state == define.ContainerStateRunning } - cons, err = ic.Libpod.GetContainers(running) + ctrs, err = ic.Libpod.GetContainers(running) + if err != nil { + return nil, err + } } else { - cons, err = getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod) - } - if err != nil { - return nil, err + ctrs, rawInputs, err = getContainersAndInputByContext(false, options.Latest, namesOrIds, nil, ic.Libpod) + if err != nil { + return nil, err + } + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } } - reports := make([]*entities.CheckpointReport, 0, len(cons)) - for _, con := range cons { - criuStatistics, runtimeCheckpointDuration, err := con.Checkpoint(ctx, checkOpts) + reports := make([]*entities.CheckpointReport, 0, len(ctrs)) + for _, c := range ctrs { + criuStatistics, runtimeCheckpointDuration, err := c.Checkpoint(ctx, checkOpts) reports = append(reports, &entities.CheckpointReport{ Err: err, - Id: con.ID(), + Id: c.ID(), + RawInput: idToRawInput[c.ID()], RuntimeDuration: runtimeCheckpointDuration, CRIUStatistics: criuStatistics, }) @@ -643,7 +687,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []string, options entities.RestoreOptions) ([]*entities.RestoreReport, error) { var ( - containers []*libpod.Container + ctrs []*libpod.Container checkpointImageImportErrors []error err error ) @@ -670,19 +714,21 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st }, } + idToRawInput := map[string]string{} switch { case options.Import != "": - containers, err = checkpoint.CRImportCheckpointTar(ctx, ic.Libpod, options) + ctrs, err = checkpoint.CRImportCheckpointTar(ctx, ic.Libpod, options) case options.All: - containers, err = ic.Libpod.GetContainers(filterFuncs...) + ctrs, err = ic.Libpod.GetContainers(filterFuncs...) case options.Latest: - containers, err = getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod) + ctrs, err = getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod) default: for _, nameOrID := range namesOrIds { logrus.Debugf("look up container: %q", nameOrID) - ctr, err := ic.Libpod.LookupContainer(nameOrID) + c, err := ic.Libpod.LookupContainer(nameOrID) if err == nil { - containers = append(containers, ctr) + ctrs = append(ctrs, c) + idToRawInput[c.ID()] = nameOrID } else { // If container was not found, check if this is a checkpoint image logrus.Debugf("look up image: %q", nameOrID) @@ -700,7 +746,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st if err != nil { return nil, err } - importedContainers, err := checkpoint.CRImportCheckpoint(ctx, ic.Libpod, options, mountPoint) + importedCtrs, err := checkpoint.CRImportCheckpoint(ctx, ic.Libpod, options, mountPoint) if err != nil { // CRImportCheckpoint is expected to import exactly one container from checkpoint image checkpointImageImportErrors = append( @@ -708,7 +754,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st fmt.Errorf("unable to import checkpoint from image: %q: %v", nameOrID, err), ) } else { - containers = append(containers, importedContainers[0]) + ctrs = append(ctrs, importedCtrs[0]) } } } @@ -717,12 +763,13 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st return nil, err } - reports := make([]*entities.RestoreReport, 0, len(containers)) - for _, con := range containers { - criuStatistics, runtimeRestoreDuration, err := con.Restore(ctx, restoreOptions) + reports := make([]*entities.RestoreReport, 0, len(ctrs)) + for _, c := range ctrs { + criuStatistics, runtimeRestoreDuration, err := c.Restore(ctx, restoreOptions) reports = append(reports, &entities.RestoreReport{ Err: err, - Id: con.ID(), + Id: c.ID(), + RawInput: idToRawInput[c.ID()], RuntimeDuration: runtimeRestoreDuration, CRIUStatistics: criuStatistics, }) @@ -774,7 +821,7 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, // If the container is in a pod, also set to recursively start dependencies err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, false) if err != nil && !errors.Is(err, define.ErrDetach) { - return fmt.Errorf("error attaching to container %s: %w", ctr.ID(), err) + return fmt.Errorf("attaching to container %s: %w", ctr.ID(), err) } os.Stdout.WriteString("\n") return nil @@ -796,12 +843,12 @@ func makeExecConfig(options entities.ExecOptions, rt *libpod.Runtime) (*libpod.E storageConfig := rt.StorageConfig() runtimeConfig, err := rt.GetConfig() if err != nil { - return nil, fmt.Errorf("error retrieving Libpod configuration to build exec exit command: %w", err) + return nil, fmt.Errorf("retrieving Libpod configuration to build exec exit command: %w", err) } // TODO: Add some ability to toggle syslog exitCommandArgs, err := specgenutil.CreateExitCommandArgs(storageConfig, runtimeConfig, logrus.IsLevelEnabled(logrus.DebugLevel), false, true) if err != nil { - return nil, fmt.Errorf("error constructing exit command for exec session: %w", err) + return nil, fmt.Errorf("constructing exit command for exec session: %w", err) } execConfig.ExitCommand = exitCommandArgs @@ -810,7 +857,7 @@ func makeExecConfig(options entities.ExecOptions, rt *libpod.Runtime) (*libpod.E func checkExecPreserveFDs(options entities.ExecOptions) error { if options.PreserveFDs > 0 { - entries, err := ioutil.ReadDir("/proc/self/fd") + entries, err := os.ReadDir("/proc/self/fd") if err != nil { return err } @@ -886,48 +933,19 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric - containersNamesOrIds := namesOrIds - all := options.All - if len(options.Filters) > 0 { - all = false - filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters)) - if len(options.Filters) > 0 { - for k, v := range options.Filters { - generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod) - if err != nil { - return nil, err - } - filterFuncs = append(filterFuncs, generatedFunc) - } - } - candidates, err := ic.Libpod.GetContainers(filterFuncs...) - if err != nil { - return nil, err - } - containersNamesOrIds = []string{} - for _, candidate := range candidates { - if options.All { - containersNamesOrIds = append(containersNamesOrIds, candidate.ID()) - continue - } - for _, nameOrID := range namesOrIds { - if nameOrID == candidate.ID() || nameOrID == candidate.Name() { - containersNamesOrIds = append(containersNamesOrIds, nameOrID) - } - } - } - } - ctrs, rawInputs, err := getContainersAndInputByContext(all, options.Latest, containersNamesOrIds, options.Filters, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, options.Filters, ic.Libpod) if err != nil { return nil, err } + idToRawInput := map[string]string{} + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } // There can only be one container if attach was used for i := range ctrs { ctr := ctrs[i] - rawInput := ctr.ID() - if !options.All { - rawInput = rawInputs[i] - } ctrState, err := ctr.State() if err != nil { return nil, err @@ -941,7 +959,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri // Exit cleanly immediately reports = append(reports, &entities.ContainerStartReport{ Id: ctr.ID(), - RawInput: rawInput, + RawInput: idToRawInput[ctr.ID()], Err: nil, ExitCode: 0, }) @@ -952,7 +970,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri logrus.Debugf("Deadlock error: %v", err) reports = append(reports, &entities.ContainerStartReport{ Id: ctr.ID(), - RawInput: rawInput, + RawInput: idToRawInput[ctr.ID()], Err: err, ExitCode: define.ExitCode(err), }) @@ -962,7 +980,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri if ctrRunning { reports = append(reports, &entities.ContainerStartReport{ Id: ctr.ID(), - RawInput: rawInput, + RawInput: idToRawInput[ctr.ID()], Err: nil, ExitCode: 0, }) @@ -972,7 +990,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri if err != nil { reports = append(reports, &entities.ContainerStartReport{ Id: ctr.ID(), - RawInput: rawInput, + RawInput: idToRawInput[ctr.ID()], Err: err, ExitCode: exitCode, }) @@ -987,7 +1005,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri exitCode = ic.GetContainerExitCode(ctx, ctr) reports = append(reports, &entities.ContainerStartReport{ Id: ctr.ID(), - RawInput: rawInput, + RawInput: idToRawInput[ctr.ID()], Err: err, ExitCode: exitCode, }) @@ -1000,7 +1018,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri // If the container is in a pod, also set to recursively start dependencies report := &entities.ContainerStartReport{ Id: ctr.ID(), - RawInput: rawInput, + RawInput: idToRawInput[ctr.ID()], ExitCode: 125, } if err := ctr.Start(ctx, true); err != nil { @@ -1211,14 +1229,20 @@ func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []strin } func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) { - reports := []*entities.ContainerCleanupReport{} - ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, nil, ic.Libpod) if err != nil { return nil, err } + idToRawInput := map[string]string{} + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } + reports := []*entities.ContainerCleanupReport{} for _, ctr := range ctrs { var err error - report := entities.ContainerCleanupReport{Id: ctr.ID()} + report := entities.ContainerCleanupReport{Id: ctr.ID(), RawInput: idToRawInput[ctr.ID()]} if options.Exec != "" { if options.Remove { @@ -1259,13 +1283,19 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st } func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) { - ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, nil, ic.Libpod) if err != nil { return nil, err } + idToRawInput := map[string]string{} + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } reports := make([]*entities.ContainerInitReport, 0, len(ctrs)) for _, ctr := range ctrs { - report := entities.ContainerInitReport{Id: ctr.ID()} + report := entities.ContainerInitReport{Id: ctr.ID(), RawInput: idToRawInput[ctr.ID()]} err := ctr.Init(ctx, ctr.PodID() != "") // If we're initializing all containers, ignore invalid state errors @@ -1418,7 +1448,7 @@ func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIDs []str logrus.Debugf("Error umounting container %s, storage.ErrLayerNotMounted", ctr.ID()) continue } - report.Err = fmt.Errorf("error unmounting container %s: %w", ctr.ID(), err) + report.Err = fmt.Errorf("unmounting container %s: %w", ctr.ID(), err) } reports = append(reports, &report) } @@ -1656,31 +1686,7 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti if err == nil { n += "-clone" } - switch { - case strings.Contains(n, "-clone"): - ind := strings.Index(n, "-clone") + 6 - num, err := strconv.Atoi(n[ind:]) - if num == 0 && err != nil { // clone1 is hard to get with this logic, just check for it here. - _, err = ic.Libpod.LookupContainer(n + "1") - if err != nil { - spec.Name = n + "1" - break - } - } else { - n = n[0:ind] - } - err = nil - count := num - for err == nil { - count++ - tempN := n + strconv.Itoa(count) - _, err = ic.Libpod.LookupContainer(tempN) - } - n += strconv.Itoa(count) - spec.Name = n - default: - spec.Name = c.Name() + "-clone" - } + spec.Name = generate.CheckName(ic.Libpod, n, true) } rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, spec, true, c) @@ -1708,3 +1714,27 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti return &entities.ContainerCreateReport{Id: ctr.ID()}, nil } + +// ContainerUpdate finds and updates the given container's cgroup config with the specified options +func (ic *ContainerEngine) ContainerUpdate(ctx context.Context, updateOptions *entities.ContainerUpdateOptions) (string, error) { + err := specgen.WeightDevices(updateOptions.Specgen) + if err != nil { + return "", err + } + err = specgen.FinishThrottleDevices(updateOptions.Specgen) + if err != nil { + return "", err + } + ctrs, err := getContainersByContext(false, false, []string{updateOptions.NameOrID}, ic.Libpod) + if err != nil { + return "", err + } + if len(ctrs) != 1 { + return "", fmt.Errorf("container not found") + } + + if err = ctrs[0].Update(updateOptions.Specgen.ResourceLimits); err != nil { + return "", err + } + return ctrs[0].ID(), nil +} |