diff --git a/cmd/quadlet/main.go b/cmd/quadlet/main.go index e2b021b669..457b3f0a4e 100644 --- a/cmd/quadlet/main.go +++ b/cmd/quadlet/main.go @@ -589,7 +589,7 @@ func process() error { warnIfAmbiguousName(unit, quadlet.ImageGroup) service, name, err = quadlet.ConvertImage(unit) case strings.HasSuffix(unit.Filename, ".pod"): - service, err = quadlet.ConvertPod(unit, unit.Filename, podsInfoMap) + service, err = quadlet.ConvertPod(unit, unit.Filename, podsInfoMap, resourceNames) default: Logf("Unsupported file type %q", unit.Filename) continue diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md index be6a969ef9..5bbc2b6974 100644 --- a/docs/source/markdown/podman-systemd.unit.5.md +++ b/docs/source/markdown/podman-systemd.unit.5.md @@ -709,8 +709,10 @@ Valid options for `[Pod]` are listed below: |-------------------------------------|----------------------------------------| | ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf | | GlobalArgs=--log-level=debug | --log-level=debug | +| Network=host | --network host | | PodmanArgs=\-\-cpus=2 | --cpus=2 | | PodName=name | --name=name | +| Volume=/source:/dest | --volume /source:/dest | Supported keys in the `[Pod]` section are: @@ -732,6 +734,19 @@ escaped to allow inclusion of whitespace and other control characters. This key can be listed multiple times. +### `Network=` + +Specify a custom network for the pod. +This has the same format as the `--network` option to `podman pod create`. +For example, use `host` to use the host network in the pod, or `none` to not set up networking in the pod. + +As a special case, if the `name` of the network ends with `.network`, Quadlet will look for the corresponding `.network` Quadlet unit. +If found, Quadlet will use the name of the Network set in the Unit, otherwise, `systemd-$name` is used. +The generated systemd service contains a dependency on the service unit generated for that `.network` unit, +or on `$name-network.service` if the `.network` unit is not found + +This key can be listed multiple times. + ### `PodmanArgs=` This key contains a list of arguments passed directly to the end of the `podman pod create` command @@ -753,6 +768,20 @@ prefix to avoid conflicts with user-managed containers. Please note that pods and containers cannot have the same name. So, if PodName is set, it must not conflict with any container. +### `Volume=` + +Mount a volume in the pod. This is equivalent to the Podman `--volume` option, and +generally has the form `[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]`. + +If `SOURCE-VOLUME` starts with `.`, Quadlet resolves the path relative to the location of the unit file. + +As a special case, if `SOURCE-VOLUME` ends with `.volume`, Quadlet will look for the corresponding `.volume` Quadlet unit. +If found, Quadlet will use the name of the Volume set in the Unit, otherwise, `systemd-$name` is used. +The generated systemd service contains a dependency on the service unit generated for that `.volume` unit, +or on `$name-volume.service` if the `.volume` unit is not found + +This key can be listed multiple times. + ## Kube units [Kube] Kube units are named with a `.kube` extension and contain a `[Kube]` section describing diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go index 59f2e56e08..349d55bc79 100644 --- a/pkg/systemd/quadlet/quadlet.go +++ b/pkg/systemd/quadlet/quadlet.go @@ -321,8 +321,10 @@ var ( supportedPodKeys = map[string]bool{ KeyContainersConfModule: true, KeyGlobalArgs: true, + KeyNetwork: true, KeyPodmanArgs: true, KeyPodName: true, + KeyVolume: true, } ) @@ -666,37 +668,8 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse podman.add("--tmpfs", tmpfs) } - volumes := container.LookupAll(ContainerGroup, KeyVolume) - for _, volume := range volumes { - parts := strings.SplitN(volume, ":", 3) - - source := "" - var dest string - options := "" - if len(parts) >= 2 { - source = parts[0] - dest = parts[1] - } else { - dest = parts[0] - } - if len(parts) >= 3 { - options = ":" + parts[2] - } - - if source != "" { - var err error - source, err = handleStorageSource(container, service, source, names) - if err != nil { - return nil, err - } - } - - podman.add("-v") - if source == "" { - podman.add(dest) - } else { - podman.addf("%s:%s%s", source, dest, options) - } + if err := addVolumes(container, service, ContainerGroup, names, podman); err != nil { + return nil, err } update, ok := container.Lookup(ContainerGroup, KeyAutoUpdate) @@ -1253,14 +1226,14 @@ func GetPodServiceName(podUnit *parser.UnitFile) string { return replaceExtension(podUnit.Filename, "", "", "-pod") } -func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*PodInfo) (*parser.UnitFile, error) { +func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*PodInfo, names map[string]string) (*parser.UnitFile, error) { podInfo, ok := podsInfoMap[podUnit.Filename] if !ok { return nil, fmt.Errorf("internal error while processing pod %s", podUnit.Filename) } service := podUnit.Dup() - service.Filename = replaceExtension(podInfo.ServiceName, ".service", "", "") + service.Filename = fmt.Sprintf("%s.service", podInfo.ServiceName) if podUnit.Path != "" { service.Add(UnitGroup, "SourcePath", podUnit.Path) @@ -1322,6 +1295,12 @@ func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*P "--replace", ) + addNetworks(podUnit, PodGroup, service, names, execStartPre) + + if err := addVolumes(podUnit, service, PodGroup, names, execStartPre); err != nil { + return nil, err + } + execStartPre.addf("--name=%s", podName) handlePodmanArgs(podUnit, PodGroup, execStartPre) @@ -1821,3 +1800,40 @@ func handlePod(quadletUnitFile, serviceUnitFile *parser.UnitFile, groupName stri } return nil } + +func addVolumes(quadletUnitFile, serviceUnitFile *parser.UnitFile, groupName string, names map[string]string, podman *PodmanCmdline) error { + volumes := quadletUnitFile.LookupAll(groupName, KeyVolume) + for _, volume := range volumes { + parts := strings.SplitN(volume, ":", 3) + + source := "" + var dest string + options := "" + if len(parts) >= 2 { + source = parts[0] + dest = parts[1] + } else { + dest = parts[0] + } + if len(parts) >= 3 { + options = ":" + parts[2] + } + + if source != "" { + var err error + source, err = handleStorageSource(quadletUnitFile, serviceUnitFile, source, names) + if err != nil { + return err + } + } + + podman.add("-v") + if source == "" { + podman.add(dest) + } else { + podman.addf("%s:%s%s", source, dest, options) + } + } + + return nil +} diff --git a/test/e2e/quadlet/network.pod b/test/e2e/quadlet/network.pod new file mode 100644 index 0000000000..edc89fcacf --- /dev/null +++ b/test/e2e/quadlet/network.pod @@ -0,0 +1,4 @@ +## assert-podman-pre-args "--network=host" + +[Pod] +Network=host diff --git a/test/e2e/quadlet/network.quadlet.pod b/test/e2e/quadlet/network.quadlet.pod new file mode 100644 index 0000000000..4c2b0bf7d6 --- /dev/null +++ b/test/e2e/quadlet/network.quadlet.pod @@ -0,0 +1,6 @@ +## assert-podman-pre-args "--network=systemd-basic" +## assert-key-is "Unit" "Requires" "basic-network.service" +## assert-key-is "Unit" "After" "basic-network.service" + +[Pod] +Network=basic.network diff --git a/test/e2e/quadlet/volume.pod b/test/e2e/quadlet/volume.pod new file mode 100644 index 0000000000..7950b0ab54 --- /dev/null +++ b/test/e2e/quadlet/volume.pod @@ -0,0 +1,15 @@ +## assert-podman-pre-args -v /host/dir:/container/volume +## assert-podman-pre-args -v /host/dir2:/container/volume2:Z +## assert-podman-pre-args-regex -v .*/podman_test.*/quadlet/host/dir3:/container/volume3 +## assert-podman-pre-args -v named:/container/named +## assert-podman-pre-args -v systemd-quadlet:/container/quadlet +## assert-podman-pre-args -v %h/container:/container/volume4 + +[Pod] +Volume=/host/dir:/container/volume +Volume=/host/dir2:/container/volume2:Z +Volume=./host/dir3:/container/volume3 +Volume=/container/empty +Volume=named:/container/named +Volume=quadlet.volume:/container/quadlet +Volume=%h/container:/container/volume4 diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index b887e5cf97..a89107e13d 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -901,7 +901,10 @@ BOGUS=foo 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, ""), ) })