diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md index 7fa1301248..6490554acd 100644 --- a/docs/source/markdown/podman-systemd.unit.5.md +++ b/docs/source/markdown/podman-systemd.unit.5.md @@ -863,6 +863,7 @@ Valid options for `[Pod]` are listed below: | PodmanArgs=\-\-cpus=2 | --cpus=2 | | PodName=name | --name=name | | PublishPort=50-59 | --publish 50-59 | +| ServiceName=name | Name the systemd unit `name.service` | | Volume=/source:/dest | --volume /source:/dest | Supported keys in the `[Pod]` section are: @@ -947,6 +948,14 @@ When using `host` networking via `Network=host`, the `PublishPort=` option canno This key can be listed multiple times. + +### `ServiceName=` + +By default, Quadlet will name the systemd service unit by appending `-pod` to the name of the Quadlet. +Setting this key overrides this behavior by instructing Quadlet to use the provided name. + +Note, the name should not include the `.service` file extension + ### `Volume=` Mount a volume in the pod. This is equivalent to the Podman `--volume` option, and diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go index 329f3883bc..f02ca54c8e 100644 --- a/pkg/systemd/quadlet/quadlet.go +++ b/pkg/systemd/quadlet/quadlet.go @@ -143,6 +143,7 @@ const ( KeySecurityLabelLevel = "SecurityLabelLevel" KeySecurityLabelNested = "SecurityLabelNested" KeySecurityLabelType = "SecurityLabelType" + KeyServiceName = "ServiceName" KeySetWorkingDirectory = "SetWorkingDirectory" KeyShmSize = "ShmSize" KeyStopSignal = "StopSignal" @@ -373,6 +374,7 @@ var ( KeyPodName: true, KeyPodmanArgs: true, KeyPublishPort: true, + KeyServiceName: true, KeyVolume: true, } ) @@ -1474,6 +1476,9 @@ func GetBuiltImageName(buildUnit *parser.UnitFile) string { } func GetPodServiceName(podUnit *parser.UnitFile) string { + if serviceName, ok := podUnit.Lookup(PodGroup, KeyServiceName); ok { + return serviceName + } return replaceExtension(podUnit.Filename, "", "", "-pod") } diff --git a/test/e2e/quadlet/service-name.pod b/test/e2e/quadlet/service-name.pod new file mode 100644 index 0000000000..6f2842e083 --- /dev/null +++ b/test/e2e/quadlet/service-name.pod @@ -0,0 +1,5 @@ +## assert-podman-pre-args "--name=test-pod" + +[Pod] +PodName=test-pod +ServiceName=test-pod diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index 7ba4e6269b..0450a8f459 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -36,24 +36,29 @@ func getGenericTemplateFile(fileName string) (bool, string) { return false, "" } -func loadQuadletTestcase(path string) *quadletTestcase { +func loadQuadletTestcase(path, serviceName string) *quadletTestcase { data, err := os.ReadFile(path) Expect(err).ToNot(HaveOccurred()) - base := filepath.Base(path) - ext := filepath.Ext(base) - service := base[:len(base)-len(ext)] - switch ext { - case ".volume": - service += "-volume" - case ".network": - service += "-network" - case ".image": - service += "-image" - case ".build": - service += "-build" - case ".pod": - service += "-pod" + var service string + if len(serviceName) > 0 { + service = serviceName + } else { + base := filepath.Base(path) + ext := filepath.Ext(base) + service = base[:len(base)-len(ext)] + switch ext { + case ".volume": + service += "-volume" + case ".network": + service += "-network" + case ".image": + service += "-image" + case ".build": + service += "-build" + case ".pod": + service += "-pod" + } } service += ".service" @@ -609,8 +614,8 @@ var _ = Describe("quadlet system generator", func() { generatedDir string quadletDir string - runQuadletTestCase = func(fileName string, exitCode int, errString string) { - testcase := loadQuadletTestcase(filepath.Join("quadlet", fileName)) + runQuadletTestCase = func(fileName string, exitCode int, errString string, serviceName string) { + testcase := loadQuadletTestcase(filepath.Join("quadlet", fileName), serviceName) // Write the tested file to the quadlet dir err = os.WriteFile(filepath.Join(quadletDir, fileName), testcase.data, 0644) @@ -670,7 +675,7 @@ var _ = Describe("quadlet system generator", func() { Describe("Running quadlet dryrun tests", func() { It("Should exit with an error because of no files are found to parse", func() { fileName := "basic.kube" - testcase := loadQuadletTestcase(filepath.Join("quadlet", fileName)) + testcase := loadQuadletTestcase(filepath.Join("quadlet", fileName), "") // Write the tested file to the quadlet dir err = os.WriteFile(filepath.Join(quadletDir, fileName), testcase.data, 0644) @@ -733,7 +738,7 @@ BOGUS=foo It("Should parse a kube file and print it to stdout", func() { fileName := "basic.kube" - testcase := loadQuadletTestcase(filepath.Join("quadlet", fileName)) + testcase := loadQuadletTestcase(filepath.Join("quadlet", fileName), "") // quadlet uses PODMAN env to get a stable podman path podmanPath, found := os.LookupEnv("PODMAN") @@ -788,229 +793,229 @@ BOGUS=foo DescribeTable("Running quadlet test case", runQuadletTestCase, - Entry("Basic container", "basic.container", 0, ""), - Entry("annotation.container", "annotation.container", 0, ""), - Entry("autoupdate.container", "autoupdate.container", 0, ""), - Entry("basepodman.container", "basepodman.container", 0, ""), - Entry("capabilities.container", "capabilities.container", 0, ""), - Entry("capabilities2.container", "capabilities2.container", 0, ""), - Entry("comment-with-continuation.container", "comment-with-continuation.container", 0, ""), - Entry("devices.container", "devices.container", 0, ""), - Entry("disableselinux.container", "disableselinux.container", 0, ""), - Entry("dns-options.container", "dns-options.container", 0, ""), - Entry("dns-search.container", "dns-search.container", 0, ""), - Entry("dns.container", "dns.container", 0, ""), - Entry("env-file.container", "env-file.container", 0, ""), - Entry("env-host-false.container", "env-host-false.container", 0, ""), - Entry("env-host.container", "env-host.container", 0, ""), - Entry("env.container", "env.container", 0, ""), - Entry("entrypoint.container", "entrypoint.container", 0, ""), - Entry("escapes.container", "escapes.container", 0, ""), - Entry("exec.container", "exec.container", 0, ""), - Entry("group-add.container", "group-add.container", 0, ""), - Entry("health.container", "health.container", 0, ""), - Entry("hostname.container", "hostname.container", 0, ""), - Entry("idmapping.container", "idmapping.container", 0, ""), - Entry("idmapping-with-remap.container", "idmapping-with-remap.container", 1, "converting \"idmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"), - Entry("image.container", "image.container", 0, ""), - Entry("install.container", "install.container", 0, ""), - Entry("ip.container", "ip.container", 0, ""), - Entry("label.container", "label.container", 0, ""), - Entry("line-continuation-whitespace.container", "line-continuation-whitespace.container", 0, ""), - Entry("logdriver.container", "logdriver.container", 0, ""), - Entry("logopt.container", "logopt.container", 0, ""), - Entry("mask.container", "mask.container", 0, ""), - Entry("mount.container", "mount.container", 0, ""), - Entry("name.container", "name.container", 0, ""), - Entry("nestedselinux.container", "nestedselinux.container", 0, ""), - Entry("network.container", "network.container", 0, ""), - 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("pod.non-quadlet.container", "pod.non-quadlet.container", 1, "converting \"pod.non-quadlet.container\": pod test-pod is not Quadlet based"), - Entry("pod.not-found.container", "pod.not-found.container", 1, "converting \"pod.not-found.container\": quadlet pod unit not-found.pod does not exist"), - Entry("podmanargs.container", "podmanargs.container", 0, ""), - Entry("ports.container", "ports.container", 0, ""), - Entry("ports_ipv6.container", "ports_ipv6.container", 0, ""), - Entry("pull.container", "pull.container", 0, ""), - Entry("quotes.container", "quotes.container", 0, ""), - Entry("readonly.container", "readonly.container", 0, ""), - Entry("readonly-tmpfs.container", "readonly-tmpfs.container", 0, ""), - Entry("readonly-notmpfs.container", "readonly-notmpfs.container", 0, ""), - Entry("readwrite-notmpfs.container", "readwrite-notmpfs.container", 0, ""), - Entry("volatiletmp-readwrite.container", "volatiletmp-readwrite.container", 0, ""), - Entry("volatiletmp-readonly.container", "volatiletmp-readonly.container", 0, ""), - Entry("remap-auto.container", "remap-auto.container", 0, ""), - Entry("remap-auto2.container", "remap-auto2.container", 0, ""), - Entry("remap-keep-id.container", "remap-keep-id.container", 0, ""), - Entry("remap-keep-id2.container", "remap-keep-id2.container", 0, ""), - Entry("remap-manual.container", "remap-manual.container", 0, ""), - Entry("rootfs.container", "rootfs.container", 0, ""), - Entry("seccomp.container", "seccomp.container", 0, ""), - Entry("secrets.container", "secrets.container", 0, ""), - Entry("selinux.container", "selinux.container", 0, ""), - Entry("shmsize.container", "shmsize.container", 0, ""), - Entry("shortname.container", "shortname.container", 0, "Warning: shortname.container specifies the image \"shortname\" which not a fully qualified image name. This is not ideal for performance and security reasons. See the podman-pull manpage discussion of short-name-aliases.conf for details."), - Entry("stopsigal.container", "stopsignal.container", 0, ""), - Entry("stoptimeout.container", "stoptimeout.container", 0, ""), - Entry("subidmapping.container", "subidmapping.container", 0, ""), - Entry("subidmapping-with-remap.container", "subidmapping-with-remap.container", 1, "converting \"subidmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"), - Entry("sysctl.container", "sysctl.container", 0, ""), - Entry("timezone.container", "timezone.container", 0, ""), - Entry("ulimit.container", "ulimit.container", 0, ""), - Entry("unmask.container", "unmask.container", 0, ""), - Entry("user.container", "user.container", 0, ""), - Entry("userns.container", "userns.container", 0, ""), - Entry("userns-with-remap.container", "userns-with-remap.container", 1, "converting \"userns-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"), - Entry("volume.container", "volume.container", 0, ""), - 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("template@.container", "template@.container", 0, ""), - Entry("template@instance.container", "template@instance.container", 0, ""), - Entry("Unit After Override", "unit-after-override.container", 0, ""), - Entry("NetworkAlias", "network-alias.container", 0, ""), + Entry("Basic container", "basic.container", 0, "", ""), + Entry("annotation.container", "annotation.container", 0, "", ""), + Entry("autoupdate.container", "autoupdate.container", 0, "", ""), + Entry("basepodman.container", "basepodman.container", 0, "", ""), + Entry("capabilities.container", "capabilities.container", 0, "", ""), + Entry("capabilities2.container", "capabilities2.container", 0, "", ""), + Entry("comment-with-continuation.container", "comment-with-continuation.container", 0, "", ""), + Entry("devices.container", "devices.container", 0, "", ""), + Entry("disableselinux.container", "disableselinux.container", 0, "", ""), + Entry("dns-options.container", "dns-options.container", 0, "", ""), + Entry("dns-search.container", "dns-search.container", 0, "", ""), + Entry("dns.container", "dns.container", 0, "", ""), + Entry("env-file.container", "env-file.container", 0, "", ""), + Entry("env-host-false.container", "env-host-false.container", 0, "", ""), + Entry("env-host.container", "env-host.container", 0, "", ""), + Entry("env.container", "env.container", 0, "", ""), + Entry("entrypoint.container", "entrypoint.container", 0, "", ""), + Entry("escapes.container", "escapes.container", 0, "", ""), + Entry("exec.container", "exec.container", 0, "", ""), + Entry("group-add.container", "group-add.container", 0, "", ""), + Entry("health.container", "health.container", 0, "", ""), + Entry("hostname.container", "hostname.container", 0, "", ""), + Entry("idmapping.container", "idmapping.container", 0, "", ""), + Entry("idmapping-with-remap.container", "idmapping-with-remap.container", 1, "converting \"idmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys", ""), + Entry("image.container", "image.container", 0, "", ""), + Entry("install.container", "install.container", 0, "", ""), + Entry("ip.container", "ip.container", 0, "", ""), + Entry("label.container", "label.container", 0, "", ""), + Entry("line-continuation-whitespace.container", "line-continuation-whitespace.container", 0, "", ""), + Entry("logdriver.container", "logdriver.container", 0, "", ""), + Entry("logopt.container", "logopt.container", 0, "", ""), + Entry("mask.container", "mask.container", 0, "", ""), + Entry("mount.container", "mount.container", 0, "", ""), + Entry("name.container", "name.container", 0, "", ""), + Entry("nestedselinux.container", "nestedselinux.container", 0, "", ""), + Entry("network.container", "network.container", 0, "", ""), + 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("pod.non-quadlet.container", "pod.non-quadlet.container", 1, "converting \"pod.non-quadlet.container\": pod test-pod is not Quadlet based", ""), + Entry("pod.not-found.container", "pod.not-found.container", 1, "converting \"pod.not-found.container\": quadlet pod unit not-found.pod does not exist", ""), + Entry("podmanargs.container", "podmanargs.container", 0, "", ""), + Entry("ports.container", "ports.container", 0, "", ""), + Entry("ports_ipv6.container", "ports_ipv6.container", 0, "", ""), + Entry("pull.container", "pull.container", 0, "", ""), + Entry("quotes.container", "quotes.container", 0, "", ""), + Entry("readonly.container", "readonly.container", 0, "", ""), + Entry("readonly-tmpfs.container", "readonly-tmpfs.container", 0, "", ""), + Entry("readonly-notmpfs.container", "readonly-notmpfs.container", 0, "", ""), + Entry("readwrite-notmpfs.container", "readwrite-notmpfs.container", 0, "", ""), + Entry("volatiletmp-readwrite.container", "volatiletmp-readwrite.container", 0, "", ""), + Entry("volatiletmp-readonly.container", "volatiletmp-readonly.container", 0, "", ""), + Entry("remap-auto.container", "remap-auto.container", 0, "", ""), + Entry("remap-auto2.container", "remap-auto2.container", 0, "", ""), + Entry("remap-keep-id.container", "remap-keep-id.container", 0, "", ""), + Entry("remap-keep-id2.container", "remap-keep-id2.container", 0, "", ""), + Entry("remap-manual.container", "remap-manual.container", 0, "", ""), + Entry("rootfs.container", "rootfs.container", 0, "", ""), + Entry("seccomp.container", "seccomp.container", 0, "", ""), + Entry("secrets.container", "secrets.container", 0, "", ""), + Entry("selinux.container", "selinux.container", 0, "", ""), + Entry("shmsize.container", "shmsize.container", 0, "", ""), + Entry("shortname.container", "shortname.container", 0, "Warning: shortname.container specifies the image \"shortname\" which not a fully qualified image name. This is not ideal for performance and security reasons. See the podman-pull manpage discussion of short-name-aliases.conf for details.", ""), + Entry("stopsigal.container", "stopsignal.container", 0, "", ""), + Entry("stoptimeout.container", "stoptimeout.container", 0, "", ""), + Entry("subidmapping.container", "subidmapping.container", 0, "", ""), + Entry("subidmapping-with-remap.container", "subidmapping-with-remap.container", 1, "converting \"subidmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys", ""), + Entry("sysctl.container", "sysctl.container", 0, "", ""), + Entry("timezone.container", "timezone.container", 0, "", ""), + Entry("ulimit.container", "ulimit.container", 0, "", ""), + Entry("unmask.container", "unmask.container", 0, "", ""), + Entry("user.container", "user.container", 0, "", ""), + Entry("userns.container", "userns.container", 0, "", ""), + Entry("userns-with-remap.container", "userns-with-remap.container", 1, "converting \"userns-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys", ""), + Entry("volume.container", "volume.container", 0, "", ""), + 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("template@.container", "template@.container", 0, "", ""), + Entry("template@instance.container", "template@instance.container", 0, "", ""), + Entry("Unit After Override", "unit-after-override.container", 0, "", ""), + Entry("NetworkAlias", "network-alias.container", 0, "", ""), - Entry("basic.volume", "basic.volume", 0, ""), - Entry("device-copy.volume", "device-copy.volume", 0, ""), - Entry("device.volume", "device.volume", 0, ""), - Entry("label.volume", "label.volume", 0, ""), - Entry("name.volume", "name.volume", 0, ""), - Entry("podmanargs.volume", "podmanargs.volume", 0, ""), - Entry("uid.volume", "uid.volume", 0, ""), - Entry("image.volume", "image.volume", 0, ""), - Entry("image-no-image.volume", "image-no-image.volume", 1, "converting \"image-no-image.volume\": the key Image is mandatory when using the image driver"), - Entry("Volume - global args", "globalargs.volume", 0, ""), - Entry("Volume - Containers Conf Modules", "containersconfmodule.volume", 0, ""), - Entry("Volume - Quadlet image (.build) not found", "build-not-found.quadlet.volume", 1, "converting \"build-not-found.quadlet.volume\": requested Quadlet image not-found.build was not found"), - Entry("Volume - Quadlet image (.image) not found", "image-not-found.quadlet.volume", 1, "converting \"image-not-found.quadlet.volume\": requested Quadlet image not-found.image was not found"), + Entry("basic.volume", "basic.volume", 0, "", ""), + Entry("device-copy.volume", "device-copy.volume", 0, "", ""), + Entry("device.volume", "device.volume", 0, "", ""), + Entry("label.volume", "label.volume", 0, "", ""), + Entry("name.volume", "name.volume", 0, "", ""), + Entry("podmanargs.volume", "podmanargs.volume", 0, "", ""), + Entry("uid.volume", "uid.volume", 0, "", ""), + Entry("image.volume", "image.volume", 0, "", ""), + Entry("image-no-image.volume", "image-no-image.volume", 1, "converting \"image-no-image.volume\": the key Image is mandatory when using the image driver", ""), + Entry("Volume - global args", "globalargs.volume", 0, "", ""), + Entry("Volume - Containers Conf Modules", "containersconfmodule.volume", 0, "", ""), + Entry("Volume - Quadlet image (.build) not found", "build-not-found.quadlet.volume", 1, "converting \"build-not-found.quadlet.volume\": requested Quadlet image not-found.build was not found", ""), + Entry("Volume - Quadlet image (.image) not found", "image-not-found.quadlet.volume", 1, "converting \"image-not-found.quadlet.volume\": requested Quadlet image not-found.image was not found", ""), - Entry("Absolute Path", "absolute.path.kube", 0, ""), - Entry("Basic kube", "basic.kube", 0, ""), - Entry("Kube - ConfigMap", "configmap.kube", 0, ""), - Entry("Kube - Exit Code Propagation", "exit_code_propagation.kube", 0, ""), - Entry("Kube - Logdriver", "logdriver.kube", 0, ""), - Entry("Kube - Logopt", "logopt.kube", 0, ""), - Entry("Kube - Network", "network.kube", 0, ""), - Entry("Kube - PodmanArgs", "podmanargs.kube", 0, ""), - Entry("Kube - Publish IPv4 ports", "ports.kube", 0, ""), - Entry("Kube - Publish IPv6 ports", "ports_ipv6.kube", 0, ""), - Entry("Kube - Quadlet Network", "network.quadlet.kube", 0, ""), - Entry("Kube - User Remap Auto with IDs", "remap-auto2.kube", 0, ""), - Entry("Kube - User Remap Auto", "remap-auto.kube", 0, ""), - Entry("Kube - User Remap Manual", "remap-manual.kube", 1, "converting \"remap-manual.kube\": RemapUsers=manual is not supported"), - Entry("Syslog Identifier", "syslog.identifier.kube", 0, ""), - Entry("Kube - Working Directory YAML Absolute Path", "workingdir-yaml-abs.kube", 0, ""), - Entry("Kube - Working Directory YAML Relative Path", "workingdir-yaml-rel.kube", 0, ""), - Entry("Kube - Working Directory Unit", "workingdir-unit.kube", 0, ""), - Entry("Kube - Working Directory already in Service", "workingdir-service.kube", 0, ""), - Entry("Kube - global args", "globalargs.kube", 0, ""), - Entry("Kube - Containers Conf Modules", "containersconfmodule.kube", 0, ""), - Entry("Kube - Service Type=oneshot", "oneshot.kube", 0, ""), - Entry("Kube - Down force", "downforce.kube", 0, ""), + Entry("Absolute Path", "absolute.path.kube", 0, "", ""), + Entry("Basic kube", "basic.kube", 0, "", ""), + Entry("Kube - ConfigMap", "configmap.kube", 0, "", ""), + Entry("Kube - Exit Code Propagation", "exit_code_propagation.kube", 0, "", ""), + Entry("Kube - Logdriver", "logdriver.kube", 0, "", ""), + Entry("Kube - Logopt", "logopt.kube", 0, "", ""), + Entry("Kube - Network", "network.kube", 0, "", ""), + Entry("Kube - PodmanArgs", "podmanargs.kube", 0, "", ""), + Entry("Kube - Publish IPv4 ports", "ports.kube", 0, "", ""), + Entry("Kube - Publish IPv6 ports", "ports_ipv6.kube", 0, "", ""), + Entry("Kube - Quadlet Network", "network.quadlet.kube", 0, "", ""), + Entry("Kube - User Remap Auto with IDs", "remap-auto2.kube", 0, "", ""), + Entry("Kube - User Remap Auto", "remap-auto.kube", 0, "", ""), + Entry("Kube - User Remap Manual", "remap-manual.kube", 1, "converting \"remap-manual.kube\": RemapUsers=manual is not supported", ""), + Entry("Syslog Identifier", "syslog.identifier.kube", 0, "", ""), + Entry("Kube - Working Directory YAML Absolute Path", "workingdir-yaml-abs.kube", 0, "", ""), + Entry("Kube - Working Directory YAML Relative Path", "workingdir-yaml-rel.kube", 0, "", ""), + Entry("Kube - Working Directory Unit", "workingdir-unit.kube", 0, "", ""), + Entry("Kube - Working Directory already in Service", "workingdir-service.kube", 0, "", ""), + Entry("Kube - global args", "globalargs.kube", 0, "", ""), + Entry("Kube - Containers Conf Modules", "containersconfmodule.kube", 0, "", ""), + Entry("Kube - Service Type=oneshot", "oneshot.kube", 0, "", ""), + Entry("Kube - Down force", "downforce.kube", 0, "", ""), - Entry("Network - Basic", "basic.network", 0, ""), - Entry("Network - Disable DNS", "disable-dns.network", 0, ""), - Entry("Network - DNS", "dns.network", 0, ""), - Entry("Network - Driver", "driver.network", 0, ""), - Entry("Network - Gateway not enough Subnet", "gateway.less-subnet.network", 1, "converting \"gateway.less-subnet.network\": cannot set more gateways than subnets"), - Entry("Network - Gateway without Subnet", "gateway.no-subnet.network", 1, "converting \"gateway.no-subnet.network\": cannot set gateway or range without subnet"), - Entry("Network - Gateway", "gateway.network", 0, ""), - Entry("Network - IPAM Driver", "ipam-driver.network", 0, ""), - Entry("Network - IPv6", "ipv6.network", 0, ""), - Entry("Network - Internal network", "internal.network", 0, ""), - Entry("Network - Label", "label.network", 0, ""), - Entry("Network - Multiple Options", "options.multiple.network", 0, ""), - Entry("Network - Name", "name.network", 0, ""), - Entry("Network - Options", "options.network", 0, ""), - Entry("Network - PodmanArgs", "podmanargs.network", 0, ""), - Entry("Network - Range not enough Subnet", "range.less-subnet.network", 1, "converting \"range.less-subnet.network\": cannot set more ranges than subnets"), - Entry("Network - Range without Subnet", "range.no-subnet.network", 1, "converting \"range.no-subnet.network\": cannot set gateway or range without subnet"), - Entry("Network - Range", "range.network", 0, ""), - Entry("Network - Subnets", "subnets.network", 0, ""), - Entry("Network - multiple subnet, gateway and range", "subnet-trio.multiple.network", 0, ""), - Entry("Network - subnet, gateway and range", "subnet-trio.network", 0, ""), - Entry("Network - global args", "globalargs.network", 0, ""), - Entry("Network - Containers Conf Modules", "containersconfmodule.network", 0, ""), + Entry("Network - Basic", "basic.network", 0, "", ""), + Entry("Network - Disable DNS", "disable-dns.network", 0, "", ""), + Entry("Network - DNS", "dns.network", 0, "", ""), + Entry("Network - Driver", "driver.network", 0, "", ""), + Entry("Network - Gateway not enough Subnet", "gateway.less-subnet.network", 1, "converting \"gateway.less-subnet.network\": cannot set more gateways than subnets", ""), + Entry("Network - Gateway without Subnet", "gateway.no-subnet.network", 1, "converting \"gateway.no-subnet.network\": cannot set gateway or range without subnet", ""), + Entry("Network - Gateway", "gateway.network", 0, "", ""), + Entry("Network - IPAM Driver", "ipam-driver.network", 0, "", ""), + Entry("Network - IPv6", "ipv6.network", 0, "", ""), + Entry("Network - Internal network", "internal.network", 0, "", ""), + Entry("Network - Label", "label.network", 0, "", ""), + Entry("Network - Multiple Options", "options.multiple.network", 0, "", ""), + Entry("Network - Name", "name.network", 0, "", ""), + Entry("Network - Options", "options.network", 0, "", ""), + Entry("Network - PodmanArgs", "podmanargs.network", 0, "", ""), + Entry("Network - Range not enough Subnet", "range.less-subnet.network", 1, "converting \"range.less-subnet.network\": cannot set more ranges than subnets", ""), + Entry("Network - Range without Subnet", "range.no-subnet.network", 1, "converting \"range.no-subnet.network\": cannot set gateway or range without subnet", ""), + Entry("Network - Range", "range.network", 0, "", ""), + Entry("Network - Subnets", "subnets.network", 0, "", ""), + Entry("Network - multiple subnet, gateway and range", "subnet-trio.multiple.network", 0, "", ""), + Entry("Network - subnet, gateway and range", "subnet-trio.network", 0, "", ""), + Entry("Network - global args", "globalargs.network", 0, "", ""), + Entry("Network - Containers Conf Modules", "containersconfmodule.network", 0, "", ""), - Entry("Image - Basic", "basic.image", 0, ""), - Entry("Image - No Image", "no-image.image", 1, "converting \"no-image.image\": no Image key specified"), - Entry("Image - Architecture", "arch.image", 0, ""), - Entry("Image - Auth File", "auth.image", 0, ""), - Entry("Image - Certificates", "certs.image", 0, ""), - Entry("Image - Credentials", "creds.image", 0, ""), - Entry("Image - Decryption Key", "decrypt.image", 0, ""), - Entry("Image - OS Key", "os.image", 0, ""), - Entry("Image - Variant Key", "variant.image", 0, ""), - Entry("Image - All Tags", "all-tags.image", 0, ""), - Entry("Image - TLS Verify", "tls-verify.image", 0, ""), - Entry("Image - Arch and OS", "arch-os.image", 0, ""), - Entry("Image - global args", "globalargs.image", 0, ""), - Entry("Image - Containers Conf Modules", "containersconfmodule.image", 0, ""), - Entry("Image - Unit After Override", "unit-after-override.image", 0, ""), + Entry("Image - Basic", "basic.image", 0, "", ""), + Entry("Image - No Image", "no-image.image", 1, "converting \"no-image.image\": no Image key specified", ""), + Entry("Image - Architecture", "arch.image", 0, "", ""), + Entry("Image - Auth File", "auth.image", 0, "", ""), + Entry("Image - Certificates", "certs.image", 0, "", ""), + Entry("Image - Credentials", "creds.image", 0, "", ""), + Entry("Image - Decryption Key", "decrypt.image", 0, "", ""), + Entry("Image - OS Key", "os.image", 0, "", ""), + Entry("Image - Variant Key", "variant.image", 0, "", ""), + Entry("Image - All Tags", "all-tags.image", 0, "", ""), + Entry("Image - TLS Verify", "tls-verify.image", 0, "", ""), + Entry("Image - Arch and OS", "arch-os.image", 0, "", ""), + Entry("Image - global args", "globalargs.image", 0, "", ""), + Entry("Image - Containers Conf Modules", "containersconfmodule.image", 0, "", ""), + Entry("Image - Unit After Override", "unit-after-override.image", 0, "", ""), - Entry("Build - Basic", "basic.build", 0, ""), - Entry("Build - Annotation Key", "annotation.build", 0, ""), - Entry("Build - Arch Key", "arch.build", 0, ""), - Entry("Build - AuthFile Key", "authfile.build", 0, ""), - Entry("Build - DNS Key", "dns.build", 0, ""), - Entry("Build - DNSOptions Key", "dns-options.build", 0, ""), - Entry("Build - DNSSearch Key", "dns-search.build", 0, ""), - Entry("Build - Environment Key", "env.build", 0, ""), - Entry("Build - File Key absolute", "file-abs.build", 0, ""), - Entry("Build - File Key relative", "file-rel.build", 0, ""), - Entry("Build - File Key relative no WD", "file-rel-no-wd.build", 1, "converting \"file-rel-no-wd.build\": relative path in File key requires SetWorkingDirectory key to be set"), - Entry("Build - File Key HTTP(S) URL", "file-https.build", 0, ""), - Entry("Build - ForceRM Key", "force-rm.build", 0, ""), - Entry("Build - GlobalArgs", "globalargs.build", 0, ""), - Entry("Build - GroupAdd Key", "group-add.build", 0, ""), - Entry("Build - Containers Conf Modules", "containersconfmodule.build", 0, ""), - Entry("Build - Label Key", "label.build", 0, ""), - Entry("Build - Neither WorkingDirectory nor File Key", "neither-workingdirectory-nor-file.build", 1, "converting \"neither-workingdirectory-nor-file.build\": neither SetWorkingDirectory, nor File key specified"), - Entry("Build - Network Key host", "network.build", 0, ""), - Entry("Build - Network Key quadlet", "network.quadlet.build", 0, ""), - Entry("Build - No ImageTag Key", "no-imagetag.build", 1, "converting \"no-imagetag.build\": no ImageTag key specified"), - Entry("Build - PodmanArgs", "podmanargs.build", 0, ""), - Entry("Build - Pull Key", "pull.build", 0, ""), - Entry("Build - Secrets", "secrets.build", 0, ""), - Entry("Build - SetWorkingDirectory is absolute path", "setworkingdirectory-is-abs.build", 0, ""), - Entry("Build - SetWorkingDirectory is absolute File= path", "setworkingdirectory-is-file-abs.build", 0, ""), - Entry("Build - SetWorkingDirectory is relative path", "setworkingdirectory-is-rel.build", 0, ""), - Entry("Build - SetWorkingDirectory is relative File= path", "setworkingdirectory-is-file-rel.build", 0, ""), - Entry("Build - SetWorkingDirectory is https://.git URL", "setworkingdirectory-is-https-git.build", 0, ""), - Entry("Build - SetWorkingDirectory is git:// URL", "setworkingdirectory-is-git.build", 0, ""), - Entry("Build - SetWorkingDirectory is github.com URL", "setworkingdirectory-is-github.build", 0, ""), - Entry("Build - SetWorkingDirectory is archive URL", "setworkingdirectory-is-archive.build", 0, ""), - Entry("Build - Target Key", "target.build", 0, ""), - Entry("Build - TLSVerify Key", "tls-verify.build", 0, ""), - Entry("Build - Variant Key", "variant.build", 0, ""), - Entry("Build - Volume Key", "volume.build", 0, ""), - Entry("Build - Volume Key quadlet", "volume.quadlet.build", 0, ""), + Entry("Build - Basic", "basic.build", 0, "", ""), + Entry("Build - Annotation Key", "annotation.build", 0, "", ""), + Entry("Build - Arch Key", "arch.build", 0, "", ""), + Entry("Build - AuthFile Key", "authfile.build", 0, "", ""), + Entry("Build - DNS Key", "dns.build", 0, "", ""), + Entry("Build - DNSOptions Key", "dns-options.build", 0, "", ""), + Entry("Build - DNSSearch Key", "dns-search.build", 0, "", ""), + Entry("Build - Environment Key", "env.build", 0, "", ""), + Entry("Build - File Key absolute", "file-abs.build", 0, "", ""), + Entry("Build - File Key relative", "file-rel.build", 0, "", ""), + Entry("Build - File Key relative no WD", "file-rel-no-wd.build", 1, "converting \"file-rel-no-wd.build\": relative path in File key requires SetWorkingDirectory key to be set", ""), + Entry("Build - File Key HTTP(S) URL", "file-https.build", 0, "", ""), + Entry("Build - ForceRM Key", "force-rm.build", 0, "", ""), + Entry("Build - GlobalArgs", "globalargs.build", 0, "", ""), + Entry("Build - GroupAdd Key", "group-add.build", 0, "", ""), + Entry("Build - Containers Conf Modules", "containersconfmodule.build", 0, "", ""), + Entry("Build - Label Key", "label.build", 0, "", ""), + Entry("Build - Neither WorkingDirectory nor File Key", "neither-workingdirectory-nor-file.build", 1, "converting \"neither-workingdirectory-nor-file.build\": neither SetWorkingDirectory, nor File key specified", ""), + Entry("Build - Network Key host", "network.build", 0, "", ""), + Entry("Build - Network Key quadlet", "network.quadlet.build", 0, "", ""), + Entry("Build - No ImageTag Key", "no-imagetag.build", 1, "converting \"no-imagetag.build\": no ImageTag key specified", ""), + Entry("Build - PodmanArgs", "podmanargs.build", 0, "", ""), + Entry("Build - Pull Key", "pull.build", 0, "", ""), + Entry("Build - Secrets", "secrets.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is absolute path", "setworkingdirectory-is-abs.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is absolute File= path", "setworkingdirectory-is-file-abs.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is relative path", "setworkingdirectory-is-rel.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is relative File= path", "setworkingdirectory-is-file-rel.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is https://.git URL", "setworkingdirectory-is-https-git.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is git:// URL", "setworkingdirectory-is-git.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is github.com URL", "setworkingdirectory-is-github.build", 0, "", ""), + Entry("Build - SetWorkingDirectory is archive URL", "setworkingdirectory-is-archive.build", 0, "", ""), + Entry("Build - Target Key", "target.build", 0, "", ""), + Entry("Build - TLSVerify Key", "tls-verify.build", 0, "", ""), + Entry("Build - Variant Key", "variant.build", 0, "", ""), + Entry("Build - Volume Key", "volume.build", 0, "", ""), + Entry("Build - Volume Key quadlet", "volume.quadlet.build", 0, "", ""), - Entry("basic.pod", "basic.pod", 0, ""), - Entry("name.pod", "name.pod", 0, ""), - Entry("network.pod", "network.pod", 0, ""), - Entry("network-quadlet.pod", "network.quadlet.pod", 0, ""), - Entry("podmanargs.pod", "podmanargs.pod", 0, ""), - Entry("volume.pod", "volume.pod", 0, ""), - Entry("Pod - NetworkAlias", "network-alias.pod", 0, ""), + Entry("basic.pod", "basic.pod", 0, "", ""), + Entry("name.pod", "name.pod", 0, "", ""), + Entry("network.pod", "network.pod", 0, "", ""), + Entry("network-quadlet.pod", "network.quadlet.pod", 0, "", ""), + Entry("podmanargs.pod", "podmanargs.pod", 0, "", ""), + Entry("volume.pod", "volume.pod", 0, "", ""), + Entry("Pod - NetworkAlias", "network-alias.pod", 0, "", ""), ) DescribeTable("Running quadlet test case with dependencies", func(fileName string, exitCode int, errString string, dependencyFiles []string) { // Write additional files this test depends on to the quadlet dir for _, dependencyFileName := range dependencyFiles { - dependencyTestCase := loadQuadletTestcase(filepath.Join("quadlet", dependencyFileName)) + dependencyTestCase := loadQuadletTestcase(filepath.Join("quadlet", dependencyFileName), "") err = os.WriteFile(filepath.Join(quadletDir, dependencyFileName), dependencyTestCase.data, 0644) Expect(err).ToNot(HaveOccurred()) } - runQuadletTestCase(fileName, exitCode, errString) + runQuadletTestCase(fileName, exitCode, errString, "") }, Entry("Volume - Quadlet image (.build)", "build.quadlet.volume", 0, "", []string{"basic.build"}), Entry("Volume - Quadlet image (.image)", "image.quadlet.volume", 0, "", []string{"basic.image"}),