summaryrefslogtreecommitdiff
path: root/pkg/specgen/generate/container.go
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 /pkg/specgen/generate/container.go
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 'pkg/specgen/generate/container.go')
-rw-r--r--pkg/specgen/generate/container.go150
1 files changed, 150 insertions, 0 deletions
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index a4d862a60..64669f34d 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -2,6 +2,7 @@ package generate
import (
"context"
+ "encoding/json"
"os"
"strings"
"time"
@@ -335,3 +336,152 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
}
return nil
}
+
+// 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)
+ if err != nil {
+ return nil, err
+ }
+ conf := c.Config()
+
+ tmpSystemd := conf.Systemd
+ tmpMounts := conf.Mounts
+
+ conf.Systemd = nil
+ conf.Mounts = []string{}
+
+ specg.Pod = conf.Pod
+
+ matching, err := json.Marshal(conf)
+ if err != nil {
+ return nil, err
+ }
+
+ err = json.Unmarshal(matching, specg)
+ if err != nil {
+ return nil, err
+ }
+ conf.Systemd = tmpSystemd
+ conf.Mounts = tmpMounts
+
+ if conf.Spec != nil && conf.Spec.Linux != nil && conf.Spec.Linux.Resources != nil {
+ if specg.ResourceLimits == nil {
+ specg.ResourceLimits = conf.Spec.Linux.Resources
+ }
+ }
+
+ nameSpaces := []string{"pid", "net", "cgroup", "ipc", "uts", "user"}
+ containers := []string{conf.PIDNsCtr, conf.NetNsCtr, conf.CgroupNsCtr, conf.IPCNsCtr, conf.UTSNsCtr, conf.UserNsCtr}
+ place := []*specgen.Namespace{&specg.PidNS, &specg.NetNS, &specg.CgroupNS, &specg.IpcNS, &specg.UtsNS, &specg.UserNS}
+ for i, ns := range containers {
+ if len(ns) > 0 {
+ ns := specgen.Namespace{NSMode: specgen.FromContainer, Value: ns}
+ place[i] = &ns
+ } else {
+ switch nameSpaces[i] {
+ case "pid":
+ specg.PidNS = specgen.Namespace{NSMode: specgen.Default} //default
+ case "net":
+ switch {
+ case conf.NetMode.IsBridge():
+ toExpose := make(map[uint16]string, len(conf.ExposedPorts))
+ for _, expose := range []map[uint16][]string{conf.ExposedPorts} {
+ for port, proto := range expose {
+ toExpose[port] = strings.Join(proto, ",")
+ }
+ }
+ specg.Expose = toExpose
+ specg.PortMappings = conf.PortMappings
+ specg.NetNS = specgen.Namespace{NSMode: specgen.Bridge}
+ case conf.NetMode.IsSlirp4netns():
+ toExpose := make(map[uint16]string, len(conf.ExposedPorts))
+ for _, expose := range []map[uint16][]string{conf.ExposedPorts} {
+ for port, proto := range expose {
+ toExpose[port] = strings.Join(proto, ",")
+ }
+ }
+ specg.Expose = toExpose
+ specg.PortMappings = conf.PortMappings
+ netMode := strings.Split(string(conf.NetMode), ":")
+ var val string
+ if len(netMode) > 1 {
+ val = netMode[1]
+ }
+ specg.NetNS = specgen.Namespace{NSMode: specgen.Slirp, Value: val}
+ case conf.NetMode.IsPrivate():
+ specg.NetNS = specgen.Namespace{NSMode: specgen.Private}
+ case conf.NetMode.IsDefault():
+ specg.NetNS = specgen.Namespace{NSMode: specgen.Default}
+ case conf.NetMode.IsUserDefined():
+ specg.NetNS = specgen.Namespace{NSMode: specgen.Path, Value: strings.Split(string(conf.NetMode), ":")[1]}
+ case conf.NetMode.IsContainer():
+ specg.NetNS = specgen.Namespace{NSMode: specgen.FromContainer, Value: strings.Split(string(conf.NetMode), ":")[1]}
+ case conf.NetMode.IsPod():
+ specg.NetNS = specgen.Namespace{NSMode: specgen.FromPod, Value: strings.Split(string(conf.NetMode), ":")[1]}
+ }
+ case "cgroup":
+ specg.CgroupNS = specgen.Namespace{NSMode: specgen.Default} //default
+ case "ipc":
+ if conf.ShmDir == "/dev/shm" {
+ specg.IpcNS = specgen.Namespace{NSMode: specgen.Host}
+ } else {
+ specg.IpcNS = specgen.Namespace{NSMode: specgen.Default} //default
+ }
+ case "uts":
+ specg.UtsNS = specgen.Namespace{NSMode: specgen.Default} //default
+ case "user":
+ if conf.AddCurrentUserPasswdEntry {
+ specg.UserNS = specgen.Namespace{NSMode: specgen.KeepID}
+ } else {
+ specg.UserNS = specgen.Namespace{NSMode: specgen.Default} //default
+ }
+ }
+ }
+ }
+
+ specg.IDMappings = &conf.IDMappings
+ specg.ContainerCreateCommand = conf.CreateCommand
+ if len(specg.Rootfs) == 0 {
+ specg.Rootfs = conf.Rootfs
+ }
+ if len(specg.Image) == 0 {
+ specg.Image = conf.RootfsImageID
+ }
+ var named []*specgen.NamedVolume
+ if len(conf.NamedVolumes) != 0 {
+ for _, v := range conf.NamedVolumes {
+ named = append(named, &specgen.NamedVolume{
+ Name: v.Name,
+ Dest: v.Dest,
+ Options: v.Options,
+ })
+ }
+ }
+ specg.Volumes = named
+ var image []*specgen.ImageVolume
+ if len(conf.ImageVolumes) != 0 {
+ for _, v := range conf.ImageVolumes {
+ image = append(image, &specgen.ImageVolume{
+ Source: v.Source,
+ Destination: v.Dest,
+ ReadWrite: v.ReadWrite,
+ })
+ }
+ }
+ specg.ImageVolumes = image
+ var overlay []*specgen.OverlayVolume
+ if len(conf.OverlayVolumes) != 0 {
+ for _, v := range conf.OverlayVolumes {
+ overlay = append(overlay, &specgen.OverlayVolume{
+ Source: v.Source,
+ Destination: v.Dest,
+ Options: v.Options,
+ })
+ }
+ }
+ specg.OverlayVolumes = overlay
+ specg.Mounts = conf.Spec.Mounts
+ specg.HostDeviceList = conf.DeviceHostSrc
+ return c, nil
+}