diff options
-rw-r--r-- | cmd/podman/common/create.go | 15 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-create.1.md | 33 | ||||
-rw-r--r-- | libpod/define/pod_inspect.go | 2 | ||||
-rw-r--r-- | libpod/pod.go | 16 | ||||
-rw-r--r-- | libpod/pod_api.go | 1 | ||||
-rw-r--r-- | pkg/api/server/docs.go | 9 | ||||
-rw-r--r-- | pkg/domain/entities/pods.go | 4 | ||||
-rw-r--r-- | pkg/specgen/generate/pod_create.go | 6 | ||||
-rw-r--r-- | pkg/specgen/podspecgen.go | 43 | ||||
-rw-r--r-- | test/e2e/events_test.go | 13 | ||||
-rw-r--r-- | test/e2e/pod_create_test.go | 33 |
11 files changed, 150 insertions, 25 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index e714b6785..a3ff37c19 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -656,14 +656,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(mountFlagName, AutocompleteMountFlag) - volumesFromFlagName := "volumes-from" - createFlags.StringArrayVar( - &cf.VolumesFrom, - volumesFromFlagName, []string{}, - "Mount volumes from the specified container(s)", - ) - _ = cmd.RegisterFlagCompletionFunc(volumesFromFlagName, AutocompleteContainers) - workdirFlagName := "workdir" createFlags.StringVarP( &cf.Workdir, @@ -877,4 +869,11 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, "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) } diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index 4c36c66ca..08ac19b8b 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -381,6 +381,39 @@ change propagation properties of source mount. Say `/` is source mount for Note: if the user only has access rights via a group, accessing the volume from inside a rootless pod will fail. +#### **--volumes-from**[=*CONTAINER*[:*OPTIONS*]] + +Mount volumes from the specified container(s). Used to share volumes between +containers and pods. The *options* is a comma-separated list with the following available elements: + +* **rw**|**ro** +* **z** + +Mounts already mounted volumes from a source container into another +pod. You must supply the source's container-id or container-name. +To share a volume, use the --volumes-from option when running +the target container. You can share volumes even if the source container +is not running. + +By default, Podman mounts the volumes in the same mode (read-write or +read-only) as it is mounted in the source container. +You can change this by adding a `ro` or `rw` _option_. + +Labeling systems like SELinux require that proper labels are placed on volume +content mounted into a pod. Without a label, the security system might +prevent the processes running inside the container from using the content. By +default, Podman does not change the labels set by the OS. + +To change a label in the pod context, you can add `z` to the volume mount. +This suffix tells Podman to relabel file objects on the shared volumes. The `z` +option tells Podman that two entities share the volume content. As a result, +Podman labels the content with a shared content label. Shared volume labels allow +all containers to read/write content. + +If the location of the volume from the source container overlaps with +data residing on a target pod, then the volume hides +that data on the target. + ## EXAMPLES diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go index bc2c1d81f..97e7ffdfb 100644 --- a/libpod/define/pod_inspect.go +++ b/libpod/define/pod_inspect.go @@ -63,6 +63,8 @@ type InspectPodData struct { Devices []InspectDevice `json:"devices,omitempty"` // BlkioDeviceReadBps contains the Read/Access limit for the pod's devices BlkioDeviceReadBps []InspectBlkioThrottleDevice `json:"device_read_bps,omitempty"` + // VolumesFrom contains the containers that the pod inherits mounts from + VolumesFrom []string `json:"volumes_from,omitempty"` } // InspectPodInfraConfig contains the configuration of the pod's infra diff --git a/libpod/pod.go b/libpod/pod.go index c0b0a974b..068a835f6 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "sort" + "strings" "time" "github.com/containers/podman/v3/libpod/define" @@ -200,6 +201,21 @@ func (p *Pod) UserNSMode() string { return "" } +// CPUQuota returns the pod CPU quota +func (p *Pod) VolumesFrom() []string { + if p.state.InfraContainerID == "" { + return nil + } + infra, err := p.runtime.GetContainer(p.state.InfraContainerID) + if err != nil { + return nil + } + if ctrs, ok := infra.config.Spec.Annotations[define.InspectAnnotationVolumesFrom]; ok { + return strings.Split(ctrs, ",") + } + return nil +} + // Labels returns the pod's labels func (p *Pod) Labels() map[string]string { labels := make(map[string]string) diff --git a/libpod/pod_api.go b/libpod/pod_api.go index 05349aff5..4ae02fb40 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -668,6 +668,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { Mounts: inspectMounts, Devices: devices, BlkioDeviceReadBps: deviceLimits, + VolumesFrom: p.VolumesFrom(), } return &inspectData, nil diff --git a/pkg/api/server/docs.go b/pkg/api/server/docs.go index bf15afbf9..83d9ef160 100644 --- a/pkg/api/server/docs.go +++ b/pkg/api/server/docs.go @@ -15,6 +15,15 @@ // NOTE: if you install the package podman-docker, it will create a symbolic // link for /run/docker.sock to /run/podman/podman.sock // +// NOTE: some fields in the API response JSON are set as omitempty, which means that +// if there is no value set for them, they will not show up in the API response. This +// is a feature to help reduce the size of the JSON responses returned via the API. +// +// NOTE: due to the limitations of [go-swagger](https://github.com/go-swagger/go-swagger), +// some field values that have a complex type show up as null in the docs as well as in the +// API responses. This is because the zero value for the field type is null. The field +// description in the docs will state what type the field is expected to be for such cases. +// // See podman-service(1) for more information. // // Quick Examples: diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 0356383ec..653f64b42 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -135,6 +135,7 @@ type PodCreateOptions struct { CpusetCpus string `json:"cpuset_cpus,omitempty"` Userns specgen.Namespace `json:"-"` Volume []string `json:"volume,omitempty"` + VolumesFrom []string `json:"volumes_from,omitempty"` } // PodLogsOptions describes the options to extract pod logs. @@ -251,7 +252,7 @@ type ContainerCreateOptions struct { UTS string Mount []string Volume []string `json:"volume,omitempty"` - VolumesFrom []string + VolumesFrom []string `json:"volumes_from,omitempty"` Workdir string SeccompPolicy string PidFile string @@ -308,6 +309,7 @@ func ToPodSpecGen(s specgen.PodSpecGenerator, p *PodCreateOptions) (*specgen.Pod s.InfraImage = p.InfraImage s.SharedNamespaces = p.Share s.PodCreateCommand = p.CreateCommand + s.VolumesFrom = p.VolumesFrom // Networking config diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index e523aef42..a4027eae7 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -59,6 +59,12 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) { if err != nil { return nil, err } + } else { + // SavePod is used to save the pod state and trigger a create event even if infra is not created + err := rt.SavePod(pod) + if err != nil { + return nil, err + } } return pod, nil } diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index ee4fbc13a..7713ea26c 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -72,22 +72,6 @@ type PodBasicConfig struct { // Any containers created within the pod will inherit the pod's userns settings. // Optional Userns Namespace `json:"userns,omitempty"` - // Mounts are mounts that will be added to the pod. - // These will supersede Image Volumes and VolumesFrom (WIP) volumes where - // there are conflicts. - // Optional. - Mounts []spec.Mount `json:"mounts,omitempty"` - // Volumes are named volumes that will be added to the pod. - // These will supersede Image Volumes and VolumesFrom (WIP) volumes where - // there are conflicts. - // Optional. - Volumes []*NamedVolume `json:"volumes,omitempty"` - // Overlay volumes are named volumes that will be added to the pod. - // Optional. - OverlayVolumes []*OverlayVolume `json:"overlay_volumes,omitempty"` - // Image volumes bind-mount a container-image mount into the pod's infra container. - // Optional. - ImageVolumes []*ImageVolume `json:"image_volumes,omitempty"` // Devices contains user specified Devices to be added to the Pod Devices []string `json:"pod_devices,omitempty"` } @@ -174,6 +158,32 @@ type PodNetworkConfig struct { NetworkOptions map[string][]string `json:"network_options,omitempty"` } +// PodStorageConfig contains all of the storage related options for the pod and its infra container. +type PodStorageConfig struct { + // Mounts are mounts that will be added to the pod. + // These will supersede Image Volumes and VolumesFrom volumes where + // there are conflicts. + // Optional. + Mounts []spec.Mount `json:"mounts,omitempty"` + // Volumes are named volumes that will be added to the pod. + // These will supersede Image Volumes and VolumesFrom volumes where + // there are conflicts. + // Optional. + Volumes []*NamedVolume `json:"volumes,omitempty"` + // Overlay volumes are named volumes that will be added to the pod. + // Optional. + OverlayVolumes []*OverlayVolume `json:"overlay_volumes,omitempty"` + // Image volumes bind-mount a container-image mount into the pod's infra container. + // Optional. + ImageVolumes []*ImageVolume `json:"image_volumes,omitempty"` + // VolumesFrom is a set of containers whose volumes will be added to + // this pod. The name or ID of the container must be provided, and + // may optionally be followed by a : and then one or more + // comma-separated options. Valid options are 'ro', 'rw', and 'z'. + // Options will be used for all volumes sourced from the container. + VolumesFrom []string `json:"volumes_from,omitempty"` +} + // PodCgroupConfig contains configuration options about a pod's cgroups. // This will be expanded in future updates to pods. type PodCgroupConfig struct { @@ -191,6 +201,7 @@ type PodSpecGenerator struct { PodNetworkConfig PodCgroupConfig PodResourceConfig + PodStorageConfig InfraContainerSpec *SpecGenerator `json:"-"` } diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go index 46ea10c56..ee0b8761a 100644 --- a/test/e2e/events_test.go +++ b/test/e2e/events_test.go @@ -199,4 +199,17 @@ var _ = Describe("Podman events", func() { wg.Wait() }) + + It("podman events pod creation", func() { + create := podmanTest.Podman([]string{"pod", "create", "--infra=false", "--name", "foobarpod"}) + create.WaitWithDefaultTimeout() + Expect(create).Should(Exit(0)) + id := create.OutputToString() + result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "pod=" + id}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).To(HaveLen(1)) + Expect(result.OutputToString()).To(ContainSubstring("create")) + }) + }) diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index e8bc871da..34e879ed4 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -924,4 +924,37 @@ ENTRYPOINT ["sleep","99999"] } }) + It("podman pod create --volumes-from", func() { + volName := "testVol" + volCreate := podmanTest.Podman([]string{"volume", "create", volName}) + volCreate.WaitWithDefaultTimeout() + Expect(volCreate).Should(Exit(0)) + ctrName := "testCtr" + ctrCreate := podmanTest.Podman([]string{"create", "--volume", volName + ":/tmp1", "--name", ctrName, ALPINE}) + ctrCreate.WaitWithDefaultTimeout() + Expect(ctrCreate).Should(Exit(0)) + ctrInspect := podmanTest.Podman([]string{"inspect", ctrName}) + ctrInspect.WaitWithDefaultTimeout() + Expect(ctrInspect).Should(Exit(0)) + data := ctrInspect.InspectContainerToJSON() + Expect(data[0].Mounts[0].Name).To(Equal(volName)) + podName := "testPod" + podCreate := podmanTest.Podman([]string{"pod", "create", "--volumes-from", ctrName, "--name", podName}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + podInspect := podmanTest.Podman([]string{"pod", "inspect", podName}) + podInspect.WaitWithDefaultTimeout() + Expect(podInspect).Should(Exit(0)) + podData := podInspect.InspectPodToJSON() + Expect(podData.Mounts[0].Name).To(Equal(volName)) + + ctr2 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "sh", "-c", "echo hello >> " + "/tmp1/test"}) + ctr2.WaitWithDefaultTimeout() + Expect(ctr2).Should(Exit(0)) + + ctr3 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "cat", "/tmp1/test"}) + ctr3.WaitWithDefaultTimeout() + Expect(ctr3.OutputToString()).To(ContainSubstring("hello")) + }) + }) |