summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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--pkg/specgen/generate/container.go4
-rw-r--r--test/e2e/container_clone_test.go37
5 files changed, 82 insertions, 10 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/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 64669f34d..0e9d33dd8 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -338,8 +338,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
}
// ConfigToSpec takes a completed container config and converts it back into a specgenerator for purposes of cloning an exisiting container
-func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID string) (*libpod.Container, error) {
- c, err := rt.LookupContainer(contaierID)
+func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID string) (*libpod.Container, error) {
+ c, err := rt.LookupContainer(containerID)
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:"))
+ })
})