From 8e013c00122fae5354045bbb4097d9a1fe8fc441 Mon Sep 17 00:00:00 2001 From: axel7083 <42176370+axel7083@users.noreply.github.com> Date: Wed, 22 Oct 2025 16:09:47 +0200 Subject: [PATCH 1/2] feat(quadlet: kube): support multiple Yaml entries fixes https://github.com/containers/podman/issues/26274 Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> --- docs/source/markdown/podman-systemd.unit.5.md | 5 ++++ pkg/systemd/quadlet/quadlet.go | 29 +++++++++++++------ .../multiple-yaml-set-working-dir-yaml.kube | 4 +++ test/e2e/quadlet/multiple-yaml.kube | 10 +++++++ test/e2e/quadlet_test.go | 2 ++ 5 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube create mode 100644 test/e2e/quadlet/multiple-yaml.kube diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md index 0161656dc3..e7a149ab4f 100644 --- a/docs/source/markdown/podman-systemd.unit.5.md +++ b/docs/source/markdown/podman-systemd.unit.5.md @@ -1392,6 +1392,9 @@ Alternatively, users can explicitly set the `WorkingDirectory` field of the `Ser Please note that if the `WorkingDirectory` field of the `Service` group is set, Quadlet will not set it even if `SetWorkingDirectory` is set +Special case: +* If multiple `Yaml` path are provided only `unit` is supported. + ### `UserNS=` Set the user namespace mode for the container. This is equivalent to the Podman `--userns` option and @@ -1401,6 +1404,8 @@ generally has the form `MODE[:OPTIONS,...]`. The path, absolute or relative to the location of the unit file, to the Kubernetes YAML file to use. +This key can be listed multiple times. + ## Network units [Network] Network files are named with a `.network` extension and contain a section `[Network]` describing the diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go index 16e79cac6f..a56a631806 100644 --- a/pkg/systemd/quadlet/quadlet.go +++ b/pkg/systemd/quadlet/quadlet.go @@ -1201,14 +1201,19 @@ func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUse return nil, err } - yamlPath, ok := kube.Lookup(KubeGroup, KeyYaml) - if !ok || len(yamlPath) == 0 { + yamlPaths := kube.LookupAllStrv(KubeGroup, KeyYaml) + if len(yamlPaths) == 0 { return nil, fmt.Errorf("no Yaml key specified") } - yamlPath, err = getAbsolutePath(kube, yamlPath) - if err != nil { - return nil, err + // Convert all yaml paths to absolute paths + absoluteYamlPaths := make([]string, 0, len(yamlPaths)) + for _, yamlPath := range yamlPaths { + absPath, err := getAbsolutePath(kube, yamlPath) + if err != nil { + return nil, err + } + absoluteYamlPaths = append(absoluteYamlPaths, absPath) } // Only allow mixed or control-group, as nothing else works well @@ -1293,7 +1298,8 @@ func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUse handlePodmanArgs(kube, KubeGroup, execStart) - execStart.add(yamlPath) + // Add all YAML file paths to the command + execStart.add(absoluteYamlPaths...) service.AddCmdline(ServiceGroup, "ExecStart", execStart.Args) @@ -1307,7 +1313,8 @@ func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUse execStop.addBool("--force", kubeDownForce) } - execStop.add(yamlPath) + // Add all YAML file paths to the stop command + execStop.add(absoluteYamlPaths...) service.AddCmdline(ServiceGroup, "ExecStopPost", execStop.Args) _, err = handleSetWorkingDirectory(kube, service, KubeGroup) @@ -1988,10 +1995,14 @@ func handleSetWorkingDirectory(quadletUnitFile, serviceUnitFile *parser.UnitFile return "", fmt.Errorf("SetWorkingDirectory=%s is only supported in .kube files", setWorkingDirectory) } - relativeToFile, ok = quadletUnitFile.Lookup(quadletGroup, KeyYaml) - if !ok { + yamlPaths := quadletUnitFile.LookupAllStrv(KubeGroup, KeyYaml) + if len(yamlPaths) == 0 { return "", fmt.Errorf("no Yaml key specified") + } else if len(yamlPaths) != 1 { + return "", fmt.Errorf("SetWorkingDirectory=yaml is only supported when a single Yaml key is provided") } + + relativeToFile = yamlPaths[0] case "file": if quadletGroup != BuildGroup { return "", fmt.Errorf("SetWorkingDirectory=%s is only supported in .build files", setWorkingDirectory) diff --git a/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube b/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube new file mode 100644 index 0000000000..1a9f2a67ca --- /dev/null +++ b/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube @@ -0,0 +1,4 @@ +[Kube] +Yaml=foo.yml +Yaml=bar.yml +SetWorkingDirectory=yaml diff --git a/test/e2e/quadlet/multiple-yaml.kube b/test/e2e/quadlet/multiple-yaml.kube new file mode 100644 index 0000000000..d3e388798d --- /dev/null +++ b/test/e2e/quadlet/multiple-yaml.kube @@ -0,0 +1,10 @@ +## assert-podman-args "kube" +## assert-podman-args "play" +## assert-podman-final-args-regex .*/podman-e2e-.*/subtest-.*/quadlet/foo.yml .*/podman-e2e-.*/subtest-.*/quadlet/bar.yml +## assert-podman-stop-post-args "kube" +## assert-podman-stop-post-args "down" +## assert-podman-stop-post-final-args-regex .*/podman-e2e-.*/subtest-.*/quadlet/foo.yml .*/podman-e2e-.*/subtest-.*/quadlet/bar.yml + +[Kube] +Yaml=foo.yml +Yaml=bar.yml diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index ec22b9a953..59bdb7779f 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -996,6 +996,7 @@ BOGUS=foo Entry("Kube - Working Directory YAML Absolute Path", "workingdir-yaml-abs.kube"), Entry("Kube - Working Directory YAML Relative Path", "workingdir-yaml-rel.kube"), Entry("Kube - Working Directory Unit", "workingdir-unit.kube"), + Entry("Kube - Multiple YAML entries", "multiple-yaml.kube"), Entry("Kube - Working Directory already in Service", "workingdir-service.kube"), Entry("Kube - global args", "globalargs.kube"), Entry("Kube - Containers Conf Modules", "containersconfmodule.kube"), @@ -1139,6 +1140,7 @@ BOGUS=foo Entry("Volume - Quadlet image (.image) not found", "image-not-found.quadlet.volume", "converting \"image-not-found.quadlet.volume\": requested Quadlet image not-found.image was not found"), Entry("Kube - User Remap Manual", "remap-manual.kube", "converting \"remap-manual.kube\": RemapUsers=manual is not supported"), + Entry("Kube - Multiple Yaml and SetWorkingDir=yaml", "multiple-yaml-set-working-dir-yaml.kube", "converting \"multiple-yaml-set-working-dir-yaml.kube\": SetWorkingDirectory=yaml is only supported when a single Yaml key is provided quadlet-generator"), Entry("Network - Gateway not enough Subnet", "gateway.less-subnet.network", "converting \"gateway.less-subnet.network\": cannot set more gateways than subnets"), Entry("Network - Gateway without Subnet", "gateway.no-subnet.network", "converting \"gateway.no-subnet.network\": cannot set gateway or range without subnet"), From f957852e4a8260898205975942512b4f591489d0 Mon Sep 17 00:00:00 2001 From: axel7083 <42176370+axel7083@users.noreply.github.com> Date: Wed, 22 Oct 2025 18:07:03 +0200 Subject: [PATCH 2/2] fix: failing tests Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com> --- test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube | 3 +++ test/e2e/quadlet_test.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube b/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube index 1a9f2a67ca..c13d5accab 100644 --- a/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube +++ b/test/e2e/quadlet/multiple-yaml-set-working-dir-yaml.kube @@ -1,3 +1,6 @@ +## assert-failed +## assert-stderr-contains "SetWorkingDirectory=yaml is only supported when a single Yaml key is provided" + [Kube] Yaml=foo.yml Yaml=bar.yml diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index 59bdb7779f..e67c4ee8db 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -1140,7 +1140,7 @@ BOGUS=foo Entry("Volume - Quadlet image (.image) not found", "image-not-found.quadlet.volume", "converting \"image-not-found.quadlet.volume\": requested Quadlet image not-found.image was not found"), Entry("Kube - User Remap Manual", "remap-manual.kube", "converting \"remap-manual.kube\": RemapUsers=manual is not supported"), - Entry("Kube - Multiple Yaml and SetWorkingDir=yaml", "multiple-yaml-set-working-dir-yaml.kube", "converting \"multiple-yaml-set-working-dir-yaml.kube\": SetWorkingDirectory=yaml is only supported when a single Yaml key is provided quadlet-generator"), + Entry("Kube - Multiple Yaml and SetWorkingDir=yaml", "multiple-yaml-set-working-dir-yaml.kube", "converting \"multiple-yaml-set-working-dir-yaml.kube\": SetWorkingDirectory=yaml is only supported when a single Yaml key is provided"), Entry("Network - Gateway not enough Subnet", "gateway.less-subnet.network", "converting \"gateway.less-subnet.network\": cannot set more gateways than subnets"), Entry("Network - Gateway without Subnet", "gateway.no-subnet.network", "converting \"gateway.no-subnet.network\": cannot set gateway or range without subnet"),