mirror of https://github.com/containers/podman.git
Add rm --filter option
--filter : remove the filtered container. Signed-off-by: Toshiki Sonoda <sonoda.toshiki@fujitsu.com>
This commit is contained in:
parent
fed326d8a6
commit
53ec479685
|
@ -49,7 +49,8 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
killOptions = entities.KillOptions{}
|
killOptions = entities.KillOptions{}
|
||||||
|
killCidFiles = []string{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func killFlags(cmd *cobra.Command) {
|
func killFlags(cmd *cobra.Command) {
|
||||||
|
@ -61,7 +62,7 @@ func killFlags(cmd *cobra.Command) {
|
||||||
flags.StringVarP(&killOptions.Signal, signalFlagName, "s", "KILL", "Signal to send to the container")
|
flags.StringVarP(&killOptions.Signal, signalFlagName, "s", "KILL", "Signal to send to the container")
|
||||||
_ = cmd.RegisterFlagCompletionFunc(signalFlagName, common.AutocompleteStopSignal)
|
_ = cmd.RegisterFlagCompletionFunc(signalFlagName, common.AutocompleteStopSignal)
|
||||||
cidfileFlagName := "cidfile"
|
cidfileFlagName := "cidfile"
|
||||||
flags.StringArrayVar(&cidFiles, cidfileFlagName, []string{}, "Read the container ID from the file")
|
flags.StringArrayVar(&killCidFiles, cidfileFlagName, nil, "Read the container ID from the file")
|
||||||
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
|
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ func kill(_ *cobra.Command, args []string) error {
|
||||||
if sig < 1 || sig > 64 {
|
if sig < 1 || sig > 64 {
|
||||||
return errors.New("valid signals are 1 through 64")
|
return errors.New("valid signals are 1 through 64")
|
||||||
}
|
}
|
||||||
for _, cidFile := range cidFiles {
|
for _, cidFile := range killCidFiles {
|
||||||
content, err := ioutil.ReadFile(cidFile)
|
content, err := ioutil.ReadFile(cidFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading CIDFile: %w", err)
|
return fmt.Errorf("error reading CIDFile: %w", err)
|
||||||
|
|
|
@ -52,8 +52,10 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rmOptions = entities.RmOptions{}
|
rmOptions = entities.RmOptions{
|
||||||
cidFiles = []string{}
|
Filters: make(map[string][]string),
|
||||||
|
}
|
||||||
|
rmCidFiles = []string{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func rmFlags(cmd *cobra.Command) {
|
func rmFlags(cmd *cobra.Command) {
|
||||||
|
@ -69,9 +71,13 @@ func rmFlags(cmd *cobra.Command) {
|
||||||
flags.BoolVarP(&rmOptions.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container")
|
flags.BoolVarP(&rmOptions.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container")
|
||||||
|
|
||||||
cidfileFlagName := "cidfile"
|
cidfileFlagName := "cidfile"
|
||||||
flags.StringArrayVar(&cidFiles, cidfileFlagName, nil, "Read the container ID from the file")
|
flags.StringArrayVar(&rmCidFiles, cidfileFlagName, nil, "Read the container ID from the file")
|
||||||
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
|
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
|
||||||
|
|
||||||
|
filterFlagName := "filter"
|
||||||
|
flags.StringSliceVar(&filters, filterFlagName, []string{}, "Filter output based on conditions given")
|
||||||
|
_ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePsFilters)
|
||||||
|
|
||||||
if !registry.IsRemote() {
|
if !registry.IsRemote() {
|
||||||
// This option is deprecated, but needs to still exists for backwards compatibility
|
// This option is deprecated, but needs to still exists for backwards compatibility
|
||||||
flags.Bool("storage", false, "Remove container from storage library")
|
flags.Bool("storage", false, "Remove container from storage library")
|
||||||
|
@ -101,7 +107,7 @@ func rm(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
rmOptions.Timeout = &stopTimeout
|
rmOptions.Timeout = &stopTimeout
|
||||||
}
|
}
|
||||||
for _, cidFile := range cidFiles {
|
for _, cidFile := range rmCidFiles {
|
||||||
content, err := ioutil.ReadFile(cidFile)
|
content, err := ioutil.ReadFile(cidFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading CIDFile: %w", err)
|
return fmt.Errorf("error reading CIDFile: %w", err)
|
||||||
|
@ -110,6 +116,14 @@ func rm(cmd *cobra.Command, args []string) error {
|
||||||
args = append(args, id)
|
args = append(args, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, f := range filters {
|
||||||
|
split := strings.SplitN(f, "=", 2)
|
||||||
|
if len(split) < 2 {
|
||||||
|
return fmt.Errorf("invalid filter %q", f)
|
||||||
|
}
|
||||||
|
rmOptions.Filters[split[0]] = append(rmOptions.Filters[split[0]], split[1])
|
||||||
|
}
|
||||||
|
|
||||||
if rmOptions.All {
|
if rmOptions.All {
|
||||||
logrus.Debug("--all is set: enforcing --depend=true")
|
logrus.Debug("--all is set: enforcing --depend=true")
|
||||||
rmOptions.Depend = true
|
rmOptions.Depend = true
|
||||||
|
@ -147,7 +161,7 @@ func removeContainers(namesOrIDs []string, rmOptions entities.RmOptions, setExit
|
||||||
}
|
}
|
||||||
errs = append(errs, r.Err)
|
errs = append(errs, r.Err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(r.Id)
|
fmt.Println(r.RawInput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errs.PrintErrors()
|
return errs.PrintErrors()
|
||||||
|
|
|
@ -52,7 +52,8 @@ var (
|
||||||
stopOptions = entities.StopOptions{
|
stopOptions = entities.StopOptions{
|
||||||
Filters: make(map[string][]string),
|
Filters: make(map[string][]string),
|
||||||
}
|
}
|
||||||
stopTimeout uint
|
stopCidFiles = []string{}
|
||||||
|
stopTimeout uint
|
||||||
)
|
)
|
||||||
|
|
||||||
func stopFlags(cmd *cobra.Command) {
|
func stopFlags(cmd *cobra.Command) {
|
||||||
|
@ -62,7 +63,7 @@ func stopFlags(cmd *cobra.Command) {
|
||||||
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing")
|
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing")
|
||||||
|
|
||||||
cidfileFlagName := "cidfile"
|
cidfileFlagName := "cidfile"
|
||||||
flags.StringArrayVar(&cidFiles, cidfileFlagName, nil, "Read the container ID from the file")
|
flags.StringArrayVar(&stopCidFiles, cidfileFlagName, nil, "Read the container ID from the file")
|
||||||
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
|
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
|
||||||
|
|
||||||
timeFlagName := "time"
|
timeFlagName := "time"
|
||||||
|
@ -103,7 +104,7 @@ func stop(cmd *cobra.Command, args []string) error {
|
||||||
if cmd.Flag("time").Changed {
|
if cmd.Flag("time").Changed {
|
||||||
stopOptions.Timeout = &stopTimeout
|
stopOptions.Timeout = &stopTimeout
|
||||||
}
|
}
|
||||||
for _, cidFile := range cidFiles {
|
for _, cidFile := range stopCidFiles {
|
||||||
content, err := ioutil.ReadFile(cidFile)
|
content, err := ioutil.ReadFile(cidFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading CIDFile: %w", err)
|
return fmt.Errorf("error reading CIDFile: %w", err)
|
||||||
|
|
|
@ -26,6 +26,30 @@ Read container ID from the specified file and remove the container. Can be spec
|
||||||
|
|
||||||
Remove selected container and recursively remove all containers that depend on it.
|
Remove selected container and recursively remove all containers that depend on it.
|
||||||
|
|
||||||
|
#### **--filter**=*filter*
|
||||||
|
|
||||||
|
Filter what containers remove.
|
||||||
|
Multiple filters can be given with multiple uses of the --filter flag.
|
||||||
|
Filters with the same key work inclusive with the only exception being
|
||||||
|
`label` which is exclusive. Filters with different keys always work exclusive.
|
||||||
|
|
||||||
|
Valid filters are listed below:
|
||||||
|
|
||||||
|
| **Filter** | **Description** |
|
||||||
|
| --------------- | -------------------------------------------------------------------------------- |
|
||||||
|
| id | [ID] Container's ID (accepts regex) |
|
||||||
|
| name | [Name] Container's name (accepts regex) |
|
||||||
|
| label | [Key] or [Key=Value] Label assigned to a container |
|
||||||
|
| exited | [Int] Container's exit code |
|
||||||
|
| status | [Status] Container's status: 'created', 'exited', 'paused', 'running', 'unknown' |
|
||||||
|
| ancestor | [ImageName] Image or descendant used to create container |
|
||||||
|
| before | [ID] or [Name] Containers created before this container |
|
||||||
|
| since | [ID] or [Name] Containers created since this container |
|
||||||
|
| volume | [VolumeName] or [MountpointDestination] Volume mounted in container |
|
||||||
|
| health | [Status] healthy or unhealthy |
|
||||||
|
| pod | [Pod] name or full or partial ID of pod |
|
||||||
|
| network | [Network] name or full ID of network |
|
||||||
|
|
||||||
#### **--force**, **-f**
|
#### **--force**, **-f**
|
||||||
|
|
||||||
Force the removal of running and paused containers. Forcing a container removal also
|
Force the removal of running and paused containers. Forcing a container removal also
|
||||||
|
|
|
@ -995,7 +995,7 @@ func (r *Runtime) RemoveDepend(ctx context.Context, rmCtr *Container, force bool
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, cID := range podContainerIDS {
|
for _, cID := range podContainerIDS {
|
||||||
rmReports = append(rmReports, &reports.RmReport{Id: cID})
|
rmReports = append(rmReports, &reports.RmReport{Id: cID, RawInput: cID})
|
||||||
}
|
}
|
||||||
return rmReports, nil
|
return rmReports, nil
|
||||||
}
|
}
|
||||||
|
@ -1023,7 +1023,7 @@ func (r *Runtime) RemoveDepend(ctx context.Context, rmCtr *Container, force bool
|
||||||
rmReports = append(rmReports, reports...)
|
rmReports = append(rmReports, reports...)
|
||||||
}
|
}
|
||||||
|
|
||||||
report := reports.RmReport{Id: rmCtr.ID()}
|
report := reports.RmReport{Id: rmCtr.ID(), RawInput: rmCtr.ID()}
|
||||||
report.Err = r.removeContainer(ctx, rmCtr, force, removeVolume, false, timeout)
|
report.Err = r.removeContainer(ctx, rmCtr, force, removeVolume, false, timeout)
|
||||||
return append(rmReports, &report), nil
|
return append(rmReports, &report), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,7 @@ type RestartReport struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RmOptions struct {
|
type RmOptions struct {
|
||||||
|
Filters map[string][]string
|
||||||
All bool
|
All bool
|
||||||
Depend bool
|
Depend bool
|
||||||
Force bool
|
Force bool
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package reports
|
package reports
|
||||||
|
|
||||||
type RmReport struct {
|
type RmReport struct {
|
||||||
Id string `json:"Id"` //nolint:revive,stylecheck
|
Id string `json:"Id"` //nolint:revive,stylecheck
|
||||||
Err error `json:"Err,omitempty"`
|
Err error `json:"Err,omitempty"`
|
||||||
|
RawInput string
|
||||||
}
|
}
|
||||||
|
|
||||||
func RmReportsIds(r []*RmReport) []string {
|
func RmReportsIds(r []*RmReport) []string {
|
||||||
|
|
|
@ -142,10 +142,10 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
if len(rawInputs) == len(ctrs) {
|
if len(rawInputs) == len(ctrs) {
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID()] = rawInputs[i]
|
idToRawInput[ctrs[i].ID()] = rawInputs[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
||||||
|
@ -158,7 +158,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
|
||||||
reports = append(reports, &entities.PauseUnpauseReport{
|
reports = append(reports, &entities.PauseUnpauseReport{
|
||||||
Id: c.ID(),
|
Id: c.ID(),
|
||||||
Err: err,
|
Err: err,
|
||||||
RawInput: ctrMap[c.ID()],
|
RawInput: idToRawInput[c.ID()],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -169,10 +169,10 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
if len(rawInputs) == len(ctrs) {
|
if len(rawInputs) == len(ctrs) {
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID()] = rawInputs[i]
|
idToRawInput[ctrs[i].ID()] = rawInputs[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
||||||
|
@ -185,7 +185,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
|
||||||
reports = append(reports, &entities.PauseUnpauseReport{
|
reports = append(reports, &entities.PauseUnpauseReport{
|
||||||
Id: c.ID(),
|
Id: c.ID(),
|
||||||
Err: err,
|
Err: err,
|
||||||
RawInput: ctrMap[c.ID()],
|
RawInput: idToRawInput[c.ID()],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -196,10 +196,10 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
|
||||||
if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) {
|
if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
if len(rawInputs) == len(ctrs) {
|
if len(rawInputs) == len(ctrs) {
|
||||||
for i := range 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 {
|
errMap, err := parallelctr.ContainerOp(ctx, ctrs, func(c *libpod.Container) error {
|
||||||
|
@ -245,7 +245,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
|
||||||
if options.All {
|
if options.All {
|
||||||
report.RawInput = ctr.ID()
|
report.RawInput = ctr.ID()
|
||||||
} else {
|
} else {
|
||||||
report.RawInput = ctrMap[ctr.ID()]
|
report.RawInput = idToRawInput[ctr.ID()]
|
||||||
}
|
}
|
||||||
report.Err = err
|
report.Err = err
|
||||||
reports = append(reports, report)
|
reports = append(reports, report)
|
||||||
|
@ -275,10 +275,10 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
if len(rawInputs) == len(ctrs) {
|
if len(rawInputs) == len(ctrs) {
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID()] = rawInputs[i]
|
idToRawInput[ctrs[i].ID()] = rawInputs[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reports := make([]*entities.KillReport, 0, len(ctrs))
|
reports := make([]*entities.KillReport, 0, len(ctrs))
|
||||||
|
@ -291,7 +291,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
|
||||||
reports = append(reports, &entities.KillReport{
|
reports = append(reports, &entities.KillReport{
|
||||||
Id: con.ID(),
|
Id: con.ID(),
|
||||||
Err: err,
|
Err: err,
|
||||||
RawInput: ctrMap[con.ID()],
|
RawInput: idToRawInput[con.ID()],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -360,7 +360,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
// this will fail and code will fall through to removing the container from libpod.`
|
// this will fail and code will fall through to removing the container from libpod.`
|
||||||
tmpNames := []string{}
|
tmpNames := []string{}
|
||||||
for _, ctr := range names {
|
for _, ctr := range names {
|
||||||
report := reports.RmReport{Id: ctr}
|
report := reports.RmReport{Id: ctr, RawInput: ctr}
|
||||||
report.Err = ic.Libpod.RemoveStorageContainer(ctr, options.Force)
|
report.Err = ic.Libpod.RemoveStorageContainer(ctr, options.Force)
|
||||||
//nolint:gocritic
|
//nolint:gocritic
|
||||||
if report.Err == nil {
|
if report.Err == nil {
|
||||||
|
@ -381,7 +381,16 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
}
|
}
|
||||||
names = tmpNames
|
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)) {
|
if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) {
|
||||||
// Failed to get containers. If force is specified, get the containers ID
|
// Failed to get containers. If force is specified, get the containers ID
|
||||||
// and evict them
|
// and evict them
|
||||||
|
@ -391,7 +400,10 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
|
|
||||||
for _, ctr := range names {
|
for _, ctr := range names {
|
||||||
logrus.Debugf("Evicting container %q", ctr)
|
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)
|
_, err := ic.Libpod.EvictContainer(ctx, ctr, options.Volumes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) {
|
if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) {
|
||||||
|
@ -461,6 +473,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
report := new(reports.RmReport)
|
report := new(reports.RmReport)
|
||||||
report.Id = ctr.ID()
|
report.Id = ctr.ID()
|
||||||
report.Err = err
|
report.Err = err
|
||||||
|
report.RawInput = idToRawInput[ctr.ID()]
|
||||||
rmReports = append(rmReports, report)
|
rmReports = append(rmReports, report)
|
||||||
}
|
}
|
||||||
return rmReports, nil
|
return rmReports, nil
|
||||||
|
|
|
@ -61,9 +61,9 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID] = rawInputs[i]
|
idToRawInput[ctrs[i].ID] = rawInputs[i]
|
||||||
}
|
}
|
||||||
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
||||||
for _, c := range ctrs {
|
for _, c := range ctrs {
|
||||||
|
@ -75,7 +75,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
|
||||||
reports = append(reports, &entities.PauseUnpauseReport{
|
reports = append(reports, &entities.PauseUnpauseReport{
|
||||||
Id: c.ID,
|
Id: c.ID,
|
||||||
Err: err,
|
Err: err,
|
||||||
RawInput: ctrMap[c.ID],
|
RawInput: idToRawInput[c.ID],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -86,9 +86,9 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID] = rawInputs[i]
|
idToRawInput[ctrs[i].ID] = rawInputs[i]
|
||||||
}
|
}
|
||||||
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
|
||||||
for _, c := range ctrs {
|
for _, c := range ctrs {
|
||||||
|
@ -100,7 +100,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
|
||||||
reports = append(reports, &entities.PauseUnpauseReport{
|
reports = append(reports, &entities.PauseUnpauseReport{
|
||||||
Id: c.ID,
|
Id: c.ID,
|
||||||
Err: err,
|
Err: err,
|
||||||
RawInput: ctrMap[c.ID],
|
RawInput: idToRawInput[c.ID],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -111,9 +111,9 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID] = rawInputs[i]
|
idToRawInput[ctrs[i].ID] = rawInputs[i]
|
||||||
}
|
}
|
||||||
options := new(containers.StopOptions).WithIgnore(opts.Ignore)
|
options := new(containers.StopOptions).WithIgnore(opts.Ignore)
|
||||||
if to := opts.Timeout; to != nil {
|
if to := opts.Timeout; to != nil {
|
||||||
|
@ -123,7 +123,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
|
||||||
for _, c := range ctrs {
|
for _, c := range ctrs {
|
||||||
report := entities.StopReport{
|
report := entities.StopReport{
|
||||||
Id: c.ID,
|
Id: c.ID,
|
||||||
RawInput: ctrMap[c.ID],
|
RawInput: idToRawInput[c.ID],
|
||||||
}
|
}
|
||||||
if err = containers.Stop(ic.ClientCtx, c.ID, options); err != nil {
|
if err = containers.Stop(ic.ClientCtx, c.ID, options); err != nil {
|
||||||
// These first two are considered non-fatal under the right conditions
|
// These first two are considered non-fatal under the right conditions
|
||||||
|
@ -154,9 +154,9 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctrMap := map[string]string{}
|
idToRawInput := map[string]string{}
|
||||||
for i := range ctrs {
|
for i := range ctrs {
|
||||||
ctrMap[ctrs[i].ID] = rawInputs[i]
|
idToRawInput[ctrs[i].ID] = rawInputs[i]
|
||||||
}
|
}
|
||||||
options := new(containers.KillOptions).WithSignal(opts.Signal)
|
options := new(containers.KillOptions).WithSignal(opts.Signal)
|
||||||
reports := make([]*entities.KillReport, 0, len(ctrs))
|
reports := make([]*entities.KillReport, 0, len(ctrs))
|
||||||
|
@ -169,7 +169,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
|
||||||
reports = append(reports, &entities.KillReport{
|
reports = append(reports, &entities.KillReport{
|
||||||
Id: c.ID,
|
Id: c.ID,
|
||||||
Err: err,
|
Err: err,
|
||||||
RawInput: ctrMap[c.ID],
|
RawInput: idToRawInput[c.ID],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reports, nil
|
return reports, nil
|
||||||
|
@ -208,11 +208,18 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
|
|
||||||
toRemove := []string{}
|
toRemove := []string{}
|
||||||
alreadyRemoved := make(map[string]bool) // Avoids trying to remove already removed containers
|
alreadyRemoved := make(map[string]bool) // Avoids trying to remove already removed containers
|
||||||
if opts.All {
|
idToRawInput := map[string]string{}
|
||||||
ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, opts.Ignore, nil)
|
|
||||||
|
if opts.All || len(opts.Filters) > 0 {
|
||||||
|
ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, opts.All, opts.Ignore, nil, opts.Filters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(rawInputs) == len(ctrs) {
|
||||||
|
for i := range ctrs {
|
||||||
|
idToRawInput[ctrs[i].ID] = rawInputs[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, c := range ctrs {
|
for _, c := range ctrs {
|
||||||
toRemove = append(toRemove, c.ID)
|
toRemove = append(toRemove, c.ID)
|
||||||
}
|
}
|
||||||
|
@ -225,10 +232,15 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
// instead of the ID. Since this can only happen
|
// instead of the ID. Since this can only happen
|
||||||
// with external containers, it poses no threat
|
// with external containers, it poses no threat
|
||||||
// to the `alreadyRemoved` checks below.
|
// to the `alreadyRemoved` checks below.
|
||||||
ctrs, err := getContainersByContext(ic.ClientCtx, false, true, []string{ctr})
|
ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, false, true, []string{ctr}, opts.Filters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(rawInputs) == len(ctrs) {
|
||||||
|
for i := range ctrs {
|
||||||
|
idToRawInput[ctrs[i].ID] = rawInputs[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
id := ctr
|
id := ctr
|
||||||
if len(ctrs) == 1 {
|
if len(ctrs) == 1 {
|
||||||
id = ctrs[0].ID
|
id = ctrs[0].ID
|
||||||
|
@ -238,13 +250,20 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
|
||||||
}
|
}
|
||||||
|
|
||||||
rmReports := make([]*reports.RmReport, 0, len(toRemove))
|
rmReports := make([]*reports.RmReport, 0, len(toRemove))
|
||||||
for _, nameOrID := range toRemove {
|
for _, rmCtr := range toRemove {
|
||||||
if alreadyRemoved[nameOrID] {
|
if alreadyRemoved[rmCtr] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
newReports, err := containers.Remove(ic.ClientCtx, nameOrID, options)
|
if ctr, exist := idToRawInput[rmCtr]; exist {
|
||||||
|
rmCtr = ctr
|
||||||
|
}
|
||||||
|
newReports, err := containers.Remove(ic.ClientCtx, rmCtr, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rmReports = append(rmReports, &reports.RmReport{Id: nameOrID, Err: err})
|
rmReports = append(rmReports, &reports.RmReport{
|
||||||
|
Id: rmCtr,
|
||||||
|
Err: err,
|
||||||
|
RawInput: idToRawInput[rmCtr],
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for i := range newReports {
|
for i := range newReports {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
// FIXME: the `ignore` parameter is very likely wrong here as it should rather
|
// FIXME: the `ignore` parameter is very likely wrong here as it should rather
|
||||||
// be used on *errors* from operations such as remove.
|
// be used on *errors* from operations such as remove.
|
||||||
func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) {
|
func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) { //nolint:unparam
|
||||||
ctrs, _, err := getContainersAndInputByContext(contextWithConnection, all, ignore, namesOrIDs, nil)
|
ctrs, _, err := getContainersAndInputByContext(contextWithConnection, all, ignore, namesOrIDs, nil)
|
||||||
return ctrs, err
|
return ctrs, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ var _ = Describe("Podman rm", func() {
|
||||||
result := podmanTest.Podman([]string{"rm", cid})
|
result := podmanTest.Podman([]string{"rm", cid})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).Should(Exit(2))
|
Expect(result).Should(Exit(2))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("containers cannot be removed without force"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm created container", func() {
|
It("podman rm created container", func() {
|
||||||
|
@ -140,11 +142,9 @@ var _ = Describe("Podman rm", func() {
|
||||||
output := result.OutputToString()
|
output := result.OutputToString()
|
||||||
Expect(output).To(ContainSubstring(cid))
|
Expect(output).To(ContainSubstring(cid))
|
||||||
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
|
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm --cidfile", func() {
|
It("podman rm --cidfile", func() {
|
||||||
|
|
||||||
tmpDir, err := ioutil.TempDir("", "")
|
tmpDir, err := ioutil.TempDir("", "")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
tmpFile := tmpDir + "cid"
|
tmpFile := tmpDir + "cid"
|
||||||
|
@ -166,7 +166,6 @@ var _ = Describe("Podman rm", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm multiple --cidfile", func() {
|
It("podman rm multiple --cidfile", func() {
|
||||||
|
|
||||||
tmpDir, err := ioutil.TempDir("", "")
|
tmpDir, err := ioutil.TempDir("", "")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
tmpFile1 := tmpDir + "cid-1"
|
tmpFile1 := tmpDir + "cid-1"
|
||||||
|
@ -201,18 +200,22 @@ var _ = Describe("Podman rm", func() {
|
||||||
result := podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--latest"})
|
result := podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--latest"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).Should(Exit(125))
|
Expect(result).Should(Exit(125))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all"})
|
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).Should(Exit(125))
|
Expect(result).Should(Exit(125))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all", "--latest"})
|
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all", "--latest"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).Should(Exit(125))
|
Expect(result).Should(Exit(125))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", "--latest", "--all"})
|
result = podmanTest.Podman([]string{"rm", "--latest", "--all"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).Should(Exit(125))
|
Expect(result).Should(Exit(125))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("--all and --latest cannot be used together"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm --all", func() {
|
It("podman rm --all", func() {
|
||||||
|
@ -242,10 +245,17 @@ var _ = Describe("Podman rm", func() {
|
||||||
session = podmanTest.Podman([]string{"rm", "bogus", cid})
|
session = podmanTest.Podman([]string{"rm", "bogus", cid})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(1))
|
Expect(session).Should(Exit(1))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
|
||||||
|
if IsRemote() {
|
||||||
|
Expect(session.OutputToString()).To(BeEquivalentTo(cid))
|
||||||
|
}
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"rm", "--ignore", "bogus", cid})
|
session = podmanTest.Podman([]string{"rm", "--ignore", "bogus", cid})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
|
if !IsRemote() {
|
||||||
|
Expect(session.OutputToString()).To(BeEquivalentTo(cid))
|
||||||
|
}
|
||||||
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
|
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -253,6 +263,7 @@ var _ = Describe("Podman rm", func() {
|
||||||
session := podmanTest.Podman([]string{"rm", "bogus"})
|
session := podmanTest.Podman([]string{"rm", "bogus"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(1))
|
Expect(session).Should(Exit(1))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm bogus container and a running container", func() {
|
It("podman rm bogus container and a running container", func() {
|
||||||
|
@ -263,10 +274,12 @@ var _ = Describe("Podman rm", func() {
|
||||||
session = podmanTest.Podman([]string{"rm", "bogus", "test1"})
|
session = podmanTest.Podman([]string{"rm", "bogus", "test1"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(1))
|
Expect(session).Should(Exit(1))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"rm", "test1", "bogus"})
|
session = podmanTest.Podman([]string{"rm", "test1", "bogus"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(1))
|
Expect(session).Should(Exit(1))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm --ignore bogus container and a running container", func() {
|
It("podman rm --ignore bogus container and a running container", func() {
|
||||||
|
@ -274,12 +287,52 @@ var _ = Describe("Podman rm", func() {
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"rm", "--ignore", "test1", "bogus"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(2))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("containers cannot be removed without force"))
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"rm", "-t", "0", "--force", "--ignore", "bogus", "test1"})
|
session = podmanTest.Podman([]string{"rm", "-t", "0", "--force", "--ignore", "bogus", "test1"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
|
Expect(session.OutputToString()).To(BeEquivalentTo("test1"))
|
||||||
|
})
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"rm", "--ignore", "test1", "bogus"})
|
It("podman rm --filter", func() {
|
||||||
session.WaitWithDefaultTimeout()
|
session1 := podmanTest.RunTopContainer("test1")
|
||||||
Expect(session).Should(Exit(0))
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
cid1 := session1.OutputToString()
|
||||||
|
|
||||||
|
session1 = podmanTest.RunTopContainer("test2")
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
cid2 := session1.OutputToString()
|
||||||
|
|
||||||
|
session1 = podmanTest.RunTopContainer("test3")
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
cid3 := session1.OutputToString()
|
||||||
|
shortCid3 := cid3[0:5]
|
||||||
|
|
||||||
|
session1 = podmanTest.Podman([]string{"rm", cid1, "-f", "--filter", "status=running"})
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(125))
|
||||||
|
Expect(session1.ErrorToString()).To(ContainSubstring("--filter takes no arguments"))
|
||||||
|
|
||||||
|
session1 = podmanTest.Podman([]string{"rm", "-a", "-f", "--filter", fmt.Sprintf("id=%swrongid", shortCid3)})
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
Expect(session1.OutputToString()).To(HaveLen(0))
|
||||||
|
|
||||||
|
session1 = podmanTest.Podman([]string{"rm", "-a", "-f", "--filter", fmt.Sprintf("id=%s", shortCid3)})
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
Expect(session1.OutputToString()).To(BeEquivalentTo(cid3))
|
||||||
|
|
||||||
|
session1 = podmanTest.Podman([]string{"rm", "-f", "--filter", fmt.Sprintf("id=%s", cid2)})
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
Expect(session1.OutputToString()).To(BeEquivalentTo(cid2))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,6 +18,7 @@ load helpers
|
||||||
|
|
||||||
# Remove container; now 'inspect' should fail
|
# Remove container; now 'inspect' should fail
|
||||||
run_podman rm $rand
|
run_podman rm $rand
|
||||||
|
is "$output" "$rand" "display raw input"
|
||||||
run_podman 125 inspect $rand
|
run_podman 125 inspect $rand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,10 +345,10 @@ failed | exited | 17
|
||||||
|
|
||||||
@test "rm a stopped container" {
|
@test "rm a stopped container" {
|
||||||
run_podman rm myfailedcontainer
|
run_podman rm myfailedcontainer
|
||||||
is "$output" "[0-9a-f]\\{64\\}" "podman rm myfailedcontainer"
|
is "$output" "myfailedcontainer" "podman rm myfailedcontainer"
|
||||||
|
|
||||||
run_podman rm mydonecontainer
|
run_podman rm mydonecontainer
|
||||||
is "$output" "[0-9a-f]\\{64\\}" "podman rm mydonecontainer"
|
is "$output" "mydonecontainer" "podman rm mydonecontainer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue