Skip to content

Commit

Permalink
quadlet: Support Type=oneshot container files
Browse files Browse the repository at this point in the history
These just run once and are considered successful at exist. Not much is
needed to support it, but we have to avoid overwriting the type
with Type=notify.

Signed-off-by: Alexander Larsson <[email protected]>
  • Loading branch information
alexlarsson committed Dec 21, 2022
1 parent 236f0cc commit 0179aa2
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 13 deletions.
32 changes: 20 additions & 12 deletions pkg/systemd/quadlet/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,6 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
// On clean shutdown, remove container
"--rm",

// Detach from container, we don't need the podman process to hang around
"-d",

// But we still want output to the journal, so use the log driver.
"--log-driver", "passthrough",
)
Expand All @@ -300,16 +297,27 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
podman.addBool("--init", runInit)
}

// By default we handle startup notification with conmon, but allow passing it to the container with Notify=yes
notify := container.LookupBooleanWithDefault(ContainerGroup, KeyNotify, false)
if notify {
podman.add("--sdnotify=container")
} else {
podman.add("--sdnotify=conmon")
serviceType, ok := service.Lookup(ServiceGroup, "Type")
if ok && serviceType != "notify" && serviceType != "oneshot" {
return nil, fmt.Errorf("invalid service Type '%s'", serviceType)
}

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 {
podman.add("--sdnotify=container")
} else {
podman.add("--sdnotify=conmon")
}
service.Setv(ServiceGroup,
"Type", "notify",
"NotifyAccess", "all")

// Detach from container, we don't need the podman process to hang around
podman.add("-d")
}
service.Setv(ServiceGroup,
"Type", "notify",
"NotifyAccess", "all")

if !container.HasKey(ServiceGroup, "SyslogIdentifier") {
service.Set(ServiceGroup, "SyslogIdentifier", "%N")
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/quadlet/basepodman.container
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## assert-podman-final-args run --name=systemd-%N --cidfile=%t/%N.cid --replace --rm -d --log-driver passthrough --runtime /usr/bin/crun --cgroups=split --sdnotify=conmon localhost/imagename
## assert-podman-final-args run --name=systemd-%N --cidfile=%t/%N.cid --replace --rm --log-driver passthrough --runtime /usr/bin/crun --cgroups=split --sdnotify=conmon -d localhost/imagename

[Container]
Image=localhost/imagename
Expand Down
9 changes: 9 additions & 0 deletions test/e2e/quadlet/oneshot.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## !assert-podman-args "--sdnotify=conmon"
## !assert-podman-args "--sdnotify=container"
## assert-key-is Service Type oneshot

[Container]
Image=localhost/imagename

[Service]
Type=oneshot
1 change: 1 addition & 0 deletions test/e2e/quadlet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ var _ = Describe("quadlet system generator", func() {
Entry("network.quadlet.container", "network.quadlet.container"),
Entry("noimage.container", "noimage.container"),
Entry("notify.container", "notify.container"),
Entry("oneshot.container", "oneshot.container"),
Entry("other-sections.container", "other-sections.container"),
Entry("podmanargs.container", "podmanargs.container"),
Entry("ports.container", "ports.container"),
Expand Down
23 changes: 23 additions & 0 deletions test/system/252-quadlet.bats
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,29 @@ EOF
service_cleanup $QUADLET_SERVICE_NAME failed
}

@test "quadlet - oneshot" {
local quadlet_file=$PODMAN_TMPDIR/oneshot_$(random_string).container
cat > $quadlet_file <<EOF
[Container]
Image=$IMAGE
Exec=echo INITIALIZED
[Service]
Type=oneshot
RemainAfterExit=yes
EOF

run_quadlet "$quadlet_file"

service_setup $QUADLET_SERVICE_NAME

# Ensure we have output. Output is synced by oneshot command exit
run journalctl "--since=$STARTED_TIME" SYSLOG_IDENTIFIER="$QUADLET_SYSLOG_ID"
is "$output" '.*INITIALIZED.*'

service_cleanup $QUADLET_SERVICE_NAME inactive
}

@test "quadlet - volume" {
local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).volume
cat > $quadlet_file <<EOF
Expand Down

0 comments on commit 0179aa2

Please sign in to comment.