diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2022-02-22 10:10:49 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-22 10:10:49 -0500 |
commit | fab82a7c9ca3821c2b4496f9e9f6bfc8b2aff53d (patch) | |
tree | 7bafc1608557fd8f98970eaece2225b0d4820edb /pkg/specgen/generate/container.go | |
parent | 948dfc6f02b7b15547a42e39760b04eca20b193d (diff) | |
parent | 94df7015121759ce69f35f7e7735aa2e4a2dc71a (diff) | |
download | podman-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.go | 150 |
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 +} |