From 2685c8dc43ff3443e30185345627760c9b94efa3 Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Tue, 2 Aug 2022 17:24:23 +0900 Subject: Output messages display rawInput `init`, `checkpint/restore` and `cleanup` command now display output messages which is rawInput instead of a container ID. Example: ``` $ podman init $ podman init ``` Signed-off-by: Toshiki Sonoda --- cmd/podman/containers/checkpoint.go | 15 ++-- cmd/podman/containers/cleanup.go | 17 +++-- cmd/podman/containers/init.go | 9 ++- cmd/podman/containers/pause.go | 9 ++- cmd/podman/containers/restore.go | 15 ++-- cmd/podman/containers/start.go | 19 +++-- cmd/podman/containers/stop.go | 9 ++- cmd/podman/containers/unpause.go | 9 ++- pkg/domain/entities/containers.go | 8 ++- pkg/domain/infra/abi/containers.go | 82 ++++++++++++++-------- pkg/domain/infra/tunnel/containers.go | 46 ++++++++---- test/e2e/checkpoint_test.go | 12 ++++ test/e2e/cleanup_test.go | 128 ++++++++++++++++++++++++++++++++++ test/e2e/init_test.go | 10 +++ test/e2e/start_test.go | 20 ------ test/e2e/stop_test.go | 17 +++++ test/system/045-start.bats | 16 +++++ test/system/050-stop.bats | 16 +++++ test/system/520-checkpoint.bats | 19 +++++ 19 files changed, 366 insertions(+), 110 deletions(-) create mode 100644 test/e2e/cleanup_test.go diff --git a/cmd/podman/containers/checkpoint.go b/cmd/podman/containers/checkpoint.go index 0eb0db394..4350e5586 100644 --- a/cmd/podman/containers/checkpoint.go +++ b/cmd/podman/containers/checkpoint.go @@ -130,14 +130,15 @@ func checkpoint(cmd *cobra.Command, args []string) error { var statistics checkpointStatistics for _, r := range responses { - if r.Err == nil { - if checkpointOptions.PrintStats { - statistics.ContainerStatistics = append(statistics.ContainerStatistics, r) - } else { - fmt.Println(r.Id) - } - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case checkpointOptions.PrintStats: + statistics.ContainerStatistics = append(statistics.ContainerStatistics, r) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } diff --git a/cmd/podman/containers/cleanup.go b/cmd/podman/containers/cleanup.go index c9a5cb28b..6abc5df19 100644 --- a/cmd/podman/containers/cleanup.go +++ b/cmd/podman/containers/cleanup.go @@ -84,21 +84,20 @@ func cleanup(cmd *cobra.Command, args []string) error { return err } for _, r := range responses { - if r.CleanErr == nil && r.RmErr == nil && r.RmiErr == nil { - fmt.Println(r.Id) - continue - } - if r.RmErr != nil { + switch { + case r.RmErr != nil: logrus.Errorf("Removing container: %v", r.RmErr) errs = append(errs, r.RmErr) - } - if r.RmiErr != nil { + case r.RmiErr != nil: logrus.Errorf("Removing image: %v", r.RmiErr) errs = append(errs, r.RmiErr) - } - if r.CleanErr != nil { + case r.CleanErr != nil: logrus.Errorf("Cleaning up container: %v", r.CleanErr) errs = append(errs, r.CleanErr) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } return errs.PrintErrors() diff --git a/cmd/podman/containers/init.go b/cmd/podman/containers/init.go index 649cdf1c9..8f53dca45 100644 --- a/cmd/podman/containers/init.go +++ b/cmd/podman/containers/init.go @@ -74,10 +74,13 @@ func initContainer(cmd *cobra.Command, args []string) error { return err } for _, r := range report { - if r.Err == nil { - fmt.Println(r.Id) - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } return errs.PrintErrors() diff --git a/cmd/podman/containers/pause.go b/cmd/podman/containers/pause.go index 53aa423ac..38c4f45aa 100644 --- a/cmd/podman/containers/pause.go +++ b/cmd/podman/containers/pause.go @@ -113,10 +113,13 @@ func pause(cmd *cobra.Command, args []string) error { return err } for _, r := range responses { - if r.Err == nil { - fmt.Println(r.RawInput) - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } return errs.PrintErrors() diff --git a/cmd/podman/containers/restore.go b/cmd/podman/containers/restore.go index 6106f2bed..ee01e19b8 100644 --- a/cmd/podman/containers/restore.go +++ b/cmd/podman/containers/restore.go @@ -193,14 +193,15 @@ func restore(cmd *cobra.Command, args []string) error { var statistics restoreStatistics for _, r := range responses { - if r.Err == nil { - if restoreOptions.PrintStats { - statistics.ContainerStatistics = append(statistics.ContainerStatistics, r) - } else { - fmt.Println(r.Id) - } - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case restoreOptions.PrintStats: + statistics.ContainerStatistics = append(statistics.ContainerStatistics, r) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index cd4fa17b8..4416d1c55 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -137,19 +137,18 @@ func start(cmd *cobra.Command, args []string) error { if err != nil { return err } - for _, r := range responses { - if r.Err == nil { - if startOptions.Attach { - // Implement the exitcode when the only one container is enabled attach - registry.SetExitCode(r.ExitCode) - } else { - fmt.Println(r.RawInput) - } - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case startOptions.Attach: + // Implement the exitcode when the only one container is enabled attach + registry.SetExitCode(r.ExitCode) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } - return errs.PrintErrors() } diff --git a/cmd/podman/containers/stop.go b/cmd/podman/containers/stop.go index 261f441c3..9ed8e3083 100644 --- a/cmd/podman/containers/stop.go +++ b/cmd/podman/containers/stop.go @@ -125,10 +125,13 @@ func stop(cmd *cobra.Command, args []string) error { return err } for _, r := range responses { - if r.Err == nil { - fmt.Println(r.RawInput) - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } return errs.PrintErrors() diff --git a/cmd/podman/containers/unpause.go b/cmd/podman/containers/unpause.go index 4282e490e..617c0e3a4 100644 --- a/cmd/podman/containers/unpause.go +++ b/cmd/podman/containers/unpause.go @@ -121,10 +121,13 @@ func unpause(cmd *cobra.Command, args []string) error { } for _, r := range responses { - if r.Err == nil { - fmt.Println(r.RawInput) - } else { + switch { + case r.Err != nil: errs = append(errs, r.Err) + case r.RawInput != "": + fmt.Println(r.RawInput) + default: + fmt.Println(r.Id) } } return errs.PrintErrors() diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index df793034b..fdaf4e194 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -201,6 +201,7 @@ type CheckpointOptions struct { type CheckpointReport struct { Err error `json:"-"` Id string `json:"Id"` //nolint:revive,stylecheck + RawInput string `json:"RawInput"` RuntimeDuration int64 `json:"runtime_checkpoint_duration"` CRIUStatistics *define.CRIUCheckpointRestoreStatistics `json:"criu_statistics"` } @@ -227,6 +228,7 @@ type RestoreOptions struct { type RestoreReport struct { Err error `json:"-"` Id string `json:"Id"` //nolint:revive,stylecheck + RawInput string `json:"RawInput"` RuntimeDuration int64 `json:"runtime_restore_duration"` CRIUStatistics *define.CRIUCheckpointRestoreStatistics `json:"criu_statistics"` } @@ -373,6 +375,7 @@ type ContainerCleanupOptions struct { type ContainerCleanupReport struct { CleanErr error Id string //nolint:revive,stylecheck + RawInput string RmErr error RmiErr error } @@ -387,8 +390,9 @@ type ContainerInitOptions struct { // ContainerInitReport describes the results of a // container init type ContainerInitReport struct { - Err error - Id string //nolint:revive,stylecheck + Err error + Id string //nolint:revive,stylecheck + RawInput string } // ContainerMountOptions describes the input values for mounting containers diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 783224e9c..d7fd2e15d 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -598,8 +598,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 +617,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 +654,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 +681,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 +713,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 +721,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 +730,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, }) @@ -1211,14 +1225,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 +1279,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 diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 98c73c51a..13768f017 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -343,6 +343,12 @@ func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrID string, } func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, opts entities.CheckpointOptions) ([]*entities.CheckpointReport, error) { + var ( + err error + ctrs []entities.ListContainer + rawInputs []string + idToRawInput = map[string]string{} + ) options := new(containers.CheckpointOptions) options.WithFileLocks(opts.FileLocks) options.WithIgnoreRootfs(opts.IgnoreRootFS) @@ -355,11 +361,6 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ options.WithLeaveRunning(opts.LeaveRunning) options.WithWithPrevious(opts.WithPrevious) - var ( - err error - ctrs = []entities.ListContainer{} - ) - if opts.All { allCtrs, err := getContainersByContext(ic.ClientCtx, true, false, []string{}) if err != nil { @@ -372,10 +373,15 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ } } } else { - ctrs, err = getContainersByContext(ic.ClientCtx, false, false, namesOrIds) + ctrs, rawInputs, err = getContainersAndInputByContext(ic.ClientCtx, false, false, namesOrIds, nil) 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(ctrs)) for _, c := range ctrs { @@ -383,6 +389,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ if err != nil { reports = append(reports, &entities.CheckpointReport{Id: c.ID, Err: err}) } else { + report.RawInput = idToRawInput[report.Id] reports = append(reports, report) } } @@ -394,6 +401,10 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st return nil, fmt.Errorf("--import-previous is not supported on the remote client") } + var ( + ids []string + idToRawInput = map[string]string{} + ) options := new(containers.RestoreOptions) options.WithFileLocks(opts.FileLocks) options.WithIgnoreRootfs(opts.IgnoreRootFS) @@ -412,10 +423,6 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st report, err := containers.Restore(ic.ClientCtx, "", options) return []*entities.RestoreReport{report}, err } - - var ( - ids = []string{} - ) if opts.All { allCtrs, err := getContainersByContext(ic.ClientCtx, true, false, []string{}) if err != nil { @@ -438,6 +445,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st ctrData, _, err := ic.ContainerInspect(ic.ClientCtx, []string{nameOrID}, entities.InspectOptions{}) if err == nil && len(ctrData) > 0 { ids = append(ids, ctrData[0].ID) + idToRawInput[ctrData[0].ID] = nameOrID } else { // If container was not found, check if this is a checkpoint image inspectReport, err := images.GetImage(ic.ClientCtx, nameOrID, getImageOptions) @@ -461,6 +469,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st if err != nil { reports = append(reports, &entities.RestoreReport{Id: id, Err: err}) } + report.RawInput = idToRawInput[report.Id] reports = append(reports, report) } return reports, nil @@ -916,21 +925,28 @@ 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(ic.ClientCtx, options.All, false, namesOrIds) + ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, options.All, false, namesOrIds, nil) 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 { - err := containers.ContainerInit(ic.ClientCtx, ctr.ID, nil) + for _, c := range ctrs { + err := containers.ContainerInit(ic.ClientCtx, c.ID, nil) // When using all, it is NOT considered an error if a container // has already been init'd. if err != nil && options.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) { err = nil } reports = append(reports, &entities.ContainerInitReport{ - Err: err, - Id: ctr.ID, + Err: err, + RawInput: idToRawInput[c.ID], + Id: c.ID, }) } return reports, nil diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index 8f5e1a0b6..bc99455f3 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -132,6 +132,7 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Equal(cid)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) @@ -156,6 +157,7 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Equal(cid)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) @@ -214,6 +216,7 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Equal("test_name")) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) @@ -221,6 +224,7 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Equal("test_name")) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) @@ -298,6 +302,7 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Equal("second")) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) @@ -310,6 +315,7 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(Equal("second")) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited"))) @@ -325,16 +331,20 @@ var _ = Describe("Podman checkpoint", func() { session1 := podmanTest.Podman(localRunString) session1.WaitWithDefaultTimeout() Expect(session1).Should(Exit(0)) + cid1 := session1.OutputToString() localRunString = getRunString([]string{"--name", "second", ALPINE, "top"}) session2 := podmanTest.Podman(localRunString) session2.WaitWithDefaultTimeout() Expect(session2).Should(Exit(0)) + cid2 := session2.OutputToString() result := podmanTest.Podman([]string{"container", "checkpoint", "-a"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(ContainSubstring(cid1)) + Expect(result.OutputToString()).To(ContainSubstring(cid2)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) @@ -347,6 +357,8 @@ var _ = Describe("Podman checkpoint", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(ContainSubstring(cid1)) + Expect(result.OutputToString()).To(ContainSubstring(cid2)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited"))) diff --git a/test/e2e/cleanup_test.go b/test/e2e/cleanup_test.go new file mode 100644 index 000000000..f15f9bd5a --- /dev/null +++ b/test/e2e/cleanup_test.go @@ -0,0 +1,128 @@ +package integration + +import ( + "os" + + . "github.com/containers/podman/v4/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("Podman container cleanup", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + SkipIfRemote("podman container cleanup is not supported in remote") + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + processTestResult(f) + + }) + + It("podman cleanup bogus container", func() { + session := podmanTest.Podman([]string{"container", "cleanup", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + Expect(session.ErrorToString()).To(ContainSubstring("no such container")) + }) + + It("podman cleanup container by id", func() { + session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToString() + session = podmanTest.Podman([]string{"container", "cleanup", cid}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(cid)) + }) + + It("podman cleanup container by short id", func() { + session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToString() + shortID := cid[0:10] + session = podmanTest.Podman([]string{"container", "cleanup", shortID}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(shortID)) + }) + + It("podman cleanup container by name", func() { + session := podmanTest.Podman([]string{"create", "--name", "foo", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"container", "cleanup", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("foo")) + }) + + It("podman cleanup all containers", func() { + session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToString() + + session = podmanTest.Podman([]string{"container", "cleanup", "--all"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(cid)) + }) + + It("podman cleanup latest container", func() { + SkipIfRemote("--latest flag n/a") + session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"create", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToString() + + session = podmanTest.Podman([]string{"container", "cleanup", "--latest"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(cid)) + }) + + It("podman cleanup running container", func() { + session := podmanTest.RunTopContainer("running") + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"container", "cleanup", "running"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + Expect(session.ErrorToString()).To(ContainSubstring("container state improper")) + }) + + It("podman cleanup paused container", func() { + SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1") + session := podmanTest.RunTopContainer("paused") + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"pause", "paused"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"container", "cleanup", "paused"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + Expect(session.ErrorToString()).To(ContainSubstring("container state improper")) + }) +}) diff --git a/test/e2e/init_test.go b/test/e2e/init_test.go index ccc102fa3..25b9e079a 100644 --- a/test/e2e/init_test.go +++ b/test/e2e/init_test.go @@ -52,6 +52,7 @@ var _ = Describe("Podman init", func() { init := podmanTest.Podman([]string{"init", cid}) init.WaitWithDefaultTimeout() Expect(init).Should(Exit(0)) + Expect(init.OutputToString()).To(Equal(cid)) result := podmanTest.Podman([]string{"inspect", cid}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) @@ -67,6 +68,7 @@ var _ = Describe("Podman init", func() { init := podmanTest.Podman([]string{"init", name}) init.WaitWithDefaultTimeout() Expect(init).Should(Exit(0)) + Expect(init.OutputToString()).To(Equal(name)) result := podmanTest.Podman([]string{"inspect", name}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) @@ -79,9 +81,11 @@ var _ = Describe("Podman init", func() { session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + cid := session.OutputToString() init := podmanTest.Podman([]string{"init", "--latest"}) init.WaitWithDefaultTimeout() Expect(init).Should(Exit(0)) + Expect(init.OutputToString()).To(Equal(cid)) result := podmanTest.Podman([]string{"inspect", "--latest"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) @@ -93,15 +97,21 @@ var _ = Describe("Podman init", func() { session := podmanTest.Podman([]string{"create", "--name", "test1", ALPINE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + cid := session.OutputToString() session2 := podmanTest.Podman([]string{"create", "--name", "test2", ALPINE, "ls"}) session2.WaitWithDefaultTimeout() Expect(session2).Should(Exit(0)) + cid2 := session2.OutputToString() session3 := podmanTest.Podman([]string{"run", "--name", "test3", "-d", ALPINE, "top"}) session3.WaitWithDefaultTimeout() Expect(session3).Should(Exit(0)) + cid3 := session3.OutputToString() init := podmanTest.Podman([]string{"init", "--all"}) init.WaitWithDefaultTimeout() Expect(init).Should(Exit(0)) + Expect(init.OutputToString()).To(ContainSubstring(cid)) + Expect(init.OutputToString()).To(ContainSubstring(cid2)) + Expect(init.OutputToString()).To(ContainSubstring(cid3)) result := podmanTest.Podman([]string{"inspect", "test1"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index 73af9d12c..0c60c084a 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -99,23 +99,6 @@ var _ = Describe("Podman start", func() { Expect(session.OutputToString()).To(Equal(shortID)) }) - It("podman container start single container by short id", func() { - session := podmanTest.Podman([]string{"container", "create", ALPINE, "ls"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - cid := session.OutputToString() - shortID := cid[0:10] - session = podmanTest.Podman([]string{"container", "start", shortID}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal(shortID)) - - session = podmanTest.Podman([]string{"stop", shortID}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Equal(shortID)) - }) - It("podman start single container by name", func() { name := "foobar99" session := podmanTest.Podman([]string{"create", "--name", name, ALPINE, "ls"}) @@ -124,9 +107,6 @@ var _ = Describe("Podman start", func() { session = podmanTest.Podman([]string{"start", name}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - if podmanTest.RemoteTest { - Skip("Container-start name check doesn't work on remote client. It always returns the full ID.") - } Expect(session.OutputToString()).To(Equal(name)) }) diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go index 7a258466a..23abb6d92 100644 --- a/test/e2e/stop_test.go +++ b/test/e2e/stop_test.go @@ -69,6 +69,19 @@ var _ = Describe("Podman stop", func() { Expect(strings.TrimSpace(finalCtrs.OutputToString())).To(Equal("")) }) + It("podman stop single container by short id", func() { + session := podmanTest.RunTopContainer("test1") + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToString() + shortID := cid[0:10] + + session = podmanTest.Podman([]string{"stop", shortID}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(shortID)) + }) + It("podman stop container by name", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() @@ -198,9 +211,13 @@ var _ = Describe("Podman stop", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + cid := session.OutputToString() + session = podmanTest.Podman([]string{"stop", "-l", "-t", "1"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(cid)) + finalCtrs := podmanTest.Podman([]string{"ps", "-q"}) finalCtrs.WaitWithDefaultTimeout() Expect(finalCtrs).Should(Exit(0)) diff --git a/test/system/045-start.bats b/test/system/045-start.bats index ad8483bba..d19171ec3 100644 --- a/test/system/045-start.bats +++ b/test/system/045-start.bats @@ -66,4 +66,20 @@ load helpers is "$output" "$cid_exited_0" } +@test "podman start print IDs or raw input" { + # start --all must print the IDs + run_podman create $IMAGE top + ctrID="$output" + run_podman start --all + is "$output" "$ctrID" + + # start $input must print $input + cname=$(random_string) + run_podman create --name $cname $IMAGE top + run_podman start $cname + is "$output" $cname + + run_podman rm -t 0 -f $ctrID $cname +} + # vim: filetype=sh diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats index 39002512b..a21a036c2 100644 --- a/test/system/050-stop.bats +++ b/test/system/050-stop.bats @@ -59,6 +59,22 @@ load helpers is "${lines[3]}" "c4--Created.*" "ps -a, created container (unaffected)" } +@test "podman stop print IDs or raw input" { + # stop -a must print the IDs + run_podman run -d $IMAGE top + ctrID="$output" + run_podman stop --all + is "$output" "$ctrID" + + # stop $input must print $input + cname=$(random_string) + run_podman run -d --name $cname $IMAGE top + run_podman stop $cname + is "$output" $cname + + run_podman rm -t 0 -f $ctrID $cname +} + # #9051 : podman stop --ignore was not working with podman-remote @test "podman stop --ignore" { name=thiscontainerdoesnotexist diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats index 7c8fc143a..73fa5d4c4 100644 --- a/test/system/520-checkpoint.bats +++ b/test/system/520-checkpoint.bats @@ -101,6 +101,25 @@ function teardown() { run_podman rm -t 0 -f $cid } +@test "podman checkpoint/restore print IDs or raw input" { + # checkpoint/restore -a must print the IDs + run_podman run -d $IMAGE top + ctrID="$output" + run_podman container checkpoint -a + is "$output" "$ctrID" + run_podman container restore -a + is "$output" "$ctrID" + + # checkpoint/restore $input must print $input + cname=$(random_string) + run_podman run -d --name $cname $IMAGE top + run_podman container checkpoint $cname + is "$output" $cname + run_podman container restore $cname + is "$output" $cname + + run_podman rm -t 0 -f $ctrID $cname +} @test "podman checkpoint --export, with volumes" { skip_if_remote "Test uses --root/--runroot, which are N/A over remote" -- cgit v1.2.3-54-g00ecf