mirror of
https://github.com/containers/podman.git
synced 2025-05-21 00:56:36 +08:00
Merge pull request #13587 from giuseppe/clone-to-pod
container: allow clone to an existing pod
This commit is contained in:
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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:"))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user