Add quadlet support for rootfs= containers

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Add rootfs= support for quadlet containers

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2023-02-04 06:34:37 -05:00
parent 004d611cba
commit 928d589b7e
6 changed files with 48 additions and 5 deletions

View File

@ -188,6 +188,14 @@ This key can be listed multiple times.
If enabled (which is the default), this disables the container processes from gaining additional privileges via things like If enabled (which is the default), this disables the container processes from gaining additional privileges via things like
setuid and file capabilities. setuid and file capabilities.
#### `Rootfs=`
The rootfs to use for the container. Rootfs points to a directory on the system that contains the content to be run within the container. This option conflicts with the `Image` option.
The format of the rootfs is the same as when passed to `podman run --rootfs`, so it supports ovelay mounts as well.
Note: On SELinux systems, the rootfs needs the correct label, which is by default unconfined_u:object_r:container_file_t:s0.
#### `Notify=` (defaults to `no`) #### `Notify=` (defaults to `no`)
By default, Podman is run in such a way that the systemd startup notify command is handled by By default, Podman is run in such a way that the systemd startup notify command is handled by

View File

@ -45,6 +45,7 @@ const (
KeyRemapUID = "RemapUid" KeyRemapUID = "RemapUid"
KeyRemapGID = "RemapGid" KeyRemapGID = "RemapGid"
KeyRemapUIDSize = "RemapUidSize" KeyRemapUIDSize = "RemapUidSize"
KeyRootfs = "Rootfs"
KeyNotify = "Notify" KeyNotify = "Notify"
KeyExposeHostPort = "ExposeHostPort" KeyExposeHostPort = "ExposeHostPort"
KeyPublishPort = "PublishPort" KeyPublishPort = "PublishPort"
@ -96,6 +97,7 @@ var (
KeyRemapUID: true, KeyRemapUID: true,
KeyRemapGID: true, KeyRemapGID: true,
KeyRemapUIDSize: true, KeyRemapUIDSize: true,
KeyRootfs: true,
KeyNotify: true, KeyNotify: true,
KeyExposeHostPort: true, KeyExposeHostPort: true,
KeyPublishPort: true, KeyPublishPort: true,
@ -239,9 +241,14 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
// Rename old Container group to x-Container so that systemd ignores it // Rename old Container group to x-Container so that systemd ignores it
service.RenameGroup(ContainerGroup, XContainerGroup) service.RenameGroup(ContainerGroup, XContainerGroup)
image, ok := container.Lookup(ContainerGroup, KeyImage) // One image or rootfs must be specified for the container
if !ok || len(image) == 0 { image, _ := container.Lookup(ContainerGroup, KeyImage)
return nil, fmt.Errorf("no Image key specified") rootfs, _ := container.Lookup(ContainerGroup, KeyRootfs)
if len(image) == 0 && len(rootfs) == 0 {
return nil, fmt.Errorf("no Image or Rootfs key specified")
}
if len(image) > 0 && len(rootfs) > 0 {
return nil, fmt.Errorf("the Image And Rootfs keys conflict can not be specified together")
} }
containerName, ok := container.Lookup(ContainerGroup, KeyContainerName) containerName, ok := container.Lookup(ContainerGroup, KeyContainerName)
@ -486,7 +493,11 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
podmanArgs := container.LookupAllArgs(ContainerGroup, KeyPodmanArgs) podmanArgs := container.LookupAllArgs(ContainerGroup, KeyPodmanArgs)
podman.add(podmanArgs...) podman.add(podmanArgs...)
if len(image) > 0 {
podman.add(image) podman.add(image)
} else {
podman.add("--rootfs", rootfs)
}
execArgs, ok := container.LookupLastArgs(ContainerGroup, KeyExec) execArgs, ok := container.LookupLastArgs(ContainerGroup, KeyExec)
if ok { if ok {

View File

@ -1,4 +1,4 @@
## assert-failed ## assert-failed
## assert-stderr-contains "no Image key specified" ## assert-stderr-contains "no Image or Rootfs key specified"
[Container] [Container]

View File

@ -0,0 +1,4 @@
## assert-podman-final-args "--rootfs" "/var/lib/foobar"
[Container]
Rootfs=/var/lib/foobar

View File

@ -460,6 +460,7 @@ var _ = Describe("quadlet system generator", func() {
Entry("noimage.container", "noimage.container"), Entry("noimage.container", "noimage.container"),
Entry("notify.container", "notify.container"), Entry("notify.container", "notify.container"),
Entry("oneshot.container", "oneshot.container"), Entry("oneshot.container", "oneshot.container"),
Entry("rootfs.container", "rootfs.container"),
Entry("other-sections.container", "other-sections.container"), Entry("other-sections.container", "other-sections.container"),
Entry("podmanargs.container", "podmanargs.container"), Entry("podmanargs.container", "podmanargs.container"),
Entry("ports.container", "ports.container"), Entry("ports.container", "ports.container"),

View File

@ -406,4 +406,23 @@ EOF
run_podman rmi $(pause_image) run_podman rmi $(pause_image)
} }
@test "quadlet - rootfs" {
skip_if_no_selinux
skip_if_rootless
local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container
cat > $quadlet_file <<EOF
[Container]
Rootfs=/:O
Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; top"
EOF
run_quadlet "$quadlet_file"
service_setup $QUADLET_SERVICE_NAME
# Ensure we have output. Output is synced via sd-notify (socat in Exec)
run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME"
is "$output" '.*STARTED CONTAINER.*'
}
# vim: filetype=sh # vim: filetype=sh