[All] Bump podman to 4.8.3 and add support for healthy sdnotify check

Moved the podman patches to the external buildroot tree
This commit is contained in:
j1nx 2024-01-07 08:39:09 +00:00
parent b9bf74be43
commit a30437ae3e
3 changed files with 331 additions and 1 deletions

@ -1 +1 @@
Subproject commit 32c57f4cb8a1a4a59f811577f53efdaaf03875ce
Subproject commit add67823a7bea007732d60a2a79bf6b2a4e3cdc9

View File

@ -0,0 +1,252 @@
From 8ee26220281bc5bbb6a2b72ab0cf5a2f120b1afa Mon Sep 17 00:00:00 2001
From: Alexander Larsson <alexl@redhat.com>
Date: Wed, 29 Nov 2023 10:57:42 +0100
Subject: [PATCH] quadlet: Support systemd style dropin files
For a source file like `foo.container`, look for drop in named
`foo.container.d/*.conf` and merged them into the main file. The
dropins are applied in alphabetical order, and files in earlier
diretories override later files with same name.
This is similar to how systemd dropins work, see:
https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html
Also adds some tests for these
Signed-off-by: Alexander Larsson <alexl@redhat.com>
---
cmd/quadlet/main.go | 67 +++++++++++++++++++
docs/source/markdown/podman-systemd.unit.5.md | 7 ++
pkg/systemd/parser/unitfile.go | 4 +-
test/e2e/quadlet/merged-override.container | 8 +++
.../merged-override.container.d/10-first.conf | 2 +
.../20-second.conf | 4 ++
test/e2e/quadlet/merged.container | 8 +++
.../quadlet/merged.container.d/10-first.conf | 2 +
.../quadlet/merged.container.d/20-second.conf | 2 +
test/e2e/quadlet_test.go | 12 ++++
10 files changed, 114 insertions(+), 2 deletions(-)
create mode 100644 test/e2e/quadlet/merged-override.container
create mode 100644 test/e2e/quadlet/merged-override.container.d/10-first.conf
create mode 100644 test/e2e/quadlet/merged-override.container.d/20-second.conf
create mode 100644 test/e2e/quadlet/merged.container
create mode 100644 test/e2e/quadlet/merged.container.d/10-first.conf
create mode 100644 test/e2e/quadlet/merged.container.d/20-second.conf
diff --git a/cmd/quadlet/main.go b/cmd/quadlet/main.go
index b36997b32a73..9c032427b0a4 100644
--- a/cmd/quadlet/main.go
+++ b/cmd/quadlet/main.go
@@ -242,6 +242,67 @@ func loadUnitsFromDir(sourcePath string) ([]*parser.UnitFile, error) {
return units, prevError
}
+func loadUnitDropins(unit *parser.UnitFile, sourcePaths []string) error {
+ var prevError error
+ reportError := func(err error) {
+ if prevError != nil {
+ err = fmt.Errorf("%s\n%s", prevError, err)
+ }
+ prevError = err
+ }
+
+ var dropinPaths = make(map[string]string)
+ for _, sourcePath := range sourcePaths {
+ dropinDir := path.Join(sourcePath, unit.Filename+".d")
+
+ dropinFiles, err := os.ReadDir(dropinDir)
+ if err != nil {
+ if !errors.Is(err, os.ErrNotExist) {
+ reportError(fmt.Errorf("error reading directory %q, %w", dropinDir, err))
+ }
+
+ continue
+ }
+
+ for _, dropinFile := range dropinFiles {
+ dropinName := dropinFile.Name()
+ if filepath.Ext(dropinName) != ".conf" {
+ continue // Only *.conf supported
+ }
+
+ if _, ok := dropinPaths[dropinName]; ok {
+ continue // We already saw this name
+ }
+
+ dropinPaths[dropinName] = path.Join(dropinDir, dropinName)
+ }
+ }
+
+ dropinFiles := make([]string, len(dropinPaths))
+ i := 0
+ for k := range dropinPaths {
+ dropinFiles[i] = k
+ i++
+ }
+
+ // Merge in alpha-numerical order
+ sort.Strings(dropinFiles)
+
+ for _, dropinFile := range dropinFiles {
+ dropinPath := dropinPaths[dropinFile]
+
+ Debugf("Loading source drop-in file %s", dropinPath)
+
+ if f, err := parser.ParseUnitFile(dropinPath); err != nil {
+ reportError(fmt.Errorf("error loading %q, %w", dropinPath, err))
+ } else {
+ unit.Merge(f)
+ }
+ }
+
+ return prevError
+}
+
func generateServiceFile(service *parser.UnitFile) error {
Debugf("writing %q", service.Path)
@@ -456,6 +517,12 @@ func process() error {
return prevError
}
+ for _, unit := range units {
+ if err := loadUnitDropins(unit, sourcePaths); err != nil {
+ reportError(err)
+ }
+ }
+
if !dryRunFlag {
err := os.MkdirAll(outputPath, os.ModePerm)
if err != nil {
diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md
index 8101338a56b6..4969a84aca7b 100644
--- a/docs/source/markdown/podman-systemd.unit.5.md
+++ b/docs/source/markdown/podman-systemd.unit.5.md
@@ -47,6 +47,13 @@ Each file type has a custom section (for example, `[Container]`) that is handled
other sections are passed on untouched, allowing the use of any normal systemd configuration options
like dependencies or cgroup limits.
+The source files also support drop-ins in the same [way systemd does](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html).
+For a given source file (say `foo.container`), the corresponding `.d`directory (in this
+case `foo.container.d`) will be scanned for files with a `.conf` extension that are merged into
+the base file in alphabetical order. The format of these drop-in files is the same as the base file.
+This is useful to alter or add configuration settings for a unit, without having to modify unit
+files.
+
For rootless containers, when administrators place Quadlet files in the
/etc/containers/systemd/users directory, all users' sessions execute the
Quadlet when the login session begins. If the administrator places a Quadlet
diff --git a/pkg/systemd/parser/unitfile.go b/pkg/systemd/parser/unitfile.go
index 963909f9d876..732daa2be4fb 100644
--- a/pkg/systemd/parser/unitfile.go
+++ b/pkg/systemd/parser/unitfile.go
@@ -182,7 +182,7 @@ func (f *UnitFile) ensureGroup(groupName string) *unitGroup {
return g
}
-func (f *UnitFile) merge(source *UnitFile) {
+func (f *UnitFile) Merge(source *UnitFile) {
for _, srcGroup := range source.groups {
group := f.ensureGroup(srcGroup.name)
group.merge(srcGroup)
@@ -193,7 +193,7 @@ func (f *UnitFile) merge(source *UnitFile) {
func (f *UnitFile) Dup() *UnitFile {
copy := NewUnitFile()
- copy.merge(f)
+ copy.Merge(f)
copy.Filename = f.Filename
return copy
}
diff --git a/test/e2e/quadlet/merged-override.container b/test/e2e/quadlet/merged-override.container
new file mode 100644
index 000000000000..d93a53b340a9
--- /dev/null
+++ b/test/e2e/quadlet/merged-override.container
@@ -0,0 +1,8 @@
+## assert-podman-final-args localhost/imagename
+## !assert-podman-args --env "MAIN=mainvalue"
+## !assert-podman-args --env "FIRST=value"
+## assert-podman-args --env "SECOND=othervalue"
+
+[Container]
+Image=localhost/imagename
+Environment=MAIN=mainvalue
diff --git a/test/e2e/quadlet/merged-override.container.d/10-first.conf b/test/e2e/quadlet/merged-override.container.d/10-first.conf
new file mode 100644
index 000000000000..f6164d631e05
--- /dev/null
+++ b/test/e2e/quadlet/merged-override.container.d/10-first.conf
@@ -0,0 +1,2 @@
+[Container]
+Environment=FIRST=value
diff --git a/test/e2e/quadlet/merged-override.container.d/20-second.conf b/test/e2e/quadlet/merged-override.container.d/20-second.conf
new file mode 100644
index 000000000000..5bfcdd44dcc8
--- /dev/null
+++ b/test/e2e/quadlet/merged-override.container.d/20-second.conf
@@ -0,0 +1,4 @@
+[Container]
+# Empty previous
+Environment=
+Environment=SECOND=othervalue
diff --git a/test/e2e/quadlet/merged.container b/test/e2e/quadlet/merged.container
new file mode 100644
index 000000000000..3d19987fd0ca
--- /dev/null
+++ b/test/e2e/quadlet/merged.container
@@ -0,0 +1,8 @@
+## assert-podman-final-args localhost/imagename
+## assert-podman-args --env "MAIN=mainvalue"
+## assert-podman-args --env "FIRST=value"
+## assert-podman-args --env "SECOND=othervalue"
+
+[Container]
+Image=localhost/imagename
+Environment=MAIN=mainvalue
diff --git a/test/e2e/quadlet/merged.container.d/10-first.conf b/test/e2e/quadlet/merged.container.d/10-first.conf
new file mode 100644
index 000000000000..f6164d631e05
--- /dev/null
+++ b/test/e2e/quadlet/merged.container.d/10-first.conf
@@ -0,0 +1,2 @@
+[Container]
+Environment=FIRST=value
diff --git a/test/e2e/quadlet/merged.container.d/20-second.conf b/test/e2e/quadlet/merged.container.d/20-second.conf
new file mode 100644
index 000000000000..f1dcaa61fc93
--- /dev/null
+++ b/test/e2e/quadlet/merged.container.d/20-second.conf
@@ -0,0 +1,2 @@
+[Container]
+Environment=SECOND=othervalue
diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go
index ad3061f4cdd2..c9c43d284971 100644
--- a/test/e2e/quadlet_test.go
+++ b/test/e2e/quadlet_test.go
@@ -664,6 +664,16 @@ BOGUS=foo
err = os.WriteFile(filepath.Join(quadletDir, fileName), testcase.data, 0644)
Expect(err).ToNot(HaveOccurred())
+ // Also copy any extra snippets
+ dotdDir := filepath.Join("quadlet", fileName+".d")
+ if s, err := os.Stat(dotdDir); err == nil && s.IsDir() {
+ dotdDirDest := filepath.Join(quadletDir, fileName+".d")
+ err = os.Mkdir(dotdDirDest, os.ModePerm)
+ Expect(err).ToNot(HaveOccurred())
+ err = CopyDirectory(dotdDir, dotdDirDest)
+ Expect(err).ToNot(HaveOccurred())
+ }
+
// Run quadlet to convert the file
session := podmanTest.Quadlet([]string{"--user", "--no-kmsg-log", generatedDir}, quadletDir)
session.WaitWithDefaultTimeout()
@@ -748,6 +758,8 @@ BOGUS=foo
Entry("workingdir.container", "workingdir.container", 0, ""),
Entry("Container - global args", "globalargs.container", 0, ""),
Entry("Container - Containers Conf Modules", "containersconfmodule.container", 0, ""),
+ Entry("merged.container", "merged.container", 0, ""),
+ Entry("merged-override.container", "merged-override.container", 0, ""),
Entry("basic.volume", "basic.volume", 0, ""),
Entry("device-copy.volume", "device-copy.volume", 0, ""),

View File

@ -0,0 +1,78 @@
From 6cb2f9b1225ade1248ed954e5e03fea9ff279730 Mon Sep 17 00:00:00 2001
From: Alex Palaistras <alex@deuill.org>
Date: Sat, 18 Nov 2023 21:37:00 +0000
Subject: [PATCH] quadlet: Support `healthy` for `Notify` directives
This expands support for the (previously) boolean `Notify` directive, in
support of healthcheck determined SD-NOTIFY event emission, as
supported by Podman with the `--sdnotify=healthy` option.
Closes: #18189
Signed-off-by: Alex Palaistras <alex@deuill.org>
---
docs/source/markdown/podman-systemd.unit.5.md | 4 ++++
pkg/systemd/quadlet/quadlet.go | 9 ++++++---
test/e2e/quadlet/notify-healthy.container | 5 +++++
test/e2e/quadlet_test.go | 1 +
4 files changed, 16 insertions(+), 3 deletions(-)
create mode 100644 test/e2e/quadlet/notify-healthy.container
diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md
index 79659ded24fa..01ca6293a0f7 100644
--- a/docs/source/markdown/podman-systemd.unit.5.md
+++ b/docs/source/markdown/podman-systemd.unit.5.md
@@ -496,6 +496,10 @@ starts the child in the container. However, if the container application support
`Notify` to true passes the notification details to the container allowing it to notify
of startup on its own.
+In addition, setting `Notify` to `healthy` will postpone startup notifications until such time as
+the container is marked healthy, as determined by Podman healthchecks. Note that this requires
+setting up a container healthcheck, see the `HealthCmd` option for more.
+
### `PidsLimit=`
Tune the container's pids limit.
diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go
index 26e1745b1e98..3328087900d6 100644
--- a/pkg/systemd/quadlet/quadlet.go
+++ b/pkg/systemd/quadlet/quadlet.go
@@ -496,10 +496,13 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
if serviceType != "oneshot" {
// If we're not in oneshot mode always use some form of sd-notify, normally via conmon,
// but we also allow passing it to the container by setting Notify=yes
- notify := container.LookupBooleanWithDefault(ContainerGroup, KeyNotify, false)
- if notify {
+ notify, ok := container.Lookup(ContainerGroup, KeyNotify)
+ switch {
+ case ok && strings.EqualFold(notify, "healthy"):
+ podman.add("--sdnotify=healthy")
+ case container.LookupBooleanWithDefault(ContainerGroup, KeyNotify, false):
podman.add("--sdnotify=container")
- } else {
+ default:
podman.add("--sdnotify=conmon")
}
service.Setv(ServiceGroup,
diff --git a/test/e2e/quadlet/notify-healthy.container b/test/e2e/quadlet/notify-healthy.container
new file mode 100644
index 000000000000..6dc3d8c09257
--- /dev/null
+++ b/test/e2e/quadlet/notify-healthy.container
@@ -0,0 +1,5 @@
+## assert-podman-args "--sdnotify=healthy"
+
+[Container]
+Image=localhost/imagename
+Notify=healthy
diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go
index 34de88293008..ad3061f4cdd2 100644
--- a/test/e2e/quadlet_test.go
+++ b/test/e2e/quadlet_test.go
@@ -712,6 +712,7 @@ BOGUS=foo
Entry("network.quadlet.container", "network.quadlet.container", 0, ""),
Entry("noimage.container", "noimage.container", 1, "converting \"noimage.container\": no Image or Rootfs key specified"),
Entry("notify.container", "notify.container", 0, ""),
+ Entry("notify-healthy.container", "notify-healthy.container", 0, ""),
Entry("oneshot.container", "oneshot.container", 0, ""),
Entry("other-sections.container", "other-sections.container", 0, ""),
Entry("podmanargs.container", "podmanargs.container", 0, ""),