From 45b9e17d7c840e10a61d9e0c2b0333fb1aa18b18 Mon Sep 17 00:00:00 2001 From: Ingo Becker Date: Thu, 22 Dec 2022 11:20:27 +0100 Subject: [PATCH] quadlet: Add device support for .volume files The Device, Type, Copy and Options keys are now supported in quadlet .volume files. This allows users to create filesystem based volumes with quadlets .volume files. Signed-off-by: Ingo Becker Signed-off-by: Ygal Blum --- docs/source/markdown/podman-systemd.unit.5.md | 17 ++++++ pkg/systemd/quadlet/quadlet.go | 52 +++++++++++++++++-- test/e2e/quadlet/device-copy.volume | 13 +++++ test/e2e/quadlet/device.volume | 13 +++++ test/e2e/quadlet_test.go | 1 + 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 test/e2e/quadlet/device-copy.volume create mode 100644 test/e2e/quadlet/device.volume diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md index df0fca37c3..b87cd6af18 100644 --- a/docs/source/markdown/podman-systemd.unit.5.md +++ b/docs/source/markdown/podman-systemd.unit.5.md @@ -412,6 +412,23 @@ Set one or more OCI labels on the volume. The format is a list of This key can be listed multiple times. +#### `Device=` + +The path of a device which should be mounted for the volume. + +#### `Type=` + +The filesystem type of `Device` as used by the **mount(8)** commands `-t` option. + +#### `Options=` + +The mount options to use for a filesystem as used by the **mount(8)** command `-o` option. + +#### `Copy=` (default to `yes`) + +If enabled, the content of the image located at the mountpoint of the volume is copied into the +volume on the first run. + ### Network units Network files are named with a `.network` extension and contain a section `[Network]` describing the diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go index 5254e2c956..d138a0dd15 100644 --- a/pkg/systemd/quadlet/quadlet.go +++ b/pkg/systemd/quadlet/quadlet.go @@ -50,6 +50,10 @@ const ( KeyPublishPort = "PublishPort" KeyUser = "User" KeyGroup = "Group" + KeyDevice = "Device" + KeyType = "Type" + KeyOptions = "Options" + KeyCopy = "Copy" KeyVolume = "Volume" KeyPodmanArgs = "PodmanArgs" KeyLabel = "Label" @@ -111,9 +115,13 @@ var ( // Supported keys in "Volume" group supportedVolumeKeys = map[string]bool{ - KeyUser: true, - KeyGroup: true, - KeyLabel: true, + KeyUser: true, + KeyGroup: true, + KeyDevice: true, + KeyType: true, + KeyOptions: true, + KeyCopy: true, + KeyLabel: true, } // Supported keys in "Volume" group @@ -622,6 +630,44 @@ func ConvertVolume(volume *parser.UnitFile, name string) (*parser.UnitFile, erro opts.WriteString(fmt.Sprintf("gid=%d", gid)) } + copy, ok := volume.LookupBoolean(VolumeGroup, KeyCopy) + if ok { + if copy { + podman.add("--opt", "copy") + } else { + podman.add("--opt", "nocopy") + } + } + + devValid := false + + dev, ok := volume.Lookup(VolumeGroup, KeyDevice) + if ok && len(dev) != 0 { + podman.add("--opt", fmt.Sprintf("device=%s", dev)) + devValid = true + } + + devType, ok := volume.Lookup(VolumeGroup, KeyType) + if ok && len(devType) != 0 { + if devValid { + podman.add("--opt", fmt.Sprintf("type=%s", devType)) + } else { + return nil, fmt.Errorf("key Type can't be used without Device") + } + } + + mountOpts, ok := volume.Lookup(VolumeGroup, KeyOptions) + if ok && len(mountOpts) != 0 { + if devValid { + if opts.Len() > 2 { + opts.WriteString(",") + } + opts.WriteString(mountOpts) + } else { + return nil, fmt.Errorf("key Options can't be used without Device") + } + } + if opts.Len() > 2 { podman.add("--opt", opts.String()) } diff --git a/test/e2e/quadlet/device-copy.volume b/test/e2e/quadlet/device-copy.volume new file mode 100644 index 0000000000..0e7405e222 --- /dev/null +++ b/test/e2e/quadlet/device-copy.volume @@ -0,0 +1,13 @@ +## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd " +## assert-key-contains Service ExecStart " --opt type=btrfs " +## assert-key-contains Service ExecStart " --opt device=/dev/vda1 " +## assert-key-contains Service ExecStart " --opt copy " + +[Volume] +# Test usernames too +User=root +Group=11 +Device=/dev/vda1 +Type=btrfs +Options=rw,compress=zstd +Copy=yes diff --git a/test/e2e/quadlet/device.volume b/test/e2e/quadlet/device.volume new file mode 100644 index 0000000000..4e742a38c4 --- /dev/null +++ b/test/e2e/quadlet/device.volume @@ -0,0 +1,13 @@ +## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd " +## assert-key-contains Service ExecStart " --opt type=btrfs " +## assert-key-contains Service ExecStart " --opt device=/dev/vda1 " +## assert-key-contains Service ExecStart " --opt nocopy " + +[Volume] +# Test usernames too +User=root +Group=11 +Device=/dev/vda1 +Type=btrfs +Options=rw,compress=zstd +Copy=no diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index a4a1b7f219..69324720c2 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -482,6 +482,7 @@ var _ = Describe("quadlet system generator", func() { Entry("basic.volume", "basic.volume"), Entry("label.volume", "label.volume"), Entry("uid.volume", "uid.volume"), + Entry("device.volume", "device-copy.volume"), Entry("Basic kube", "basic.kube"), Entry("Syslog Identifier", "syslog.identifier.kube"),