summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2022-03-22 11:04:46 +0100
committerGiuseppe Scrivano <gscrivan@redhat.com>2022-03-24 14:24:50 +0100
commitb469bf5c05ce05e7b77852fa686f1e26dd59ec3e (patch)
tree5f4f087eb631acc3372ebb848d5b0ef4c4595807
parent809f82bdbd441d602e584b1c9c2b5597a739b10e (diff)
downloadpodman-b469bf5c05ce05e7b77852fa686f1e26dd59ec3e.tar.gz
podman-b469bf5c05ce05e7b77852fa686f1e26dd59ec3e.tar.bz2
podman-b469bf5c05ce05e7b77852fa686f1e26dd59ec3e.zip
container: allow clone to an existing pod
Closes: https://github.com/containers/podman/issues/3979 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r--cmd/podman/common/create.go16
-rw-r--r--docs/source/markdown/podman-container-clone.1.md6
-rw-r--r--pkg/domain/infra/abi/containers.go29
-rw-r--r--test/e2e/container_clone_test.go37
4 files changed, 80 insertions, 8 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index 8d9a255ec..afaa1942e 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -394,14 +394,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(platformFlagName, completion.AutocompleteNone)
- podFlagName := "pod"
- createFlags.StringVar(
- &cf.Pod,
- podFlagName, "",
- "Run container in an existing pod",
- )
- _ = cmd.RegisterFlagCompletionFunc(podFlagName, AutocompletePods)
-
podIDFileFlagName := "pod-id-file"
createFlags.StringVar(
&cf.PodIDFile,
@@ -837,6 +829,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone)
+ podFlagName := "pod"
+ createFlags.StringVar(
+ &cf.Pod,
+ podFlagName, "",
+ "Run container in an existing pod",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(podFlagName, AutocompletePods)
+
cpuPeriodFlagName := "cpu-period"
createFlags.Uint64Var(
&cf.CPUPeriod,
diff --git a/docs/source/markdown/podman-container-clone.1.md b/docs/source/markdown/podman-container-clone.1.md
index 870bf077c..eaf330373 100644
--- a/docs/source/markdown/podman-container-clone.1.md
+++ b/docs/source/markdown/podman-container-clone.1.md
@@ -141,6 +141,12 @@ If no memory limits are specified, the original container's will be used.
Set a custom name for the cloned container. The default if not specified is of the syntax: **<ORIGINAL_NAME>-clone**
+#### **--pod**=*name*
+
+Clone the container in an existing pod. It is helpful to move a container to an
+existing pod. The container will join the pod shared namespaces, losing its configuration
+that conflicts with the shared namespaces.
+
#### **--run**
When set to true, this flag runs the newly created container after the
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 1986228a6..f45bdeba5 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -1496,6 +1496,35 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti
return nil, err
}
+ if ctrCloneOpts.CreateOpts.Pod != "" {
+ pod, err := ic.Libpod.LookupPod(ctrCloneOpts.CreateOpts.Pod)
+ if err != nil {
+ return nil, err
+ }
+
+ allNamespaces := []struct {
+ isShared bool
+ value *specgen.Namespace
+ }{
+ {pod.SharesPID(), &spec.PidNS},
+ {pod.SharesNet(), &spec.NetNS},
+ {pod.SharesCgroup(), &spec.CgroupNS},
+ {pod.SharesIPC(), &spec.IpcNS},
+ {pod.SharesUTS(), &spec.UtsNS},
+ }
+
+ printWarning := false
+ for _, n := range allNamespaces {
+ if n.isShared && !n.value.IsDefault() {
+ *n.value = specgen.Namespace{NSMode: specgen.Default}
+ printWarning = true
+ }
+ }
+ if printWarning {
+ logrus.Warning("At least one namespace was reset to the default configuration")
+ }
+ }
+
err = specgenutil.FillOutSpecGen(spec, &ctrCloneOpts.CreateOpts, []string{})
if err != nil {
return nil, err
diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go
index bebc6872b..a327bb8ed 100644
--- a/test/e2e/container_clone_test.go
+++ b/test/e2e/container_clone_test.go
@@ -184,4 +184,41 @@ var _ = Describe("Podman container clone", func() {
Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(Equal(runInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode))
})
+ It("podman container clone to a pod", func() {
+ createPod := podmanTest.Podman([]string{"pod", "create", "--share", "uts", "--name", "foo-pod"})
+ createPod.WaitWithDefaultTimeout()
+ Expect(createPod).To(Exit(0))
+
+ ctr := podmanTest.RunTopContainer("ctr")
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr).Should(Exit(0))
+
+ clone := podmanTest.Podman([]string{"container", "clone", "--name", "cloned", "--pod", "foo-pod", "ctr"})
+ clone.WaitWithDefaultTimeout()
+ Expect(clone).To(Exit(0))
+
+ ctrInspect := podmanTest.Podman([]string{"inspect", "cloned"})
+ ctrInspect.WaitWithDefaultTimeout()
+ Expect(ctrInspect).Should(Exit(0))
+
+ Expect(ctrInspect.InspectContainerToJSON()[0].Pod).Should(Equal(createPod.OutputToString()))
+
+ Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(Not(ContainSubstring("container:")))
+
+ createPod = podmanTest.Podman([]string{"pod", "create", "--share", "uts,net", "--name", "bar-pod"})
+ createPod.WaitWithDefaultTimeout()
+ Expect(createPod).To(Exit(0))
+
+ clone = podmanTest.Podman([]string{"container", "clone", "--name", "cloned2", "--pod", "bar-pod", "ctr"})
+ clone.WaitWithDefaultTimeout()
+ Expect(clone).To(Exit(0))
+
+ ctrInspect = podmanTest.Podman([]string{"inspect", "cloned2"})
+ ctrInspect.WaitWithDefaultTimeout()
+ Expect(ctrInspect).Should(Exit(0))
+
+ Expect(ctrInspect.InspectContainerToJSON()[0].Pod).Should(Equal(createPod.OutputToString()))
+
+ Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(ContainSubstring("container:"))
+ })
})