Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quadlet - add support for global arguments #20253

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 184 additions & 78 deletions docs/source/markdown/podman-systemd.unit.5.md

Large diffs are not rendered by default.

157 changes: 99 additions & 58 deletions pkg/systemd/quadlet/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const (
KeyDecryptionKey = "DecryptionKey"
KeyConfigMap = "ConfigMap"
KeyContainerName = "ContainerName"
KeyContainersConfModule = "ContainersConfModule"
KeyCopy = "Copy"
KeyDevice = "Device"
KeyDNS = "DNS"
Expand All @@ -72,6 +73,7 @@ const (
KeyExec = "Exec"
KeyExitCodePropagation = "ExitCodePropagation"
KeyExposeHostPort = "ExposeHostPort"
KeyGlobalArgs = "GlobalArgs"
KeyGroup = "Group"
KeyHealthCmd = "HealthCmd"
KeyHealthInterval = "HealthInterval"
Expand Down Expand Up @@ -154,6 +156,7 @@ var (
KeyAnnotation: true,
KeyAutoUpdate: true,
KeyContainerName: true,
KeyContainersConfModule: true,
KeyDNS: true,
KeyDNSOption: true,
KeyDNSSearch: true,
Expand All @@ -163,6 +166,7 @@ var (
KeyEnvironmentHost: true,
KeyExec: true,
KeyExposeHostPort: true,
KeyGlobalArgs: true,
KeyGroup: true,
KeyHealthCmd: true,
KeyHealthInterval: true,
Expand Down Expand Up @@ -219,67 +223,75 @@ var (

// Supported keys in "Volume" group
supportedVolumeKeys = map[string]bool{
KeyCopy: true,
KeyDevice: true,
KeyDriver: true,
KeyGroup: true,
KeyImage: true,
KeyLabel: true,
KeyOptions: true,
KeyPodmanArgs: true,
KeyType: true,
KeyUser: true,
KeyVolumeName: true,
KeyContainersConfModule: true,
KeyCopy: true,
KeyDevice: true,
KeyDriver: true,
KeyGlobalArgs: true,
KeyGroup: true,
KeyImage: true,
KeyLabel: true,
KeyOptions: true,
KeyPodmanArgs: true,
KeyType: true,
KeyUser: true,
KeyVolumeName: true,
}

// Supported keys in "Network" group
supportedNetworkKeys = map[string]bool{
KeyLabel: true,
KeyDNS: true,
KeyNetworkDisableDNS: true,
KeyNetworkDriver: true,
KeyNetworkGateway: true,
KeyNetworkIPAMDriver: true,
KeyNetworkIPRange: true,
KeyNetworkIPv6: true,
KeyNetworkInternal: true,
KeyNetworkName: true,
KeyNetworkOptions: true,
KeyNetworkSubnet: true,
KeyPodmanArgs: true,
KeyLabel: true,
KeyDNS: true,
KeyContainersConfModule: true,
KeyGlobalArgs: true,
KeyNetworkDisableDNS: true,
KeyNetworkDriver: true,
KeyNetworkGateway: true,
KeyNetworkIPAMDriver: true,
KeyNetworkIPRange: true,
KeyNetworkIPv6: true,
KeyNetworkInternal: true,
KeyNetworkName: true,
KeyNetworkOptions: true,
KeyNetworkSubnet: true,
KeyPodmanArgs: true,
}

// Supported keys in "Kube" group
supportedKubeKeys = map[string]bool{
KeyAutoUpdate: true,
KeyConfigMap: true,
KeyExitCodePropagation: true,
KeyLogDriver: true,
KeyNetwork: true,
KeyPodmanArgs: true,
KeyPublishPort: true,
KeyRemapGID: true,
KeyRemapUID: true,
KeyRemapUIDSize: true,
KeyRemapUsers: true,
KeySetWorkingDirectory: true,
KeyUserNS: true,
KeyYaml: true,
KeyAutoUpdate: true,
KeyConfigMap: true,
KeyContainersConfModule: true,
KeyExitCodePropagation: true,
KeyGlobalArgs: true,
KeyLogDriver: true,
KeyNetwork: true,
KeyPodmanArgs: true,
KeyPublishPort: true,
KeyRemapGID: true,
KeyRemapUID: true,
KeyRemapUIDSize: true,
KeyRemapUsers: true,
KeySetWorkingDirectory: true,
KeyUserNS: true,
KeyYaml: true,
}

// Supported keys in "Image" group
supportedImageKeys = map[string]bool{
KeyAllTags: true,
KeyArch: true,
KeyAuthFile: true,
KeyCertDir: true,
KeyCreds: true,
KeyDecryptionKey: true,
KeyImage: true,
KeyOS: true,
KeyPodmanArgs: true,
KeyTLSVerify: true,
KeyVariant: true,
KeyAllTags: true,
KeyArch: true,
KeyAuthFile: true,
KeyCertDir: true,
KeyContainersConfModule: true,
KeyCreds: true,
KeyDecryptionKey: true,
KeyGlobalArgs: true,
KeyImage: true,
KeyOS: true,
KeyPodmanArgs: true,
KeyTLSVerify: true,
KeyVariant: true,
}
)

Expand Down Expand Up @@ -416,14 +428,19 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse

// If conmon exited uncleanly it may not have removed the container, so
// force it, -i makes it ignore non-existing files.
service.Add(ServiceGroup, "ExecStop", podmanBinary()+" rm -v -f -i --cidfile=%t/%N.cid")
serviceStopCmd := createBasePodmanCommand(container, ContainerGroup)
serviceStopCmd.add("rm", "-v", "-f", "-i", "--cidfile=%t/%N.cid")
service.AddCmdline(ServiceGroup, "ExecStop", serviceStopCmd.Args)
// The ExecStopPost is needed when the main PID (i.e., conmon) gets killed.
// In that case, ExecStop is not executed but *Post only. If both are
// fired in sequence, *Post will exit when detecting that the --cidfile
// has already been removed by the previous `rm`..
service.Add(ServiceGroup, "ExecStopPost", "-"+podmanBinary()+" rm -v -f -i --cidfile=%t/%N.cid")
serviceStopCmd.Args[0] = fmt.Sprintf("-%s", serviceStopCmd.Args[0])
service.AddCmdline(ServiceGroup, "ExecStopPost", serviceStopCmd.Args)

podman := NewPodmanCmdline("run")
podman := createBasePodmanCommand(container, ContainerGroup)

podman.add("run")

podman.addf("--name=%s", containerName)

Expand Down Expand Up @@ -794,7 +811,9 @@ func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, st
// Need the containers filesystem mounted to start podman
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")

podman := NewPodmanCmdline("network", "create", "--ignore")
podman := createBasePodmanCommand(network, NetworkGroup)

podman.add("network", "create", "--ignore")

if disableDNS := network.LookupBooleanWithDefault(NetworkGroup, KeyNetworkDisableDNS, false); disableDNS {
podman.add("--disable-dns")
Expand Down Expand Up @@ -898,7 +917,9 @@ func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string

labels := volume.LookupAllKeyVal(VolumeGroup, "Label")

podman := NewPodmanCmdline("volume", "create", "--ignore")
podman := createBasePodmanCommand(volume, VolumeGroup)

podman.add("volume", "create", "--ignore")

driver, ok := volume.Lookup(VolumeGroup, KeyDriver)
if ok {
Expand Down Expand Up @@ -1050,7 +1071,9 @@ func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*
service.Set(ServiceGroup, "SyslogIdentifier", "%N")
}

execStart := NewPodmanCmdline("kube", "play")
execStart := createBasePodmanCommand(kube, KubeGroup)

execStart.add("kube", "play")

execStart.add(
// Replace any previous container with the same name, not fail
Expand Down Expand Up @@ -1107,8 +1130,8 @@ func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*

// Use `ExecStopPost` to make sure cleanup happens even in case of
// errors; otherwise containers, pods, etc. would be left behind.
execStop := NewPodmanCmdline("kube", "down")
execStop.add(yamlPath)
execStop := createBasePodmanCommand(kube, KubeGroup)
execStop.add("kube", "down", yamlPath)
service.AddCmdline(ServiceGroup, "ExecStopPost", execStop.Args)

err = handleSetWorkingDirectory(kube, service)
Expand Down Expand Up @@ -1142,7 +1165,9 @@ func ConvertImage(image *parser.UnitFile) (*parser.UnitFile, string, error) {
// Need the containers filesystem mounted to start podman
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")

podman := NewPodmanCmdline("image", "pull")
podman := createBasePodmanCommand(image, ImageGroup)

podman.add("image", "pull")

stringKeys := map[string]string{
KeyArch: "--arch",
Expand Down Expand Up @@ -1571,3 +1596,19 @@ func convertToCSV(s []string) (string, error) {

return ret, nil
}

func createBasePodmanCommand(unitFile *parser.UnitFile, groupName string) *PodmanCmdline {
podman := NewPodmanCmdline()

containersConfModules := unitFile.LookupAll(groupName, KeyContainersConfModule)
for _, containersConfModule := range containersConfModules {
podman.addf("--module=%s", containersConfModule)
}

globalArgs := unitFile.LookupAllArgs(groupName, KeyGlobalArgs)
if len(globalArgs) > 0 {
podman.add(globalArgs...)
}

return podman
}
2 changes: 1 addition & 1 deletion test/e2e/quadlet/basic.container
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
## assert-key-is "Service" "Type" "notify"
## assert-key-is "Service" "NotifyAccess" "all"
## assert-key-is "Service" "SyslogIdentifier" "%N"
## assert-key-is-regex "Service" "ExecStopPost" "-.*/podman rm -v -f -i --cidfile=%t/%N.cid"
## assert-key-is-regex "Service" "ExecStopPost" "-[/S].*/podman rm -v -f -i --cidfile=%t/%N.cid"
## assert-key-is-regex "Service" "ExecStop" ".*/podman rm -v -f -i --cidfile=%t/%N.cid"
## assert-key-is "Service" "Environment" "PODMAN_SYSTEMD_UNIT=%n"

Expand Down
7 changes: 7 additions & 0 deletions test/e2e/quadlet/containersconfmodule.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-global-args "run" "--module=/etc/container/1.conf"
## assert-podman-global-args "run" "--module=/etc/container/2.conf"

[Container]
Image=image
ContainersConfModule=/etc/container/1.conf
ContainersConfModule=/etc/container/2.conf
7 changes: 7 additions & 0 deletions test/e2e/quadlet/containersconfmodule.image
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-global-args "image" "--module=/etc/container/1.conf"
## assert-podman-global-args "image" "--module=/etc/container/2.conf"

[Image]
Image=image:latest
ContainersConfModule=/etc/container/1.conf
ContainersConfModule=/etc/container/2.conf
7 changes: 7 additions & 0 deletions test/e2e/quadlet/containersconfmodule.kube
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-global-args "kube" "--module=/etc/container/1.conf"
## assert-podman-global-args "kube" "--module=/etc/container/2.conf"

[Kube]
Yaml=file.yml
ContainersConfModule=/etc/container/1.conf
ContainersConfModule=/etc/container/2.conf
6 changes: 6 additions & 0 deletions test/e2e/quadlet/containersconfmodule.network
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## assert-podman-global-args "network" "--module=/etc/container/1.conf"
## assert-podman-global-args "network" "--module=/etc/container/2.conf"

[Network]
ContainersConfModule=/etc/container/1.conf
ContainersConfModule=/etc/container/2.conf
6 changes: 6 additions & 0 deletions test/e2e/quadlet/containersconfmodule.volume
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## assert-podman-global-args "volume" "--module=/etc/container/1.conf"
## assert-podman-global-args "volume" "--module=/etc/container/2.conf"

[Volume]
ContainersConfModule=/etc/container/1.conf
ContainersConfModule=/etc/container/2.conf
16 changes: 16 additions & 0 deletions test/e2e/quadlet/globalargs.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## assert-podman-global-args "run" "--conmon=/usr/bin/somewhere"
## assert-podman-global-args "run" "--imagestore=/var/lib/somestore"
## assert-podman-global-args "run" "--log-level=debug"

## assert-podman-stop-global-args "rm" "--conmon=/usr/bin/somewhere"
## assert-podman-stop-global-args "rm" "--imagestore=/var/lib/somestore"
## assert-podman-stop-global-args "rm" "--log-level=debug"

## assert-podman-stop-post-global-args "rm" "--conmon=/usr/bin/somewhere"
## assert-podman-stop-post-global-args "rm" "--imagestore=/var/lib/somestore"
## assert-podman-stop-post-global-args "rm" "--log-level=debug"

[Container]
Image=image
GlobalArgs=--conmon=/usr/bin/somewhere
GlobalArgs=--imagestore=/var/lib/somestore --log-level=debug
8 changes: 8 additions & 0 deletions test/e2e/quadlet/globalargs.image
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## assert-podman-global-args "image" "--identity=path=/etc/identity"
## assert-podman-global-args "image" "--syslog"
## assert-podman-global-args "image" "--log-level=debug"

[Image]
Image=image:latest
GlobalArgs=--identity=path=/etc/identity
GlobalArgs=--syslog --log-level=debug
12 changes: 12 additions & 0 deletions test/e2e/quadlet/globalargs.kube
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## assert-podman-global-args "kube" "--conmon=/usr/bin/somewhere"
## assert-podman-global-args "kube" "--imagestore=/var/lib/somestore"
## assert-podman-global-args "kube" "--log-level=debug"

## assert-podman-stop-post-global-args "kube" "--conmon=/usr/bin/somewhere"
## assert-podman-stop-post-global-args "kube" "--imagestore=/var/lib/somestore"
## assert-podman-stop-post-global-args "kube" "--log-level=debug"

[Kube]
Yaml=file.yml
GlobalArgs=--conmon=/usr/bin/somewhere
GlobalArgs=--imagestore=/var/lib/somestore --log-level=debug
7 changes: 7 additions & 0 deletions test/e2e/quadlet/globalargs.network
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-global-args "network" "--network-cmd-path=/usr/bin/network-cmd"
## assert-podman-global-args "network" "--network-config-dir=/etc/network-config"
## assert-podman-global-args "network" "--log-level=debug"

[Network]
GlobalArgs=--network-cmd-path=/usr/bin/network-cmd
GlobalArgs=--network-config-dir=/etc/network-config --log-level=debug
7 changes: 7 additions & 0 deletions test/e2e/quadlet/globalargs.volume
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-global-args "volume" "--volumepath=/var/lib/somewhere"
## assert-podman-global-args "volume" "--imagestore=/var/lib/store"
## assert-podman-global-args "volume" "--log-level=debug"

[Volume]
GlobalArgs=--volumepath=/var/lib/somewhere
GlobalArgs=--imagestore=/var/lib/store --log-level=debug
Loading