From 4855998f1cf533b27e48b2ded5541841fe6a3ea6 Mon Sep 17 00:00:00 2001 From: umohnani8 Date: Mon, 11 Jun 2018 15:27:42 -0400 Subject: Add --volumes-from flag to podman run and create podman now supports --volumes-from flag, which allows users to add all the volumes an existing container has to a new one. Signed-off-by: umohnani8 Closes: #931 Approved by: mheon --- pkg/spec/createconfig.go | 65 +++++++++++++++++++++++++++++++++++++++++++----- pkg/spec/spec.go | 3 +++ 2 files changed, 62 insertions(+), 6 deletions(-) (limited to 'pkg') diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 48343c3a4..a39f4875c 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -1,6 +1,7 @@ package createconfig import ( + "encoding/json" "os" "strconv" "strings" @@ -123,14 +124,16 @@ type CreateConfig struct { User string //user UtsMode container.UTSMode //uts Volumes []string //volume - WorkDir string //workdir - MountLabel string //SecurityOpts - ProcessLabel string //SecurityOpts - NoNewPrivs bool //SecurityOpts - ApparmorProfile string //SecurityOpts - SeccompProfilePath string //SecurityOpts + VolumesFrom []string + WorkDir string //workdir + MountLabel string //SecurityOpts + ProcessLabel string //SecurityOpts + NoNewPrivs bool //SecurityOpts + ApparmorProfile string //SecurityOpts + SeccompProfilePath string //SecurityOpts SecurityOpts []string Rootfs string + LocalVolumes []string //Keeps track of the built-in volumes of container used in the --volumes-from flag } func u32Ptr(i int64) *uint32 { u := uint32(i); return &u } @@ -215,6 +218,52 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e return m, nil } +// GetVolumesFrom reads the create-config artifact of the container to get volumes from +// and adds it to c.Volumes of the curent container. +func (c *CreateConfig) GetVolumesFrom() error { + var options string + for _, vol := range c.VolumesFrom { + splitVol := strings.SplitN(vol, ":", 2) + if len(splitVol) == 2 { + options = splitVol[1] + } + ctr, err := c.Runtime.LookupContainer(splitVol[0]) + if err != nil { + return errors.Wrapf(err, "error looking up container %q", splitVol[0]) + } + var createArtifact CreateConfig + artifact, err := ctr.GetArtifact("create-config") + if err != nil { + return errors.Wrapf(err, "error getting create-config artifact for %q", splitVol[0]) + } + if err := json.Unmarshal(artifact, &createArtifact); err != nil { + return err + } + + for key := range createArtifact.BuiltinImgVolumes { + c.LocalVolumes = append(c.LocalVolumes, key) + } + + for _, i := range createArtifact.Volumes { + // Volumes format is host-dir:ctr-dir[:options], so get the host and ctr dir + // and add on the options given by the user to the flag. + spliti := strings.SplitN(i, ":", 3) + // Throw error if mounting volume from container with Z option (private label) + // Override this by adding 'z' to options. + if len(spliti) > 2 && strings.Contains(spliti[2], "Z") && !strings.Contains(options, "z") { + return errors.Errorf("volume mounted with private option 'Z' in %q. Use option 'z' to mount in current container", ctr.ID()) + } + if options == "" { + // Mount the volumes with the default options + c.Volumes = append(c.Volumes, createArtifact.Volumes...) + } else { + c.Volumes = append(c.Volumes, spliti[0]+":"+spliti[1]+":"+options) + } + } + } + return nil +} + //GetTmpfsMounts takes user provided input for Tmpfs mounts and creates Mount structs func (c *CreateConfig) GetTmpfsMounts() []spec.Mount { var m []spec.Mount @@ -289,6 +338,10 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib options = append(options, libpod.WithUserVolumes(volumes)) } + if len(c.LocalVolumes) != 0 { + options = append(options, libpod.WithLocalVolumes(c.LocalVolumes)) + } + if len(c.Command) != 0 { options = append(options, libpod.WithCommand(c.Command)) } diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index dc23c129c..ffa242675 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -248,6 +248,9 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } // BIND MOUNTS + if err := config.GetVolumesFrom(); err != nil { + return nil, errors.Wrap(err, "error getting volume mounts from --volumes-from flag") + } mounts, err := config.GetVolumeMounts(configSpec.Mounts) if err != nil { return nil, errors.Wrapf(err, "error getting volume mounts") -- cgit v1.2.3-54-g00ecf