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>
This commit is contained in:
axel7083
2025-10-22 16:09:47 +02:00
parent c15e84534e
commit 8e013c0012
5 changed files with 41 additions and 9 deletions

View File

@@ -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, Please note that if the `WorkingDirectory` field of the `Service` group is set,
Quadlet will not set it even if `SetWorkingDirectory` 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=` ### `UserNS=`
Set the user namespace mode for the container. This is equivalent to the Podman `--userns` option and 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. 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 units [Network]
Network files are named with a `.network` extension and contain a section `[Network]` describing the Network files are named with a `.network` extension and contain a section `[Network]` describing the

View File

@@ -1201,14 +1201,19 @@ func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUse
return nil, err return nil, err
} }
yamlPath, ok := kube.Lookup(KubeGroup, KeyYaml) yamlPaths := kube.LookupAllStrv(KubeGroup, KeyYaml)
if !ok || len(yamlPath) == 0 { if len(yamlPaths) == 0 {
return nil, fmt.Errorf("no Yaml key specified") return nil, fmt.Errorf("no Yaml key specified")
} }
yamlPath, err = getAbsolutePath(kube, yamlPath) // Convert all yaml paths to absolute paths
if err != nil { absoluteYamlPaths := make([]string, 0, len(yamlPaths))
return nil, err 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 // 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) handlePodmanArgs(kube, KubeGroup, execStart)
execStart.add(yamlPath) // Add all YAML file paths to the command
execStart.add(absoluteYamlPaths...)
service.AddCmdline(ServiceGroup, "ExecStart", execStart.Args) 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.addBool("--force", kubeDownForce)
} }
execStop.add(yamlPath) // Add all YAML file paths to the stop command
execStop.add(absoluteYamlPaths...)
service.AddCmdline(ServiceGroup, "ExecStopPost", execStop.Args) service.AddCmdline(ServiceGroup, "ExecStopPost", execStop.Args)
_, err = handleSetWorkingDirectory(kube, service, KubeGroup) _, 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) return "", fmt.Errorf("SetWorkingDirectory=%s is only supported in .kube files", setWorkingDirectory)
} }
relativeToFile, ok = quadletUnitFile.Lookup(quadletGroup, KeyYaml) yamlPaths := quadletUnitFile.LookupAllStrv(KubeGroup, KeyYaml)
if !ok { if len(yamlPaths) == 0 {
return "", fmt.Errorf("no Yaml key specified") 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": case "file":
if quadletGroup != BuildGroup { if quadletGroup != BuildGroup {
return "", fmt.Errorf("SetWorkingDirectory=%s is only supported in .build files", setWorkingDirectory) return "", fmt.Errorf("SetWorkingDirectory=%s is only supported in .build files", setWorkingDirectory)

View File

@@ -0,0 +1,4 @@
[Kube]
Yaml=foo.yml
Yaml=bar.yml
SetWorkingDirectory=yaml

View File

@@ -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

View File

@@ -996,6 +996,7 @@ BOGUS=foo
Entry("Kube - Working Directory YAML Absolute Path", "workingdir-yaml-abs.kube"), 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 YAML Relative Path", "workingdir-yaml-rel.kube"),
Entry("Kube - Working Directory Unit", "workingdir-unit.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 - Working Directory already in Service", "workingdir-service.kube"),
Entry("Kube - global args", "globalargs.kube"), Entry("Kube - global args", "globalargs.kube"),
Entry("Kube - Containers Conf Modules", "containersconfmodule.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("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 - 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 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"), Entry("Network - Gateway without Subnet", "gateway.no-subnet.network", "converting \"gateway.no-subnet.network\": cannot set gateway or range without subnet"),