mirror of
https://github.com/containers/podman.git
synced 2025-06-24 03:08:13 +08:00
Merge pull request #18446 from rhatdan/quadlet
Allow user quadlets to be stored under /etc
This commit is contained in:
@ -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,16 +108,24 @@ func getUnitDirs(user bool) []string {
|
||||
}
|
||||
|
||||
dirs := make([]string, 0)
|
||||
if user {
|
||||
if configDir, err := os.UserConfigDir(); err == nil {
|
||||
if rootless {
|
||||
configDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: %v", err)
|
||||
return nil
|
||||
}
|
||||
dirs = append(dirs, path.Join(configDir, "containers/systemd"))
|
||||
}
|
||||
} else {
|
||||
dirs = append(dirs, quadlet.UnitDirAdmin)
|
||||
dirs = append(dirs, quadlet.UnitDirDistro)
|
||||
}
|
||||
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))
|
||||
}
|
||||
dirs = append(dirs, quadlet.UnitDirAdmin)
|
||||
return append(dirs, quadlet.UnitDirDistro)
|
||||
}
|
||||
|
||||
func isExtSupported(filename string) bool {
|
||||
ext := filepath.Ext(filename)
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
Reference in New Issue
Block a user