Skip to content

Commit

Permalink
Merge pull request #13587 from giuseppe/clone-to-pod
Browse files Browse the repository at this point in the history
container: allow clone to an existing pod
  • Loading branch information
openshift-merge-robot authored Mar 24, 2022
2 parents 3274849 + b469bf5 commit caaaf07
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 10 deletions.
16 changes: 8 additions & 8 deletions cmd/podman/common/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions docs/source/markdown/podman-container-clone.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 29 additions & 0 deletions pkg/domain/infra/abi/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pkg/specgen/generate/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
37 changes: 37 additions & 0 deletions test/e2e/container_clone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:"))
})
})

0 comments on commit caaaf07

Please sign in to comment.