Merge pull request #18446 from rhatdan/quadlet

Allow user quadlets to be stored under /etc
This commit is contained in:
OpenShift Merge Robot
2023-05-05 11:28:46 -04:00
committed by GitHub
3 changed files with 74 additions and 15 deletions

View File

@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"os"
"os/user"
"path"
"path/filepath"
"strings"
@ -98,8 +99,8 @@ func Debugf(format string, a ...interface{}) {
// This returns the directories where we read quadlet .container and .volumes from
// For system generators these are in /usr/share/containers/systemd (for distro files)
// and /etc/containers/systemd (for sysadmin files).
// For user generators these live in $XDG_CONFIG_HOME/containers/systemd
func getUnitDirs(user bool) []string {
// For user generators these can live in /etc/containers/systemd/users, /etc/containers/systemd/users/$UID, and $XDG_CONFIG_HOME/containers/systemd
func getUnitDirs(rootless bool) []string {
// Allow overdiding source dir, this is mainly for the CI tests
unitDirsEnv := os.Getenv("QUADLET_UNIT_DIRS")
if len(unitDirsEnv) > 0 {
@ -107,15 +108,23 @@ func getUnitDirs(user bool) []string {
}
dirs := make([]string, 0)
if user {
if configDir, err := os.UserConfigDir(); err == nil {
dirs = append(dirs, path.Join(configDir, "containers/systemd"))
if rootless {
configDir, err := os.UserConfigDir()
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: %v", err)
return nil
}
} else {
dirs = append(dirs, quadlet.UnitDirAdmin)
dirs = append(dirs, quadlet.UnitDirDistro)
dirs = append(dirs, path.Join(configDir, "containers/systemd"))
dirs = append(dirs, filepath.Join(quadlet.UnitDirAdmin, "users"))
u, err := user.Current()
if err != nil {
fmt.Fprintf(os.Stderr, "Warning: %v", err)
return dirs
}
return append(dirs, filepath.Join(quadlet.UnitDirAdmin, "users", u.Uid))
}
return dirs
dirs = append(dirs, quadlet.UnitDirAdmin)
return append(dirs, quadlet.UnitDirDistro)
}
func isExtSupported(filename string) bool {

View File

@ -1,8 +1,13 @@
package main
import (
"os"
"os/user"
"path"
"path/filepath"
"testing"
"github.com/containers/podman/v4/pkg/systemd/quadlet"
"github.com/stretchr/testify/assert"
)
@ -40,3 +45,38 @@ func TestIsUnambiguousName(t *testing.T) {
assert.Equal(t, res, test.res, "%q", test.input)
}
}
func TestUnitDirs(t *testing.T) {
rootDirs := []string{
quadlet.UnitDirAdmin,
quadlet.UnitDirDistro,
}
unitDirs := getUnitDirs(false)
assert.Equal(t, unitDirs, rootDirs, "rootful unit dirs should match")
configDir, err := os.UserConfigDir()
assert.Nil(t, err)
u, err := user.Current()
assert.Nil(t, err)
rootlessDirs := []string{
path.Join(configDir, "containers/systemd"),
filepath.Join(quadlet.UnitDirAdmin, "users"),
filepath.Join(quadlet.UnitDirAdmin, "users", u.Uid),
}
unitDirs = getUnitDirs(true)
assert.Equal(t, unitDirs, rootlessDirs, "rootless unit dirs should match")
name, err := os.MkdirTemp("", "dir")
assert.Nil(t, err)
// remove the temporary directory at the end of the program
defer os.RemoveAll(name)
t.Setenv("QUADLET_UNIT_DIRS", name)
unitDirs = getUnitDirs(false)
assert.Equal(t, unitDirs, []string{name}, "rootful should use environment variable")
unitDirs = getUnitDirs(true)
assert.Equal(t, unitDirs, []string{name}, "rootless should use environment variable")
}

View File

@ -2,7 +2,7 @@
## NAME
podman\-systemd.unit - systemd units using Podman quadlet
podman\-systemd.unit - systemd units using Podman Quadlet
## SYNOPSIS
@ -15,6 +15,8 @@ podman\-systemd.unit - systemd units using Podman quadlet
### Podman user unit search path
* /etc/containers/systemd/users/
* /etc/containers/systemd/users/$(UID)
* $XDG_CONFIG_HOME/containers/systemd/
* ~/.config/containers/systemd/
@ -38,6 +40,14 @@ Each file type has a custom section (for example, `[Container]`) that is handled
other sections will be passed on untouched, allowing the use of any normal systemd configuration options
like dependencies or cgroup limits.
For rootless containers, when administrators place Quadlet files in the
/etc/containers/systemd/users directory, all users' sessions will execute the
Quadlet when the login session begins. If the administrator places a Quadlet
file in the /etc/containers/systemd/user/${UID}/ directory, then only the
user with the matching UID will execute the Quadlet when the login
session gets started.
### Enabling unit files
The services created by Podman are considered transient by systemd, which means they don't have the same
@ -145,7 +155,7 @@ Adds a device node from the host into the container. The format of this is
`HOST-DEVICE[:CONTAINER-DEVICE][:PERMISSIONS]`, where `HOST-DEVICE` is the path of
the device node on the host, `CONTAINER-DEVICE` is the path of the device node in
the container, and `PERMISSIONS` is a list of permissions combining 'r' for read,
'w' for write, and 'm' for mknod(2). The `-` prefix tells quadlet to add the device
'w' for write, and 'm' for mknod(2). The `-` prefix tells Quadlet to add the device
only if it exists on the host.
This key can be listed multiple times.
@ -307,7 +317,7 @@ generally has the form `type=TYPE,TYPE-SPECIFIC-OPTION[,...]`.
As a special case, for `type=volume` if `source` ends with `.volume`, a Podman named volume called
`systemd-$name` will be used as the source, and the generated systemd service will contain
a dependency on the `$name-volume.service`. Such a volume can be automatically be lazily
created by using a `$name.volume` quadlet file.
created by using a `$name.volume` Quadlet file.
This key can be listed multiple times.
@ -320,7 +330,7 @@ not set up networking in the container.
As a special case, if the `name` of the network ends with `.network`, a Podman network called
`systemd-$name` will be used, and the generated systemd service will contain
a dependency on the `$name-network.service`. Such a network can be automatically
created by using a `$name.network` quadlet file.
created by using a `$name.network` Quadlet file.
This key can be listed multiple times.
@ -449,7 +459,7 @@ If `SOURCE-VOLUME` starts with `.`, Quadlet will resolve the path relative to th
As a special case, if `SOURCE-VOLUME` ends with `.volume`, a Podman named volume called
`systemd-$name` will be used as the source, and the generated systemd service will contain
a dependency on the `$name-volume.service`. Such a volume can be automatically be lazily
created by using a `$name.volume` quadlet file.
created by using a `$name.volume` Quadlet file.
This key can be listed multiple times.
@ -498,7 +508,7 @@ not set up networking in the container.
As a special case, if the `name` of the network ends with `.network`, a Podman network called
`systemd-$name` will be used, and the generated systemd service will contain
a dependency on the `$name-network.service`. Such a network can be automatically
created by using a `$name.network` quadlet file.
created by using a `$name.network` Quadlet file.
This key can be listed multiple times.