Skip to content

Commit de61858

Browse files
committed
Quadlet - Support template dependency
Add support for Volumes and Networks Add e2e and system tests Resolves: #25136 Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
1 parent a118fdf commit de61858

File tree

7 files changed

+111
-10
lines changed

7 files changed

+111
-10
lines changed

pkg/systemd/quadlet/quadlet.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,19 @@ func getContainerName(container *parser.UnitFile) string {
908908
return containerName
909909
}
910910

911+
// Get the unresolved resouce name that may contain '%'.
912+
func getResourceName(unit *parser.UnitFile, group, key string) string {
913+
resourceName, ok := unit.Lookup(group, key)
914+
if !ok || len(resourceName) == 0 {
915+
resourceName = removeExtension(unit.Filename, "systemd-", "")
916+
// By default, We want to name the resource by the service name.
917+
if strings.Contains(unit.Filename, "@") {
918+
resourceName = resourceName[:len(resourceName)-1] + "-%i"
919+
}
920+
}
921+
return resourceName
922+
}
923+
911924
// Get the resolved container name that contains no '%'.
912925
// Returns an empty string if not resolvable.
913926
func GetContainerResourceName(container *parser.UnitFile) string {
@@ -954,10 +967,7 @@ func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[stri
954967
}
955968

956969
// Derive network name from unit name (with added prefix), or use user-provided name.
957-
networkName, ok := network.Lookup(NetworkGroup, KeyNetworkName)
958-
if !ok || len(networkName) == 0 {
959-
networkName = removeExtension(name, "systemd-", "")
960-
}
970+
networkName := getResourceName(network, NetworkGroup, KeyNetworkName)
961971

962972
if network.LookupBooleanWithDefault(NetworkGroup, KeyNetworkDeleteOnStop, false) {
963973
serviceStopPostCmd := createBasePodmanCommand(network, NetworkGroup)
@@ -1046,10 +1056,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string
10461056
}
10471057

10481058
// Derive volume name from unit name (with added prefix), or use user-provided name.
1049-
volumeName, ok := volume.Lookup(VolumeGroup, KeyVolumeName)
1050-
if !ok || len(volumeName) == 0 {
1051-
volumeName = removeExtension(name, "systemd-", "")
1052-
}
1059+
volumeName := getResourceName(volume, VolumeGroup, KeyVolumeName)
10531060

10541061
podman := createBasePodmanCommand(volume, VolumeGroup)
10551062

@@ -1503,7 +1510,12 @@ func getServiceName(quadletUnitFile *parser.UnitFile, groupName string, defaultE
15031510
if serviceName, ok := quadletUnitFile.Lookup(groupName, KeyServiceName); ok {
15041511
return serviceName
15051512
}
1506-
return removeExtension(quadletUnitFile.Filename, "", defaultExtraSuffix)
1513+
baseServiceName := removeExtension(quadletUnitFile.Filename, "", "")
1514+
if baseServiceName[len(baseServiceName)-1] == '@' {
1515+
baseServiceName = baseServiceName[:len(baseServiceName)-1]
1516+
defaultExtraSuffix = defaultExtraSuffix + "@"
1517+
}
1518+
return baseServiceName + defaultExtraSuffix
15071519
}
15081520

15091521
func GetPodResourceName(podUnit *parser.UnitFile) string {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## assert-podman-args-key-val "--mount" "," "type=volume,source=systemd-template-dependency-%i,destination=/path/in/container,ro=true"
2+
## assert-podman-args -v systemd-template-dependency-%i:/container/quadlet
3+
## assert-podman-args "--network" "systemd-template-dependency-%i"
4+
## assert-key-is "Unit" "Requires" "template-dependency-network@.service" "template-dependency-volume@.service" "template-dependency-volume@.service"
5+
6+
[Container]
7+
Image=localhost/imagename
8+
Mount=type=volume,source=template-dependency@.volume,destination=/path/in/container,ro=true
9+
Volume=template-dependency@.volume:/container/quadlet
10+
Network=template-dependency@.network
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Network]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Volume]

test/e2e/quadlet_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,14 @@ BOGUS=foo
11951195
"basic.volume",
11961196
},
11971197
),
1198+
Entry(
1199+
"Container - Template with Volume Template dependency",
1200+
"template-dependency@.container",
1201+
[]string{
1202+
"template-dependency@.volume",
1203+
"template-dependency@.network",
1204+
},
1205+
),
11981206

11991207
Entry("Volume - Quadlet image (.build)", "build.quadlet.volume", []string{"basic.build"}),
12001208
Entry("Volume - Quadlet image (.image)", "image.quadlet.volume", []string{"basic.image"}),

test/system/252-quadlet.bats

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,68 @@ EOF
437437
run_podman volume rm $volume_name
438438
}
439439

440+
# A quadlet container template depends on a quadlet volume template
441+
@test "quadlet - template volume dependency" {
442+
# Save the unit name to use as the volume template for the container template
443+
local quadlet_vol_unit=dep_$(safename)@.volume
444+
local quadlet_vol_file=$PODMAN_TMPDIR/${quadlet_vol_unit}
445+
cat > $quadlet_vol_file <<EOF
446+
[Volume]
447+
EOF
448+
449+
local quadlet_tmpdir=$(mktemp -d --tmpdir=$PODMAN_TMPDIR quadlet.XXXXXX)
450+
# Have quadlet create the systemd unit file for the volume template unit
451+
run_quadlet "$quadlet_vol_file" "$quadlet_tmpdir"
452+
453+
# Save the volume service name since the variable will be overwritten
454+
local vol_service=$QUADLET_SERVICE_NAME
455+
local volume_name=systemd-$(basename $quadlet_vol_file .volume)
456+
# For template units, the volume name should have -%i appended
457+
volume_name=${volume_name%@}-%i
458+
459+
local quadlet_file=$PODMAN_TMPDIR/user_$(safename)@.container
460+
cat > $quadlet_file <<EOF
461+
[Container]
462+
Image=$IMAGE
463+
Exec=top
464+
Volume=$quadlet_vol_unit:/tmp
465+
EOF
466+
467+
# Have quadlet create the systemd unit file for the container template unit
468+
run_quadlet "$quadlet_file" "$quadlet_tmpdir"
469+
470+
# Save the container service name for readability
471+
local container_service=$QUADLET_SERVICE_NAME
472+
473+
# Create instance names for the template units
474+
local instance_name="test"
475+
local vol_service_instance="${vol_service%@*}@${instance_name}.service"
476+
local container_service_instance="${container_service%@*}@${instance_name}.service"
477+
local volume_name_instance="systemd-dep_$(safename)-${instance_name}"
478+
479+
# Volume should not exist
480+
run_podman 1 volume exists ${volume_name_instance}
481+
482+
# Start the container service instance which should also trigger the start of the volume service instance
483+
service_setup $container_service_instance
484+
485+
# Volume system unit instance should be active
486+
run systemctl show --property=ActiveState "$vol_service_instance"
487+
assert "$output" = "ActiveState=active" \
488+
"volume template instance should be active via dependency"
489+
490+
# Volume should exist
491+
run_podman volume exists ${volume_name_instance}
492+
493+
# Shutdown the service and remove the volume
494+
service_cleanup $container_service_instance failed
495+
run_podman volume rm $volume_name_instance
496+
for UNIT_FILE in ${UNIT_FILES[@]}; do
497+
rm $UNIT_FILE
498+
done
499+
UNIT_FILES=()
500+
}
501+
440502
# A quadlet container depends on a named quadlet volume
441503
@test "quadlet - named volume dependency" {
442504
local volume_name="v-$(safename)"

test/system/helpers.systemd.bash

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ quadlet_to_service_name() {
115115
local extension="${filename##*.}"
116116
local filename="${filename%.*}"
117117
local suffix=""
118+
local is_template=""
119+
120+
# Check if this is a template unit (ends with @)
121+
if [[ "$filename" == *@ ]]; then
122+
is_template="@"
123+
filename="${filename%@}"
124+
fi
118125

119126
if [ "$extension" == "volume" ]; then
120127
suffix="-volume"
@@ -128,5 +135,5 @@ quadlet_to_service_name() {
128135
suffix="-build"
129136
fi
130137

131-
echo "$filename$suffix.service"
138+
echo "$filename$suffix$is_template.service"
132139
}

0 commit comments

Comments
 (0)