From 443f8d89c94a69ec857156ed33eb37fb7f1b110b Mon Sep 17 00:00:00 2001
From: Cedric Staniewski <cedric@gmx.ca>
Date: Thu, 30 Mar 2023 22:22:09 +0200
Subject: [PATCH] quadlet: implement `Tmpfs` option

This commit adds an quadlet option `Tmpfs` which can be used to mount a
tmpfs in the container.

Closes #17907

Signed-off-by: Cedric Staniewski <cedric@gmx.ca>
---
 docs/source/markdown/podman-systemd.unit.5.md |  8 ++++++
 pkg/systemd/quadlet/quadlet.go                | 11 ++++++++
 test/system/252-quadlet.bats                  | 25 +++++++++++++++++++
 3 files changed, 44 insertions(+)

diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md
index 6f27efec3c..24c4295c4c 100644
--- a/docs/source/markdown/podman-systemd.unit.5.md
+++ b/docs/source/markdown/podman-systemd.unit.5.md
@@ -121,6 +121,7 @@ Valid options for `[Container]` are listed below:
 | SecurityLabelLevel=s0:c1,c2      | --security-opt label=level:s0:c1,c2    |
 | SecurityLabelType=spc_t          | --security-opt label=type:spc_t        |
 | Timezone=local                   | --tz local                             |
+| Tmpfs=/work                      | --tmpfs /work                          |
 | User=bin                         | --user bin                             |
 | VolatileTmp=true                 | --tmpfs /tmp                           |
 | Volume=/source:/dest             | --volume /source:/dest                 |
@@ -450,6 +451,13 @@ Set the label process type for the container processes.
 Use a Podman secret in the container either as a file or an environment variable.
 This is equivalent to the Podman `--secret` option and generally has the form `secret[,opt=opt ...]`
 
+### `Tmpfs=`
+
+Mount a tmpfs in the container. This is equivalent to the Podman `--tmpfs` option, and
+generally has the form `CONTAINER-DIR[:OPTIONS]`.
+
+This key can be listed multiple times.
+
 ### `Timezone=` (if unset uses system-configured default)
 
 The timezone to run the container in.
diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go
index 051ed11cb5..a8efd011ea 100644
--- a/pkg/systemd/quadlet/quadlet.go
+++ b/pkg/systemd/quadlet/quadlet.go
@@ -94,6 +94,7 @@ const (
 	KeySecurityLabelType     = "SecurityLabelType"
 	KeySecret                = "Secret"
 	KeyTimezone              = "Timezone"
+	KeyTmpfs                 = "Tmpfs"
 	KeyType                  = "Type"
 	KeyUser                  = "User"
 	KeyVolatileTmp           = "VolatileTmp"
@@ -152,6 +153,7 @@ var (
 		KeySecurityLabelLevel:    true,
 		KeySecurityLabelType:     true,
 		KeySecret:                true,
+		KeyTmpfs:                 true,
 		KeyTimezone:              true,
 		KeyUser:                  true,
 		KeyVolatileTmp:           true,
@@ -474,6 +476,15 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
 		return nil, err
 	}
 
+	tmpfsValues := container.LookupAll(ContainerGroup, KeyTmpfs)
+	for _, tmpfs := range tmpfsValues {
+		if strings.Count(tmpfs, ":") > 1 {
+			return nil, fmt.Errorf("invalid tmpfs format '%s'", tmpfs)
+		}
+
+		podman.add("--tmpfs", tmpfs)
+	}
+
 	volumes := container.LookupAll(ContainerGroup, KeyVolume)
 	for _, volume := range volumes {
 		parts := strings.SplitN(volume, ":", 3)
diff --git a/test/system/252-quadlet.bats b/test/system/252-quadlet.bats
index 13dbcdac4e..f7889a0c72 100644
--- a/test/system/252-quadlet.bats
+++ b/test/system/252-quadlet.bats
@@ -582,4 +582,29 @@ EOF
     rm -rf $tmp_path
 }
 
+@test "quadlet - tmpfs" {
+    local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container
+    cat > $quadlet_file <<EOF
+[Container]
+Image=$IMAGE
+Exec=top
+Tmpfs=/tmpfs1
+Tmpfs=/tmpfs2:ro
+EOF
+
+    run_quadlet "$quadlet_file"
+    service_setup $QUADLET_SERVICE_NAME
+
+    run_podman container inspect  --format '{{index .HostConfig.Tmpfs "/tmpfs1"}}' $QUADLET_CONTAINER_NAME
+    is "$output" "rw,rprivate,nosuid,nodev,tmpcopyup" "regular tmpfs mount"
+
+    run_podman container inspect  --format '{{index .HostConfig.Tmpfs "/tmpfs2"}}' $QUADLET_CONTAINER_NAME
+    is "$output" "ro,rprivate,nosuid,nodev,tmpcopyup" "read-only tmpfs mount"
+
+    run_podman container inspect  --format '{{index .HostConfig.Tmpfs "/tmpfs3"}}' $QUADLET_CONTAINER_NAME
+    is "$output" "" "nonexistent tmpfs mount"
+
+    service_cleanup $QUADLET_SERVICE_NAME failed
+}
+
 # vim: filetype=sh