summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/create.go15
-rw-r--r--docs/source/markdown/podman-pod-create.1.md33
-rw-r--r--libpod/define/pod_inspect.go2
-rw-r--r--libpod/pod.go16
-rw-r--r--libpod/pod_api.go1
-rw-r--r--pkg/api/server/docs.go9
-rw-r--r--pkg/domain/entities/pods.go4
-rw-r--r--pkg/specgen/generate/pod_create.go6
-rw-r--r--pkg/specgen/podspecgen.go43
-rw-r--r--test/e2e/events_test.go13
-rw-r--r--test/e2e/pod_create_test.go33
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"))
+ })
+
})