diff options
-rw-r--r-- | cmd/podman/containers/restore.go | 51 | ||||
-rw-r--r-- | libpod/container_internal.go | 8 | ||||
-rw-r--r-- | pkg/domain/infra/abi/manifest.go | 3 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/manifest.go | 10 | ||||
-rw-r--r-- | test/e2e/checkpoint_test.go | 20 | ||||
-rw-r--r-- | test/e2e/manifest_test.go | 44 |
6 files changed, 108 insertions, 28 deletions
diff --git a/cmd/podman/containers/restore.go b/cmd/podman/containers/restore.go index 1e4745354..6106f2bed 100644 --- a/cmd/podman/containers/restore.go +++ b/cmd/podman/containers/restore.go @@ -93,32 +93,49 @@ func init() { } func restore(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors + var ( + e error + errs utils.OutputErrors + ) podmanStart := time.Now() if rootless.IsRootless() { return fmt.Errorf("restoring a container requires root") } - // Find out if this is an image - inspectOpts := entities.InspectOptions{} - imgData, _, err := registry.ImageEngine().Inspect(context.Background(), args, inspectOpts) - if err != nil { - return err + // Check if the container exists (#15055) + exists := &entities.BoolReport{Value: false} + for _, ctr := range args { + exists, e = registry.ContainerEngine().ContainerExists(registry.GetContext(), ctr, entities.ContainerExistsOptions{}) + if e != nil { + return e + } + if exists.Value { + break + } } - hostInfo, err := registry.ContainerEngine().Info(context.Background()) - if err != nil { - return err - } + if !exists.Value { + // Find out if this is an image + inspectOpts := entities.InspectOptions{} + imgData, _, err := registry.ImageEngine().Inspect(context.Background(), args, inspectOpts) + if err != nil { + return err + } - for i := range imgData { - restoreOptions.CheckpointImage = true - checkpointRuntimeName, found := imgData[i].Annotations[define.CheckpointAnnotationRuntimeName] - if !found { - return fmt.Errorf("image is not a checkpoint: %s", imgData[i].ID) + hostInfo, err := registry.ContainerEngine().Info(context.Background()) + if err != nil { + return err } - if hostInfo.Host.OCIRuntime.Name != checkpointRuntimeName { - return fmt.Errorf("container image \"%s\" requires runtime: \"%s\"", imgData[i].ID, checkpointRuntimeName) + + for i := range imgData { + restoreOptions.CheckpointImage = true + checkpointRuntimeName, found := imgData[i].Annotations[define.CheckpointAnnotationRuntimeName] + if !found { + return fmt.Errorf("image is not a checkpoint: %s", imgData[i].ID) + } + if hostInfo.Host.OCIRuntime.Name != checkpointRuntimeName { + return fmt.Errorf("container image \"%s\" requires runtime: \"%s\"", imgData[i].ID, checkpointRuntimeName) + } } } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 7e330430c..bad68991b 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -347,7 +347,7 @@ func (c *Container) syncContainer() error { } // If runtime knows about the container, update its status in runtime // And then save back to disk - if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStateStopped, define.ContainerStatePaused) { + if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStateStopped, define.ContainerStateStopping, define.ContainerStatePaused) { oldState := c.state.State if err := c.checkExitFile(); err != nil { @@ -1316,10 +1316,10 @@ func (c *Container) stop(timeout uint) error { // Since we're now subject to a race condition with other processes who // may have altered the state (and other data), let's check if the - // state has changed. If so, we should return immediately and log a - // warning. + // state has changed. If so, we should return immediately and leave + // breadcrumbs for debugging if needed. if c.state.State != define.ContainerStateStopping { - logrus.Warnf( + logrus.Debugf( "Container %q state changed from %q to %q while waiting for it to be stopped: discontinuing stop procedure as another process interfered", c.ID(), define.ContainerStateStopping, c.state.State, ) diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go index d20744d76..bdc3d9513 100644 --- a/pkg/domain/infra/abi/manifest.go +++ b/pkg/domain/infra/abi/manifest.go @@ -331,7 +331,8 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin } if opts.Rm { - if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, nil); len(rmErrors) > 0 { + rmOpts := &libimage.RemoveImagesOptions{LookupManifest: true} + if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, rmOpts); len(rmErrors) > 0 { return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0]) } } diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go index d2554f198..4a3148fac 100644 --- a/pkg/domain/infra/tunnel/manifest.go +++ b/pkg/domain/infra/tunnel/manifest.go @@ -110,5 +110,15 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin } } digest, err := manifests.Push(ir.ClientCtx, name, destination, options) + if err != nil { + return "", fmt.Errorf("error adding to manifest list %s: %w", name, err) + } + + if opts.Rm { + if _, rmErrors := ir.Remove(ctx, []string{name}, entities.ImageRemoveOptions{LookupManifest: true}); len(rmErrors) > 0 { + return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0]) + } + } + return digest, err } diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index d1771f336..8f5e1a0b6 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -223,6 +223,26 @@ var _ = Describe("Podman checkpoint", func() { Expect(result).Should(Exit(0)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) + + // Restore a container which name is equal to a image name (#15055) + localRunString = getRunString([]string{"--name", "alpine", "quay.io/libpod/alpine:latest", "top"}) + session = podmanTest.Podman(localRunString) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + result = podmanTest.Podman([]string{"container", "checkpoint", "alpine"}) + result.WaitWithDefaultTimeout() + + Expect(result).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) + + result = podmanTest.Podman([]string{"container", "restore", "alpine"}) + result.WaitWithDefaultTimeout() + + Expect(result).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) }) It("podman pause a checkpointed container by id", func() { diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index 1f58419a1..a7fcd1559 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -339,6 +339,16 @@ var _ = Describe("Podman manifest", func() { push = podmanTest.Podman([]string{"manifest", "push", "--tls-verify=false", "--creds=podmantest:wrongpasswd", "foo", "localhost:" + registry.Port + "/credstest"}) push.WaitWithDefaultTimeout() Expect(push).To(ExitWithError()) + + // push --rm after pull image (#15033) + push = podmanTest.Podman([]string{"manifest", "push", "--rm", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "foo", "localhost:" + registry.Port + "/rmtest"}) + push.WaitWithDefaultTimeout() + Expect(push).Should(Exit(0)) + + session = podmanTest.Podman([]string{"images", "-q", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) }) It("push with error", func() { @@ -348,8 +358,8 @@ var _ = Describe("Podman manifest", func() { Expect(session.ErrorToString()).NotTo(BeEmpty()) }) - It("push --rm", func() { - SkipIfRemote("remote does not support --rm") + It("push --rm to local directory", func() { + SkipIfRemote("manifest push to dir not supported in remote mode") session := podmanTest.Podman([]string{"manifest", "create", "foo"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -365,13 +375,35 @@ var _ = Describe("Podman manifest", func() { session = podmanTest.Podman([]string{"manifest", "push", "--purge", "foo", "dir:" + dest}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) + session = podmanTest.Podman([]string{"images", "-q", "foo"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError()) + Expect(session).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) - session = podmanTest.Podman([]string{"manifest", "rm", "foo1", "foo2"}) + // push --rm after pull image (#15033) + session = podmanTest.Podman([]string{"pull", "quay.io/libpod/testdigest_v2s2"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError()) + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"manifest", "create", "bar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"manifest", "add", "bar", "quay.io/libpod/testdigest_v2s2"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"manifest", "push", "--rm", "bar", "dir:" + dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"images", "-q", "bar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + + session = podmanTest.Podman([]string{"manifest", "rm", "foo", "bar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(ExitWithError()) + Expect(session.ErrorToString()).To(ContainSubstring("foo: image not known")) + Expect(session.ErrorToString()).To(ContainSubstring("bar: image not known")) }) It("exists", func() { |