aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2022-02-22 10:10:49 -0500
committerGitHub <noreply@github.com>2022-02-22 10:10:49 -0500
commitfab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d (patch)
tree7bafc1608557fd8f98970eaece2225b0d4820edb /cmd
parent948dfc6f02b7b15547a42e39760b04eca20b193d (diff)
parent94df7015121759ce69f35f7e7735aa2e4a2dc71a (diff)
downloadpodman-fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d.tar.gz
podman-fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d.tar.bz2
podman-fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d.zip
Merge pull request #13059 from cdoern/clone
Implement Podman Container Clone
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/common/completion.go14
-rw-r--r--cmd/podman/common/create.go445
-rw-r--r--cmd/podman/containers/clone.go80
-rw-r--r--cmd/podman/containers/create.go2
-rw-r--r--cmd/podman/containers/run.go2
-rw-r--r--cmd/podman/pods/create.go2
6 files changed, 321 insertions, 224 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index a2ce3834d..9ebdcda2b 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -1308,3 +1308,17 @@ func AutocompleteCompressionFormat(cmd *cobra.Command, args []string, toComplete
types := []string{"gzip", "zstd", "zstd:chunked"}
return types, cobra.ShellCompDirectiveNoFileComp
}
+
+// AutocompleteClone - Autocomplete container and image names
+func AutocompleteClone(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ if !validCurrentCmdLine(cmd, args, toComplete) {
+ return nil, cobra.ShellCompDirectiveNoFileComp
+ }
+ switch len(args) {
+ case 0:
+ return getContainers(cmd, toComplete, completeDefault)
+ case 2:
+ return getImages(cmd, toComplete)
+ }
+ return nil, cobra.ShellCompDirectiveNoFileComp
+}
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index 1121806d5..634b49db7 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -28,10 +28,10 @@ func ContainerToPodOptions(containerCreate *entities.ContainerCreateOptions, pod
}
// DefineCreateFlags declares and instantiates the container create flags
-func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, isInfra bool) {
+func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, isInfra bool, clone bool) {
createFlags := cmd.Flags()
- if !isInfra {
+ if !isInfra && !clone { // regular create flags
annotationFlagName := "annotation"
createFlags.StringSliceVar(
&cf.Annotation,
@@ -103,45 +103,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(cgroupsFlagName, AutocompleteCgroupMode)
- cpuPeriodFlagName := "cpu-period"
- createFlags.Uint64Var(
- &cf.CPUPeriod,
- cpuPeriodFlagName, 0,
- "Limit the CPU CFS (Completely Fair Scheduler) period",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpuPeriodFlagName, completion.AutocompleteNone)
-
- cpuQuotaFlagName := "cpu-quota"
- createFlags.Int64Var(
- &cf.CPUQuota,
- cpuQuotaFlagName, 0,
- "Limit the CPU CFS (Completely Fair Scheduler) quota",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpuQuotaFlagName, completion.AutocompleteNone)
-
- cpuRtPeriodFlagName := "cpu-rt-period"
- createFlags.Uint64Var(
- &cf.CPURTPeriod,
- cpuRtPeriodFlagName, 0,
- "Limit the CPU real-time period in microseconds",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpuRtPeriodFlagName, completion.AutocompleteNone)
-
- cpuRtRuntimeFlagName := "cpu-rt-runtime"
- createFlags.Int64Var(
- &cf.CPURTRuntime,
- cpuRtRuntimeFlagName, 0,
- "Limit the CPU real-time runtime in microseconds",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpuRtRuntimeFlagName, completion.AutocompleteNone)
-
- cpuSharesFlagName := "cpu-shares"
- createFlags.Uint64Var(
- &cf.CPUShares,
- cpuSharesFlagName, 0,
- "CPU shares (relative weight)",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpuSharesFlagName, completion.AutocompleteNone)
cidfileFlagName := "cidfile"
createFlags.StringVar(
&cf.CIDFile,
@@ -149,13 +110,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
"Write the container ID to the file",
)
_ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault)
- cpusetMemsFlagName := "cpuset-mems"
- createFlags.StringVar(
- &cf.CPUSetMems,
- cpusetMemsFlagName, "",
- "Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone)
deviceCgroupRuleFlagName := "device-cgroup-rule"
createFlags.StringSliceVar(
@@ -358,14 +312,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(logOptFlagName, AutocompleteLogOpt)
- memoryFlagName := "memory"
- createFlags.StringVarP(
- &cf.Memory,
- memoryFlagName, "m", "",
- "Memory limit "+sizeWithUnitFormat,
- )
- _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
-
memoryReservationFlagName := "memory-reservation"
createFlags.StringVar(
&cf.MemoryReservation,
@@ -703,199 +649,256 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
`If a container with the same name exists, replace it`,
)
}
+ if isInfra || (!clone && !isInfra) { // infra container flags, create should also pick these up
+ sysctlFlagName := "sysctl"
+ createFlags.StringSliceVar(
+ &cf.Sysctl,
+ sysctlFlagName, []string{},
+ "Sysctl options",
+ )
+ //TODO: Add function for sysctl completion.
+ _ = cmd.RegisterFlagCompletionFunc(sysctlFlagName, completion.AutocompleteNone)
- sysctlFlagName := "sysctl"
- createFlags.StringSliceVar(
- &cf.Sysctl,
- sysctlFlagName, []string{},
- "Sysctl options",
- )
- //TODO: Add function for sysctl completion.
- _ = cmd.RegisterFlagCompletionFunc(sysctlFlagName, completion.AutocompleteNone)
-
- securityOptFlagName := "security-opt"
- createFlags.StringArrayVar(
- &cf.SecurityOpt,
- securityOptFlagName, []string{},
- "Security Options",
- )
- _ = cmd.RegisterFlagCompletionFunc(securityOptFlagName, AutocompleteSecurityOption)
-
- subgidnameFlagName := "subgidname"
- createFlags.StringVar(
- &cf.SubUIDName,
- subgidnameFlagName, "",
- "Name of range listed in /etc/subgid for use in user namespace",
- )
- _ = cmd.RegisterFlagCompletionFunc(subgidnameFlagName, completion.AutocompleteSubgidName)
+ securityOptFlagName := "security-opt"
+ createFlags.StringArrayVar(
+ &cf.SecurityOpt,
+ securityOptFlagName, []string{},
+ "Security Options",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(securityOptFlagName, AutocompleteSecurityOption)
- subuidnameFlagName := "subuidname"
- createFlags.StringVar(
- &cf.SubGIDName,
- subuidnameFlagName, "",
- "Name of range listed in /etc/subuid for use in user namespace",
- )
- _ = cmd.RegisterFlagCompletionFunc(subuidnameFlagName, completion.AutocompleteSubuidName)
+ subgidnameFlagName := "subgidname"
+ createFlags.StringVar(
+ &cf.SubUIDName,
+ subgidnameFlagName, "",
+ "Name of range listed in /etc/subgid for use in user namespace",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(subgidnameFlagName, completion.AutocompleteSubgidName)
- gidmapFlagName := "gidmap"
- createFlags.StringSliceVar(
- &cf.GIDMap,
- gidmapFlagName, []string{},
- "GID map to use for the user namespace",
- )
- _ = cmd.RegisterFlagCompletionFunc(gidmapFlagName, completion.AutocompleteNone)
+ subuidnameFlagName := "subuidname"
+ createFlags.StringVar(
+ &cf.SubGIDName,
+ subuidnameFlagName, "",
+ "Name of range listed in /etc/subuid for use in user namespace",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(subuidnameFlagName, completion.AutocompleteSubuidName)
- uidmapFlagName := "uidmap"
- createFlags.StringSliceVar(
- &cf.UIDMap,
- uidmapFlagName, []string{},
- "UID map to use for the user namespace",
- )
- _ = cmd.RegisterFlagCompletionFunc(uidmapFlagName, completion.AutocompleteNone)
+ gidmapFlagName := "gidmap"
+ createFlags.StringSliceVar(
+ &cf.GIDMap,
+ gidmapFlagName, []string{},
+ "GID map to use for the user namespace",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(gidmapFlagName, completion.AutocompleteNone)
- usernsFlagName := "userns"
- createFlags.String(
- usernsFlagName, os.Getenv("PODMAN_USERNS"),
- "User namespace to use",
- )
- _ = cmd.RegisterFlagCompletionFunc(usernsFlagName, AutocompleteUserNamespace)
+ uidmapFlagName := "uidmap"
+ createFlags.StringSliceVar(
+ &cf.UIDMap,
+ uidmapFlagName, []string{},
+ "UID map to use for the user namespace",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(uidmapFlagName, completion.AutocompleteNone)
- cgroupParentFlagName := "cgroup-parent"
- createFlags.StringVar(
- &cf.CgroupParent,
- cgroupParentFlagName, "",
- "Optional parent cgroup for the container",
- )
- _ = cmd.RegisterFlagCompletionFunc(cgroupParentFlagName, completion.AutocompleteDefault)
+ usernsFlagName := "userns"
+ createFlags.String(
+ usernsFlagName, os.Getenv("PODMAN_USERNS"),
+ "User namespace to use",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(usernsFlagName, AutocompleteUserNamespace)
- conmonPidfileFlagName := ""
- if !isInfra {
- conmonPidfileFlagName = "conmon-pidfile"
- } else {
- conmonPidfileFlagName = "infra-conmon-pidfile"
- }
- createFlags.StringVar(
- &cf.ConmonPIDFile,
- conmonPidfileFlagName, "",
- "Path to the file that will receive the PID of conmon",
- )
- _ = cmd.RegisterFlagCompletionFunc(conmonPidfileFlagName, completion.AutocompleteDefault)
+ cgroupParentFlagName := "cgroup-parent"
+ createFlags.StringVar(
+ &cf.CgroupParent,
+ cgroupParentFlagName, "",
+ "Optional parent cgroup for the container",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cgroupParentFlagName, completion.AutocompleteDefault)
+ conmonPidfileFlagName := ""
+ if !isInfra {
+ conmonPidfileFlagName = "conmon-pidfile"
+ } else {
+ conmonPidfileFlagName = "infra-conmon-pidfile"
+ }
+ createFlags.StringVar(
+ &cf.ConmonPIDFile,
+ conmonPidfileFlagName, "",
+ "Path to the file that will receive the PID of conmon",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(conmonPidfileFlagName, completion.AutocompleteDefault)
- cpusFlagName := "cpus"
- createFlags.Float64Var(
- &cf.CPUS,
- cpusFlagName, 0,
- "Number of CPUs. The default is 0.000 which means no limit",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
+ entrypointFlagName := ""
+ if !isInfra {
+ entrypointFlagName = "entrypoint"
+ } else {
+ entrypointFlagName = "infra-command"
+ }
- cpusetCpusFlagName := "cpuset-cpus"
- createFlags.StringVar(
- &cf.CPUSetCPUs,
- cpusetCpusFlagName, "",
- "CPUs in which to allow execution (0-3, 0,1)",
- )
- _ = cmd.RegisterFlagCompletionFunc(cpusetCpusFlagName, completion.AutocompleteNone)
+ createFlags.String(entrypointFlagName, "",
+ "Overwrite the default ENTRYPOINT of the image",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(entrypointFlagName, completion.AutocompleteNone)
- entrypointFlagName := ""
- if !isInfra {
- entrypointFlagName = "entrypoint"
- } else {
- entrypointFlagName = "infra-command"
- }
+ hostnameFlagName := "hostname"
+ createFlags.StringVarP(
+ &cf.Hostname,
+ hostnameFlagName, "h", "",
+ "Set container hostname",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(hostnameFlagName, completion.AutocompleteNone)
- createFlags.String(entrypointFlagName, "",
- "Overwrite the default ENTRYPOINT of the image",
- )
- _ = cmd.RegisterFlagCompletionFunc(entrypointFlagName, completion.AutocompleteNone)
+ labelFlagName := "label"
+ createFlags.StringArrayVarP(
+ &cf.Label,
+ labelFlagName, "l", []string{},
+ "Set metadata on container",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(labelFlagName, completion.AutocompleteNone)
- hostnameFlagName := "hostname"
- createFlags.StringVarP(
- &cf.Hostname,
- hostnameFlagName, "h", "",
- "Set container hostname",
- )
- _ = cmd.RegisterFlagCompletionFunc(hostnameFlagName, completion.AutocompleteNone)
+ labelFileFlagName := "label-file"
+ createFlags.StringSliceVar(
+ &cf.LabelFile,
+ labelFileFlagName, []string{},
+ "Read in a line delimited file of labels",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(labelFileFlagName, completion.AutocompleteDefault)
- labelFlagName := "label"
- createFlags.StringArrayVarP(
- &cf.Label,
- labelFlagName, "l", []string{},
- "Set metadata on container",
- )
- _ = cmd.RegisterFlagCompletionFunc(labelFlagName, completion.AutocompleteNone)
+ if isInfra {
+ nameFlagName := "infra-name"
+ createFlags.StringVar(
+ &cf.Name,
+ nameFlagName, "",
+ "Assign a name to the container",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone)
+ }
- labelFileFlagName := "label-file"
- createFlags.StringSliceVar(
- &cf.LabelFile,
- labelFileFlagName, []string{},
- "Read in a line delimited file of labels",
- )
- _ = cmd.RegisterFlagCompletionFunc(labelFileFlagName, completion.AutocompleteDefault)
+ createFlags.Bool(
+ "help", false, "",
+ )
- nameFlagName := ""
- if !isInfra {
- nameFlagName = "name"
+ pidFlagName := "pid"
createFlags.StringVar(
- &cf.Name,
- nameFlagName, "",
- "Assign a name to the container",
+ &cf.PID,
+ pidFlagName, "",
+ "PID namespace to use",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(pidFlagName, AutocompleteNamespace)
+
+ volumeDesciption := "Bind mount a volume into the container"
+ if registry.IsRemote() {
+ volumeDesciption = "Bind mount a volume into the container. Volume source will be on the server machine, not the client"
+ }
+ volumeFlagName := "volume"
+ createFlags.StringArrayVarP(
+ &cf.Volume,
+ volumeFlagName, "v", volumes(),
+ volumeDesciption,
+ )
+ _ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
+
+ deviceFlagName := "device"
+ createFlags.StringSliceVar(
+ &cf.Devices,
+ deviceFlagName, devices(),
+ "Add a host device to the container",
)
- } else {
- nameFlagName = "infra-name"
+ _ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
+
+ deviceReadBpsFlagName := "device-read-bps"
+ createFlags.StringSliceVar(
+ &cf.DeviceReadBPs,
+ deviceReadBpsFlagName, []string{},
+ "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(deviceReadBpsFlagName, completion.AutocompleteDefault)
+
+ volumesFromFlagName := "volumes-from"
+ createFlags.StringArrayVar(
+ &cf.VolumesFrom,
+ volumesFromFlagName, []string{},
+ "Mount volumes from the specified container(s)",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(volumesFromFlagName, AutocompleteContainers)
+ }
+ if clone || !isInfra { // clone and create only flags, we need this level of separation so clone does not pick up all of the flags
+ nameFlagName := "name"
createFlags.StringVar(
&cf.Name,
nameFlagName, "",
"Assign a name to the container",
)
- }
- _ = cmd.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone)
+ _ = cmd.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone)
- createFlags.Bool(
- "help", false, "",
- )
+ cpuPeriodFlagName := "cpu-period"
+ createFlags.Uint64Var(
+ &cf.CPUPeriod,
+ cpuPeriodFlagName, 0,
+ "Limit the CPU CFS (Completely Fair Scheduler) period",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cpuPeriodFlagName, completion.AutocompleteNone)
- pidFlagName := "pid"
- createFlags.StringVar(
- &cf.PID,
- pidFlagName, "",
- "PID namespace to use",
- )
- _ = cmd.RegisterFlagCompletionFunc(pidFlagName, AutocompleteNamespace)
+ cpuQuotaFlagName := "cpu-quota"
+ createFlags.Int64Var(
+ &cf.CPUQuota,
+ cpuQuotaFlagName, 0,
+ "Limit the CPU CFS (Completely Fair Scheduler) quota",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cpuQuotaFlagName, completion.AutocompleteNone)
- volumeDesciption := "Bind mount a volume into the container"
- if registry.IsRemote() {
- volumeDesciption = "Bind mount a volume into the container. Volume source will be on the server machine, not the client"
- }
- volumeFlagName := "volume"
- createFlags.StringArrayVarP(
- &cf.Volume,
- volumeFlagName, "v", volumes(),
- volumeDesciption,
- )
- _ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
+ cpuRtPeriodFlagName := "cpu-rt-period"
+ createFlags.Uint64Var(
+ &cf.CPURTPeriod,
+ cpuRtPeriodFlagName, 0,
+ "Limit the CPU real-time period in microseconds",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cpuRtPeriodFlagName, completion.AutocompleteNone)
- deviceFlagName := "device"
- createFlags.StringSliceVar(
- &cf.Devices,
- deviceFlagName, devices(),
- "Add a host device to the container",
- )
- _ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
+ cpuRtRuntimeFlagName := "cpu-rt-runtime"
+ createFlags.Int64Var(
+ &cf.CPURTRuntime,
+ cpuRtRuntimeFlagName, 0,
+ "Limit the CPU real-time runtime in microseconds",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cpuRtRuntimeFlagName, completion.AutocompleteNone)
+
+ cpuSharesFlagName := "cpu-shares"
+ createFlags.Uint64Var(
+ &cf.CPUShares,
+ cpuSharesFlagName, 0,
+ "CPU shares (relative weight)",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cpuSharesFlagName, completion.AutocompleteNone)
+
+ cpusetMemsFlagName := "cpuset-mems"
+ createFlags.StringVar(
+ &cf.CPUSetMems,
+ cpusetMemsFlagName, "",
+ "Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone)
- deviceReadBpsFlagName := "device-read-bps"
- createFlags.StringSliceVar(
- &cf.DeviceReadBPs,
- deviceReadBpsFlagName, []string{},
- "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
+ memoryFlagName := "memory"
+ createFlags.StringVarP(
+ &cf.Memory,
+ memoryFlagName, "m", "",
+ "Memory limit "+sizeWithUnitFormat,
+ )
+ _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
+ }
+ //anyone can use these
+ cpusFlagName := "cpus"
+ createFlags.Float64Var(
+ &cf.CPUS,
+ cpusFlagName, 0,
+ "Number of CPUs. The default is 0.000 which means no limit",
)
- _ = cmd.RegisterFlagCompletionFunc(deviceReadBpsFlagName, completion.AutocompleteDefault)
+ _ = cmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
- volumesFromFlagName := "volumes-from"
- createFlags.StringArrayVar(
- &cf.VolumesFrom,
- volumesFromFlagName, []string{},
- "Mount volumes from the specified container(s)",
+ cpusetCpusFlagName := "cpuset-cpus"
+ createFlags.StringVar(
+ &cf.CPUSetCPUs,
+ cpusetCpusFlagName, "",
+ "CPUs in which to allow execution (0-3, 0,1)",
)
- _ = cmd.RegisterFlagCompletionFunc(volumesFromFlagName, AutocompleteContainers)
+ _ = cmd.RegisterFlagCompletionFunc(cpusetCpusFlagName, completion.AutocompleteNone)
}
diff --git a/cmd/podman/containers/clone.go b/cmd/podman/containers/clone.go
new file mode 100644
index 000000000..d095d24ba
--- /dev/null
+++ b/cmd/podman/containers/clone.go
@@ -0,0 +1,80 @@
+package containers
+
+import (
+ "fmt"
+
+ "github.com/containers/podman/v4/cmd/podman/common"
+ "github.com/containers/podman/v4/cmd/podman/registry"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ cloneDescription = `Creates a copy of an existing container.`
+
+ containerCloneCommand = &cobra.Command{
+ Use: "clone [options] CONTAINER NAME IMAGE",
+ Short: "Clone an existing container",
+ Long: cloneDescription,
+ RunE: clone,
+ Args: cobra.RangeArgs(1, 3),
+ ValidArgsFunction: common.AutocompleteClone,
+ Example: `podman container clone container_name new_name image_name`,
+ }
+)
+
+var (
+ ctrClone entities.ContainerCloneOptions
+)
+
+func cloneFlags(cmd *cobra.Command) {
+ flags := cmd.Flags()
+
+ destroyFlagName := "destroy"
+ flags.BoolVar(&ctrClone.Destroy, destroyFlagName, false, "destroy the original container")
+
+ runFlagName := "run"
+ flags.BoolVar(&ctrClone.Run, runFlagName, false, "run the new container")
+
+ common.DefineCreateFlags(cmd, &ctrClone.CreateOpts, false, true)
+}
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Command: containerCloneCommand,
+ Parent: containerCmd,
+ })
+
+ cloneFlags(containerCloneCommand)
+}
+
+func clone(cmd *cobra.Command, args []string) error {
+ switch len(args) {
+ case 0:
+ return errors.Wrapf(define.ErrInvalidArg, "Must Specify at least 1 argument")
+ case 2:
+ ctrClone.CreateOpts.Name = args[1]
+ case 3:
+ ctrClone.CreateOpts.Name = args[1]
+ ctrClone.Image = args[2]
+ rawImageName := ""
+ if !cliVals.RootFS {
+ rawImageName = args[0]
+ name, err := PullImage(ctrClone.Image, ctrClone.CreateOpts)
+ if err != nil {
+ return err
+ }
+ ctrClone.Image = name
+ ctrClone.RawImageName = rawImageName
+ }
+ }
+ ctrClone.ID = args[0]
+ ctrClone.CreateOpts.IsClone = true
+ rep, err := registry.ContainerEngine().ContainerClone(registry.GetContext(), ctrClone)
+ if err != nil {
+ return err
+ }
+ fmt.Println(rep.Id)
+ return nil
+}
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 89d2e5515..de1a41e25 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -70,7 +70,7 @@ func createFlags(cmd *cobra.Command) {
)
flags.SetInterspersed(false)
- common.DefineCreateFlags(cmd, &cliVals, false)
+ common.DefineCreateFlags(cmd, &cliVals, false, false)
common.DefineNetFlags(cmd)
flags.SetNormalizeFunc(utils.AliasFlags)
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index 5a64b8c32..1d98eb3b3 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -61,7 +61,7 @@ func runFlags(cmd *cobra.Command) {
flags := cmd.Flags()
flags.SetInterspersed(false)
- common.DefineCreateFlags(cmd, &cliVals, false)
+ common.DefineCreateFlags(cmd, &cliVals, false, false)
common.DefineNetFlags(cmd)
flags.SetNormalizeFunc(utils.AliasFlags)
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 1cd36008e..ab3a6d578 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -63,7 +63,7 @@ func init() {
})
flags := createCommand.Flags()
flags.SetInterspersed(false)
- common.DefineCreateFlags(createCommand, &infraOptions, true)
+ common.DefineCreateFlags(createCommand, &infraOptions, true, false)
common.DefineNetFlags(createCommand)
flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")