Quadlet - Allow the user to override the default service name

Add support for the ServiceName key for all unit types
Extend the PodInfo struct into UnitInfo to consolidate all prepopulated data into a single map
Use the NodesInfo map instead of the resourceName
Update the UnitInfo in the convert function instead of returning it
No need to replace extension anymore just remove it
All e2e tests with dependencies on other Quadlet files moved to a separate section
Add the capability of overriding the service name in the test
Add e2e tests for the new functionality
Adjust integration tests
Update the MAN page

Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
This commit is contained in:
Ygal Blum
2024-08-05 07:12:54 +03:00
parent 4e788bc611
commit 795851edd3
25 changed files with 409 additions and 171 deletions

View File

@@ -486,34 +486,47 @@ func warnIfAmbiguousName(unit *parser.UnitFile, group string) {
}
}
func generatePodsInfoMap(units []*parser.UnitFile) map[string]*quadlet.PodInfo {
podsInfoMap := make(map[string]*quadlet.PodInfo)
func generateUnitsInfoMap(units []*parser.UnitFile) map[string]*quadlet.UnitInfo {
unitsInfoMap := make(map[string]*quadlet.UnitInfo)
for _, unit := range units {
if !strings.HasSuffix(unit.Filename, ".pod") {
var serviceName string
var containers []string
var resourceName string
switch {
case strings.HasSuffix(unit.Filename, ".container"):
serviceName = quadlet.GetContainerServiceName(unit)
case strings.HasSuffix(unit.Filename, ".volume"):
serviceName = quadlet.GetVolumeServiceName(unit)
case strings.HasSuffix(unit.Filename, ".kube"):
serviceName = quadlet.GetKubeServiceName(unit)
case strings.HasSuffix(unit.Filename, ".network"):
serviceName = quadlet.GetNetworkServiceName(unit)
case strings.HasSuffix(unit.Filename, ".image"):
serviceName = quadlet.GetImageServiceName(unit)
case strings.HasSuffix(unit.Filename, ".build"):
serviceName = quadlet.GetBuildServiceName(unit)
// Prefill resouceNames for .build files. This is significantly less complex than
// pre-computing all resourceNames for all Quadlet types (which is rather complex for a few
// types), but still breaks the dependency cycle between .volume and .build ([Volume] can
// have Image=some.build, and [Build] can have Volume=some.volume:/some-volume)
resourceName = quadlet.GetBuiltImageName(unit)
case strings.HasSuffix(unit.Filename, ".pod"):
serviceName = quadlet.GetPodServiceName(unit)
containers = make([]string, 0)
default:
Logf("Unsupported file type %q", unit.Filename)
continue
}
serviceName := quadlet.GetPodServiceName(unit)
podsInfoMap[unit.Filename] = &quadlet.PodInfo{
ServiceName: serviceName,
Containers: make([]string, 0),
unitsInfoMap[unit.Filename] = &quadlet.UnitInfo{
ServiceName: serviceName,
Containers: containers,
ResourceName: resourceName,
}
}
return podsInfoMap
}
func prefillBuiltImageNames(units []*parser.UnitFile, resourceNames map[string]string) {
for _, unit := range units {
if !strings.HasSuffix(unit.Filename, ".build") {
continue
}
imageName := quadlet.GetBuiltImageName(unit)
if len(imageName) > 0 {
resourceNames[unit.Filename] = imageName
}
}
return unitsInfoMap
}
func main() {
@@ -612,40 +625,30 @@ func process() error {
})
// Generate the PodsInfoMap to allow containers to link to their pods and add themselves to the pod's containers list
podsInfoMap := generatePodsInfoMap(units)
// A map of network/volume unit file-names, against their calculated names, as needed by Podman.
var resourceNames = make(map[string]string)
// Prefill resouceNames for .build files. This is significantly less complex than
// pre-computing all resourceNames for all Quadlet types (which is rather complex for a few
// types), but still breaks the dependency cycle between .volume and .build ([Volume] can
// have Image=some.build, and [Build] can have Volume=some.volume:/some-volume)
prefillBuiltImageNames(units, resourceNames)
unitsInfoMap := generateUnitsInfoMap(units)
for _, unit := range units {
var service *parser.UnitFile
var name string
var err error
switch {
case strings.HasSuffix(unit.Filename, ".container"):
warnIfAmbiguousName(unit, quadlet.ContainerGroup)
service, err = quadlet.ConvertContainer(unit, resourceNames, isUserFlag, podsInfoMap)
service, err = quadlet.ConvertContainer(unit, isUserFlag, unitsInfoMap)
case strings.HasSuffix(unit.Filename, ".volume"):
warnIfAmbiguousName(unit, quadlet.VolumeGroup)
service, name, err = quadlet.ConvertVolume(unit, unit.Filename, resourceNames)
service, err = quadlet.ConvertVolume(unit, unit.Filename, unitsInfoMap)
case strings.HasSuffix(unit.Filename, ".kube"):
service, err = quadlet.ConvertKube(unit, resourceNames, isUserFlag)
service, err = quadlet.ConvertKube(unit, unitsInfoMap, isUserFlag)
case strings.HasSuffix(unit.Filename, ".network"):
service, name, err = quadlet.ConvertNetwork(unit, unit.Filename)
service, err = quadlet.ConvertNetwork(unit, unit.Filename, unitsInfoMap)
case strings.HasSuffix(unit.Filename, ".image"):
warnIfAmbiguousName(unit, quadlet.ImageGroup)
service, name, err = quadlet.ConvertImage(unit)
service, err = quadlet.ConvertImage(unit, unitsInfoMap)
case strings.HasSuffix(unit.Filename, ".build"):
service, name, err = quadlet.ConvertBuild(unit, resourceNames)
service, err = quadlet.ConvertBuild(unit, unitsInfoMap)
case strings.HasSuffix(unit.Filename, ".pod"):
service, err = quadlet.ConvertPod(unit, unit.Filename, podsInfoMap, resourceNames)
service, err = quadlet.ConvertPod(unit, unit.Filename, unitsInfoMap)
default:
Logf("Unsupported file type %q", unit.Filename)
continue
@@ -656,9 +659,6 @@ func process() error {
continue
}
if name != "" {
resourceNames[unit.Filename] = name
}
service.Path = path.Join(outputPath, service.Filename)
if dryRunFlag {

View File

@@ -170,9 +170,15 @@ const (
KeyYaml = "Yaml"
)
type PodInfo struct {
type UnitInfo struct {
// The name of the generated systemd service unit
ServiceName string
Containers []string
// The name of the podman resource created by the service
ResourceName string
// For .pod units
// List of containers in a pod
Containers []string
}
var (
@@ -245,6 +251,7 @@ var (
KeySecurityLabelLevel: true,
KeySecurityLabelNested: true,
KeySecurityLabelType: true,
KeyServiceName: true,
KeyShmSize: true,
KeyStopSignal: true,
KeyStopTimeout: true,
@@ -275,6 +282,7 @@ var (
KeyLabel: true,
KeyOptions: true,
KeyPodmanArgs: true,
KeyServiceName: true,
KeyType: true,
KeyUser: true,
KeyVolumeName: true,
@@ -295,6 +303,7 @@ var (
KeyInternal: true,
KeyNetworkName: true,
KeyOptions: true,
KeyServiceName: true,
KeySubnet: true,
KeyPodmanArgs: true,
}
@@ -316,6 +325,7 @@ var (
KeyRemapUid: true,
KeyRemapUidSize: true,
KeyRemapUsers: true,
KeyServiceName: true,
KeySetWorkingDirectory: true,
KeyUserNS: true,
KeyYaml: true,
@@ -335,6 +345,7 @@ var (
KeyImageTag: true,
KeyOS: true,
KeyPodmanArgs: true,
KeyServiceName: true,
KeyTLSVerify: true,
KeyVariant: true,
}
@@ -359,6 +370,7 @@ var (
KeyPodmanArgs: true,
KeyPull: true,
KeySecret: true,
KeyServiceName: true,
KeySetWorkingDirectory: true,
KeyTarget: true,
KeyTLSVerify: true,
@@ -379,7 +391,11 @@ var (
}
)
func replaceExtension(name string, extension string, extraPrefix string, extraSuffix string) string {
func (u *UnitInfo) ServiceFileName() string {
return fmt.Sprintf("%s.service", u.ServiceName)
}
func removeExtension(name string, extraPrefix string, extraSuffix string) string {
baseName := name
dot := strings.LastIndexByte(name, '.')
@@ -387,7 +403,7 @@ func replaceExtension(name string, extension string, extraPrefix string, extraSu
baseName = name[:dot]
}
return extraPrefix + baseName + extraSuffix + extension
return extraPrefix + baseName + extraSuffix
}
func isURL(urlCandidate string) bool {
@@ -456,9 +472,14 @@ func usernsOpts(kind string, opts []string) string {
// service file (unit file with Service group) based on the options in the
// Container group.
// The original Container group is kept around as X-Container.
func ConvertContainer(container *parser.UnitFile, names map[string]string, isUser bool, podsInfoMap map[string]*PodInfo) (*parser.UnitFile, error) {
func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[container.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing container %s", container.Filename)
}
service := container.Dup()
service.Filename = replaceExtension(container.Filename, ".service", "", "")
service.Filename = unitInfo.ServiceFileName()
// Add a dependency on network-online.target so the image pull does not happen
// before network is ready
@@ -491,7 +512,7 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
if len(image) > 0 {
var err error
if image, err = handleImageSource(image, service, names); err != nil {
if image, err = handleImageSource(image, service, unitsInfoMap); err != nil {
return nil, err
}
}
@@ -567,7 +588,9 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
podman.addf("--tz=%s", timezone)
}
addNetworks(container, ContainerGroup, service, names, podman)
if err := addNetworks(container, ContainerGroup, service, unitsInfoMap, podman); err != nil {
return nil, err
}
networkAliases := container.LookupAll(ContainerGroup, KeyNetworkAlias)
for _, networkAlias := range networkAliases {
@@ -753,7 +776,7 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
podman.add("--tmpfs", tmpfs)
}
if err := addVolumes(container, service, ContainerGroup, names, podman); err != nil {
if err := addVolumes(container, service, ContainerGroup, unitsInfoMap, podman); err != nil {
return nil, err
}
@@ -827,7 +850,7 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
mounts := container.LookupAllArgs(ContainerGroup, KeyMount)
for _, mount := range mounts {
mountStr, err := resolveContainerMountParams(container, service, mount, names)
mountStr, err := resolveContainerMountParams(container, service, mount, unitsInfoMap)
if err != nil {
return nil, err
}
@@ -845,7 +868,7 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
podman.add("--pull", pull)
}
if err := handlePod(container, service, ContainerGroup, podsInfoMap, podman); err != nil {
if err := handlePod(container, service, ContainerGroup, unitsInfoMap, podman); err != nil {
return nil, err
}
@@ -881,12 +904,17 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
// The original Network group is kept around as X-Network.
// Also returns the canonical network name, either auto-generated or user-defined via the
// NetworkName key-value.
func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, string, error) {
func ConvertNetwork(network *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[network.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing network %s", network.Filename)
}
service := network.Dup()
service.Filename = replaceExtension(network.Filename, ".service", "", "-network")
service.Filename = unitInfo.ServiceFileName()
if err := checkForUnknownKeys(network, NetworkGroup, supportedNetworkKeys); err != nil {
return nil, "", err
return nil, err
}
/* Rename old Network group to x-Network so that systemd ignores it */
@@ -895,7 +923,7 @@ func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, st
// Derive network name from unit name (with added prefix), or use user-provided name.
networkName, ok := network.Lookup(NetworkGroup, KeyNetworkName)
if !ok || len(networkName) == 0 {
networkName = replaceExtension(name, "", "systemd-", "")
networkName = removeExtension(name, "systemd-", "")
}
// Need the containers filesystem mounted to start podman
@@ -924,10 +952,10 @@ func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, st
ipRanges := network.LookupAll(NetworkGroup, KeyIPRange)
if len(subnets) > 0 {
if len(gateways) > len(subnets) {
return nil, "", fmt.Errorf("cannot set more gateways than subnets")
return nil, fmt.Errorf("cannot set more gateways than subnets")
}
if len(ipRanges) > len(subnets) {
return nil, "", fmt.Errorf("cannot set more ranges than subnets")
return nil, fmt.Errorf("cannot set more ranges than subnets")
}
for i := range subnets {
podman.addf("--subnet=%s", subnets[i])
@@ -939,7 +967,7 @@ func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, st
}
}
} else if len(ipRanges) > 0 || len(gateways) > 0 {
return nil, "", fmt.Errorf("cannot set gateway or range without subnet")
return nil, fmt.Errorf("cannot set gateway or range without subnet")
}
if internal := network.LookupBooleanWithDefault(NetworkGroup, KeyInternal, false); internal {
@@ -976,7 +1004,9 @@ func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, st
// The default syslog identifier is the exec basename (podman) which isn't very useful here
"SyslogIdentifier", "%N")
return service, networkName, nil
// Store the name of the created resource
unitInfo.ResourceName = networkName
return service, nil
}
// Convert a quadlet volume file (unit file with a Volume group) to a systemd
@@ -985,12 +1015,17 @@ func ConvertNetwork(network *parser.UnitFile, name string) (*parser.UnitFile, st
// The original Volume group is kept around as X-Volume.
// Also returns the canonical volume name, either auto-generated or user-defined via the VolumeName
// key-value.
func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string) (*parser.UnitFile, string, error) {
func ConvertVolume(volume *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[volume.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing network %s", volume.Filename)
}
service := volume.Dup()
service.Filename = replaceExtension(volume.Filename, ".service", "", "-volume")
service.Filename = unitInfo.ServiceFileName()
if err := checkForUnknownKeys(volume, VolumeGroup, supportedVolumeKeys); err != nil {
return nil, "", err
return nil, err
}
/* Rename old Volume group to x-Volume so that systemd ignores it */
@@ -999,7 +1034,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string
// Derive volume name from unit name (with added prefix), or use user-provided name.
volumeName, ok := volume.Lookup(VolumeGroup, KeyVolumeName)
if !ok || len(volumeName) == 0 {
volumeName = replaceExtension(name, "", "systemd-", "")
volumeName = removeExtension(name, "systemd-", "")
}
// Need the containers filesystem mounted to start podman
@@ -1023,11 +1058,11 @@ func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string
imageName, ok := volume.Lookup(VolumeGroup, KeyImage)
if !ok {
return nil, "", fmt.Errorf("the key %s is mandatory when using the image driver", KeyImage)
return nil, fmt.Errorf("the key %s is mandatory when using the image driver", KeyImage)
}
imageName, err := handleImageSource(imageName, service, names)
imageName, err := handleImageSource(imageName, service, unitsInfoMap)
if err != nil {
return nil, "", err
return nil, err
}
opts.WriteString(imageName)
@@ -1072,7 +1107,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string
if devValid {
podman.add("--opt", fmt.Sprintf("type=%s", devType))
} else {
return nil, "", fmt.Errorf("key Type can't be used without Device")
return nil, fmt.Errorf("key Type can't be used without Device")
}
}
@@ -1084,7 +1119,7 @@ func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string
}
opts.WriteString(mountOpts)
} else {
return nil, "", fmt.Errorf("key Options can't be used without Device")
return nil, fmt.Errorf("key Options can't be used without Device")
}
}
}
@@ -1108,12 +1143,20 @@ func ConvertVolume(volume *parser.UnitFile, name string, names map[string]string
// The default syslog identifier is the exec basename (podman) which isn't very useful here
"SyslogIdentifier", "%N")
return service, volumeName, nil
// Store the name of the created resource
unitInfo.ResourceName = volumeName
return service, nil
}
func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*parser.UnitFile, error) {
func ConvertKube(kube *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[kube.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing network %s", kube.Filename)
}
service := kube.Dup()
service.Filename = replaceExtension(kube.Filename, ".service", "", "")
service.Filename = unitInfo.ServiceFileName()
if kube.Path != "" {
service.Add(UnitGroup, "SourcePath", kube.Path)
@@ -1192,7 +1235,9 @@ func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*
return nil, err
}
addNetworks(kube, KubeGroup, service, names, execStart)
if err := addNetworks(kube, KubeGroup, service, unitsInfoMap, execStart); err != nil {
return nil, err
}
updateMaps := kube.LookupAllStrv(KubeGroup, KeyAutoUpdate)
for _, update := range updateMaps {
@@ -1246,9 +1291,14 @@ func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*
return service, nil
}
func ConvertImage(image *parser.UnitFile) (*parser.UnitFile, string, error) {
func ConvertImage(image *parser.UnitFile, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[image.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing network %s", image.Filename)
}
service := image.Dup()
service.Filename = replaceExtension(image.Filename, ".service", "", "-image")
service.Filename = unitInfo.ServiceFileName()
// Add a dependency on network-online.target so the image pull does not happen
// before network is ready
@@ -1263,12 +1313,12 @@ func ConvertImage(image *parser.UnitFile) (*parser.UnitFile, string, error) {
}
if err := checkForUnknownKeys(image, ImageGroup, supportedImageKeys); err != nil {
return nil, "", err
return nil, err
}
imageName, ok := image.Lookup(ImageGroup, KeyImage)
if !ok || len(imageName) == 0 {
return nil, "", fmt.Errorf("no Image key specified")
return nil, fmt.Errorf("no Image key specified")
}
/* Rename old Network group to x-Network so that systemd ignores it */
@@ -1321,12 +1371,25 @@ func ConvertImage(image *parser.UnitFile) (*parser.UnitFile, string, error) {
imageName = name
}
return service, imageName, nil
// Store the name of the created resource
unitInfo.ResourceName = imageName
return service, nil
}
func ConvertBuild(build *parser.UnitFile, names map[string]string) (*parser.UnitFile, string, error) {
func ConvertBuild(build *parser.UnitFile, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[build.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing network %s", build.Filename)
}
// Fast fail is ResouceName is not set
if len(unitInfo.ResourceName) == 0 {
return nil, fmt.Errorf("no ImageTag key specified")
}
service := build.Dup()
service.Filename = replaceExtension(build.Filename, ".service", "", "-build")
service.Filename = unitInfo.ServiceFileName()
// Add a dependency on network-online.target so the image pull does not happen
// before network is ready
@@ -1347,7 +1410,7 @@ func ConvertBuild(build *parser.UnitFile, names map[string]string) (*parser.Unit
}
if err := checkForUnknownKeys(build, BuildGroup, supportedBuildKeys); err != nil {
return nil, "", err
return nil, err
}
podman := createBasePodmanCommand(build, BuildGroup)
@@ -1405,22 +1468,19 @@ func ConvertBuild(build *parser.UnitFile, names map[string]string) (*parser.Unit
labels := build.LookupAllKeyVal(BuildGroup, KeyLabel)
podman.addLabels(labels)
builtImageName, ok := names[build.Filename]
if !ok {
return nil, "", fmt.Errorf("no ImageTag key specified")
podman.addf("--tag=%s", unitInfo.ResourceName)
if err := addNetworks(build, BuildGroup, service, unitsInfoMap, podman); err != nil {
return nil, err
}
podman.addf("--tag=%s", builtImageName)
addNetworks(build, BuildGroup, service, names, podman)
secrets := build.LookupAllArgs(BuildGroup, KeySecret)
for _, secret := range secrets {
podman.add("--secret", secret)
}
if err := addVolumes(build, service, BuildGroup, names, podman); err != nil {
return nil, "", err
if err := addVolumes(build, service, BuildGroup, unitsInfoMap, podman); err != nil {
return nil, err
}
// In order to build an image locally, we need either a File key pointing directly at a
@@ -1429,13 +1489,13 @@ func ConvertBuild(build *parser.UnitFile, names map[string]string) (*parser.Unit
// an archive.
context, err := handleSetWorkingDirectory(build, service, BuildGroup)
if err != nil {
return nil, "", err
return nil, err
}
workingDirectory, okWD := service.Lookup(ServiceGroup, ServiceKeyWorkingDirectory)
filePath, okFile := build.Lookup(BuildGroup, KeyFile)
if (!okWD || len(workingDirectory) == 0) && (!okFile || len(filePath) == 0) && len(context) == 0 {
return nil, "", fmt.Errorf("neither SetWorkingDirectory, nor File key specified")
return nil, fmt.Errorf("neither SetWorkingDirectory, nor File key specified")
}
if len(filePath) > 0 {
@@ -1450,7 +1510,7 @@ func ConvertBuild(build *parser.UnitFile, names map[string]string) (*parser.Unit
} else if !filepath.IsAbs(filePath) && !isURL(filePath) {
// Special handling for relative filePaths
if len(workingDirectory) == 0 {
return nil, "", fmt.Errorf("relative path in File key requires SetWorkingDirectory key to be set")
return nil, fmt.Errorf("relative path in File key requires SetWorkingDirectory key to be set")
}
podman.add(workingDirectory)
}
@@ -1465,7 +1525,7 @@ func ConvertBuild(build *parser.UnitFile, names map[string]string) (*parser.Unit
// which isn't very useful here
"SyslogIdentifier", "%N")
return service, builtImageName, nil
return service, nil
}
func GetBuiltImageName(buildUnit *parser.UnitFile) string {
@@ -1475,21 +1535,49 @@ func GetBuiltImageName(buildUnit *parser.UnitFile) string {
return ""
}
func GetPodServiceName(podUnit *parser.UnitFile) string {
if serviceName, ok := podUnit.Lookup(PodGroup, KeyServiceName); ok {
return serviceName
}
return replaceExtension(podUnit.Filename, "", "", "-pod")
func GetContainerServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, ContainerGroup, "")
}
func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*PodInfo, names map[string]string) (*parser.UnitFile, error) {
podInfo, ok := podsInfoMap[podUnit.Filename]
func GetKubeServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, KubeGroup, "")
}
func GetVolumeServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, VolumeGroup, "-volume")
}
func GetNetworkServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, NetworkGroup, "-network")
}
func GetImageServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, ImageGroup, "-image")
}
func GetBuildServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, BuildGroup, "-build")
}
func GetPodServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, PodGroup, "-pod")
}
func getServiceName(quadletUnitFile *parser.UnitFile, groupName string, defaultExtraSuffix string) string {
if serviceName, ok := quadletUnitFile.Lookup(groupName, KeyServiceName); ok {
return serviceName
}
return removeExtension(quadletUnitFile.Filename, "", defaultExtraSuffix)
}
func ConvertPod(podUnit *parser.UnitFile, name string, unitsInfoMap map[string]*UnitInfo) (*parser.UnitFile, error) {
unitInfo, ok := unitsInfoMap[podUnit.Filename]
if !ok {
return nil, fmt.Errorf("internal error while processing pod %s", podUnit.Filename)
}
service := podUnit.Dup()
service.Filename = fmt.Sprintf("%s.service", podInfo.ServiceName)
service.Filename = unitInfo.ServiceFileName()
if podUnit.Path != "" {
service.Add(UnitGroup, "SourcePath", podUnit.Path)
@@ -1502,7 +1590,7 @@ func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*P
// Derive pod name from unit name (with added prefix), or use user-provided name.
podName, ok := podUnit.Lookup(PodGroup, KeyPodName)
if !ok || len(podName) == 0 {
podName = replaceExtension(name, "", "systemd-", "")
podName = removeExtension(name, "systemd-", "")
}
/* Rename old Pod group to x-Pod so that systemd ignores it */
@@ -1511,7 +1599,7 @@ func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*P
// Need the containers filesystem mounted to start podman
service.Add(UnitGroup, "RequiresMountsFor", "%t/containers")
for _, containerService := range podInfo.Containers {
for _, containerService := range unitInfo.Containers {
service.Add(UnitGroup, "Wants", containerService)
service.Add(UnitGroup, "Before", containerService)
}
@@ -1555,14 +1643,16 @@ func ConvertPod(podUnit *parser.UnitFile, name string, podsInfoMap map[string]*P
return nil, err
}
addNetworks(podUnit, PodGroup, service, names, execStartPre)
if err := addNetworks(podUnit, PodGroup, service, unitsInfoMap, execStartPre); err != nil {
return nil, err
}
networkAliases := podUnit.LookupAll(PodGroup, KeyNetworkAlias)
for _, networkAlias := range networkAliases {
execStartPre.add("--network-alias", networkAlias)
}
if err := addVolumes(podUnit, service, PodGroup, names, execStartPre); err != nil {
if err := addVolumes(podUnit, service, PodGroup, unitsInfoMap, execStartPre); err != nil {
return nil, err
}
@@ -1714,34 +1804,35 @@ func handleUserRemap(unitFile *parser.UnitFile, groupName string, podman *Podman
return nil
}
func addNetworks(quadletUnitFile *parser.UnitFile, groupName string, serviceUnitFile *parser.UnitFile, names map[string]string, podman *PodmanCmdline) {
func addNetworks(quadletUnitFile *parser.UnitFile, groupName string, serviceUnitFile *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, podman *PodmanCmdline) error {
networks := quadletUnitFile.LookupAll(groupName, KeyNetwork)
for _, network := range networks {
if len(network) > 0 {
quadletNetworkName, options, found := strings.Cut(network, ":")
if strings.HasSuffix(quadletNetworkName, ".network") {
// the podman network name is systemd-$name if none is specified by the user.
networkName := names[quadletNetworkName]
if networkName == "" {
networkName = replaceExtension(quadletNetworkName, "", "systemd-", "")
networkUnitInfo, ok := unitsInfoMap[quadletNetworkName]
if !ok {
return fmt.Errorf("requested Quadlet image %s was not found", quadletNetworkName)
}
// the systemd unit name is $name-network.service
networkServiceName := replaceExtension(quadletNetworkName, ".service", "", "-network")
// the systemd unit name is $serviceName.service
networkServiceName := networkUnitInfo.ServiceFileName()
serviceUnitFile.Add(UnitGroup, "Requires", networkServiceName)
serviceUnitFile.Add(UnitGroup, "After", networkServiceName)
if found {
network = fmt.Sprintf("%s:%s", networkName, options)
network = fmt.Sprintf("%s:%s", networkUnitInfo.ResourceName, options)
} else {
network = networkName
network = networkUnitInfo.ResourceName
}
}
podman.addf("--network=%s", network)
}
}
return nil
}
// Systemd Specifiers start with % with the exception of %%
@@ -1851,7 +1942,7 @@ func handleLogOpt(unitFile *parser.UnitFile, groupName string, podman *PodmanCmd
}
}
func handleStorageSource(quadletUnitFile, serviceUnitFile *parser.UnitFile, source string, names map[string]string) (string, error) {
func handleStorageSource(quadletUnitFile, serviceUnitFile *parser.UnitFile, source string, unitsInfoMap map[string]*UnitInfo) (string, error) {
if source[0] == '.' {
var err error
source, err = getAbsolutePath(quadletUnitFile, source)
@@ -1863,19 +1954,17 @@ func handleStorageSource(quadletUnitFile, serviceUnitFile *parser.UnitFile, sour
// Absolute path
serviceUnitFile.Add(UnitGroup, "RequiresMountsFor", source)
} else if strings.HasSuffix(source, ".volume") {
// the podman volume name is systemd-$name if none has been provided by the user.
volumeName := names[source]
if volumeName == "" {
volumeName = replaceExtension(source, "", "systemd-", "")
volumeUnitInfo, ok := unitsInfoMap[source]
if !ok {
return "", fmt.Errorf("requested Quadlet image %s was not found", source)
}
// the systemd unit name is $name-volume.service
volumeServiceName := replaceExtension(source, ".service", "", "-volume")
source = volumeName
// the systemd unit name is $serviceName.service
volumeServiceName := volumeUnitInfo.ServiceFileName()
serviceUnitFile.Add(UnitGroup, "Requires", volumeServiceName)
serviceUnitFile.Add(UnitGroup, "After", volumeServiceName)
source = volumeUnitInfo.ResourceName
}
return source, nil
@@ -1989,29 +2078,29 @@ func lookupAndAddBoolean(unit *parser.UnitFile, group, key, flag string, podman
}
}
func handleImageSource(quadletImageName string, serviceUnitFile *parser.UnitFile, names map[string]string) (string, error) {
func handleImageSource(quadletImageName string, serviceUnitFile *parser.UnitFile, unitsInfoMap map[string]*UnitInfo) (string, error) {
for _, suffix := range []string{".build", ".image"} {
if strings.HasSuffix(quadletImageName, suffix) {
// since there is no default name conversion, the actual image name must exist in the names map
imageName, ok := names[quadletImageName]
unitInfo, ok := unitsInfoMap[quadletImageName]
if !ok {
return "", fmt.Errorf("requested Quadlet image %s was not found", quadletImageName)
}
// the systemd unit name is $name-$suffix.service
imageServiceName := replaceExtension(quadletImageName, ".service", "", fmt.Sprintf("-%s", suffix[1:]))
imageServiceName := unitInfo.ServiceFileName()
serviceUnitFile.Add(UnitGroup, "Requires", imageServiceName)
serviceUnitFile.Add(UnitGroup, "After", imageServiceName)
quadletImageName = imageName
quadletImageName = unitInfo.ResourceName
}
}
return quadletImageName, nil
}
func resolveContainerMountParams(containerUnitFile, serviceUnitFile *parser.UnitFile, mount string, names map[string]string) (string, error) {
func resolveContainerMountParams(containerUnitFile, serviceUnitFile *parser.UnitFile, mount string, unitsInfoMap map[string]*UnitInfo) (string, error) {
mountType, tokens, err := specgenutilexternal.FindMountType(mount)
if err != nil {
return "", err
@@ -2035,7 +2124,7 @@ func resolveContainerMountParams(containerUnitFile, serviceUnitFile *parser.Unit
}
}
resolvedSource, err := handleStorageSource(containerUnitFile, serviceUnitFile, originalSource, names)
resolvedSource, err := handleStorageSource(containerUnitFile, serviceUnitFile, originalSource, unitsInfoMap)
if err != nil {
return "", err
}
@@ -2080,21 +2169,21 @@ func createBasePodmanCommand(unitFile *parser.UnitFile, groupName string) *Podma
return podman
}
func handlePod(quadletUnitFile, serviceUnitFile *parser.UnitFile, groupName string, podsInfoMap map[string]*PodInfo, podman *PodmanCmdline) error {
func handlePod(quadletUnitFile, serviceUnitFile *parser.UnitFile, groupName string, unitsInfoMap map[string]*UnitInfo, podman *PodmanCmdline) error {
pod, ok := quadletUnitFile.Lookup(groupName, KeyPod)
if ok && len(pod) > 0 {
if !strings.HasSuffix(pod, ".pod") {
return fmt.Errorf("pod %s is not Quadlet based", pod)
}
podInfo, ok := podsInfoMap[pod]
podInfo, ok := unitsInfoMap[pod]
if !ok {
return fmt.Errorf("quadlet pod unit %s does not exist", pod)
}
podman.add("--pod-id-file", fmt.Sprintf("%%t/%s.pod-id", podInfo.ServiceName))
podServiceName := fmt.Sprintf("%s.service", podInfo.ServiceName)
podServiceName := podInfo.ServiceFileName()
serviceUnitFile.Add(UnitGroup, "BindsTo", podServiceName)
serviceUnitFile.Add(UnitGroup, "After", podServiceName)
@@ -2103,7 +2192,7 @@ 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 {
func addVolumes(quadletUnitFile, serviceUnitFile *parser.UnitFile, groupName string, unitsInfoMap map[string]*UnitInfo, podman *PodmanCmdline) error {
volumes := quadletUnitFile.LookupAll(groupName, KeyVolume)
for _, volume := range volumes {
parts := strings.SplitN(volume, ":", 3)
@@ -2123,7 +2212,7 @@ func addVolumes(quadletUnitFile, serviceUnitFile *parser.UnitFile, groupName str
if source != "" {
var err error
source, err = handleStorageSource(quadletUnitFile, serviceUnitFile, source, names)
source, err = handleStorageSource(quadletUnitFile, serviceUnitFile, source, unitsInfoMap)
if err != nil {
return err
}

View File

@@ -0,0 +1,8 @@
## assert-podman-args --driver=image
## assert-podman-args --opt image=localhost/imagename
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "basic.service"
[Volume]
Driver=image
Image=service-name.build

View File

@@ -0,0 +1,8 @@
## assert-podman-args --driver=image
## assert-podman-args --opt image=localhost/imagename
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "basic.service"
[Volume]
Driver=image
Image=service-name.image

View File

@@ -8,10 +8,10 @@ Mount=type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared
Mount=type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared,U=true
## assert-podman-args-key-val "--mount" "," "type=volume,source=vol1,destination=/path/in/container,ro=true"
Mount=type=volume,source=vol1,destination=/path/in/container,ro=true
## assert-podman-args-key-val "--mount" "," "type=volume,source=systemd-vol2,destination=/path/in/container,ro=true"
## assert-key-is "Unit" "Requires" "vol2-volume.service"
## assert-key-is "Unit" "After" "network-online.target" "vol2-volume.service"
Mount=type=volume,source=vol2.volume,destination=/path/in/container,ro=true
## assert-podman-args-key-val "--mount" "," "type=volume,source=systemd-basic,destination=/path/in/container,ro=true"
## assert-key-is "Unit" "Requires" "basic-volume.service"
## assert-key-is "Unit" "After" "network-online.target" "basic-volume.service"
Mount=type=volume,source=basic.volume,destination=/path/in/container,ro=true
## assert-podman-args-key-val "--mount" "," "type=tmpfs,tmpfs-size=512M,destination=/path/in/container"
Mount=type=tmpfs,tmpfs-size=512M,destination=/path/in/container
## assert-podman-args-key-val "--mount" "," "type=image,source=fedora,destination=/fedora-image,rw=true"

View File

@@ -0,0 +1,6 @@
[Container]
Image=localhost/imagename
## assert-podman-args-key-val "--mount" "," "type=volume,source=test-volume,destination=/path/in/container,ro=true"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "network-online.target" "basic.service"
Mount=type=volume,source=service-name.volume,destination=/path/in/container,ro=true

View File

@@ -0,0 +1,8 @@
## assert-podman-args "--network=test-network"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "network-online.target" "basic.service"
[Build]
ImageTag=localhost/imagename
SetWorkingDirectory=unit
Network=service-name.network

View File

@@ -0,0 +1,7 @@
## assert-podman-args "--network=test-network"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "network-online.target" "basic.service"
[Container]
Image=localhost/imagename
Network=service-name.network

View File

@@ -0,0 +1,8 @@
## assert-podman-args "--network=test-network"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "basic.service"
[Kube]
Yaml=deployment.yml
Network=service-name.network

View File

@@ -0,0 +1,6 @@
## assert-podman-pre-args "--network=test-network"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "basic.service"
[Pod]
Network=service-name.network

View File

@@ -0,0 +1,6 @@
## assert-podman-args --tag=localhost/imagename
[Build]
ServiceName=basic
ImageTag=localhost/imagename
SetWorkingDirectory=unit

View File

@@ -0,0 +1,5 @@
## assert-podman-final-args localhost/imagename
[Container]
ServiceName=basic
Image=localhost/imagename

View File

@@ -0,0 +1,5 @@
## assert-podman-final-args localhost/imagename
[Image]
ServiceName=basic
Image=localhost/imagename

View File

@@ -0,0 +1,5 @@
## assert-podman-final-args-regex .*/podman-e2e-.*/subtest-.*/quadlet/deployment.yml
[Kube]
ServiceName=basic
Yaml=deployment.yml

View File

@@ -0,0 +1,5 @@
## assert-podman-final-args "test-network"
[Network]
ServiceName=basic
NetworkName=test-network

View File

@@ -1,5 +1,5 @@
## assert-podman-pre-args "--name=test-pod"
[Pod]
ServiceName=basic
PodName=test-pod
ServiceName=test-pod

View File

@@ -0,0 +1,5 @@
## assert-podman-final-args "test-volume"
[Volume]
ServiceName=basic
VolumeName=test-volume

View File

@@ -2,7 +2,7 @@
## assert-podman-args -v /host/dir2:/container/volume2:Z
## assert-podman-args-regex -v .*/podman-e2e-.*/subtest-.*/quadlet/host/dir3:/container/volume3
## assert-podman-args -v named:/container/named
## assert-podman-args -v systemd-quadlet:/container/quadlet
## assert-podman-args -v systemd-basic:/container/quadlet
## assert-podman-args -v %h/container:/container/volume4
[Build]
@@ -13,5 +13,5 @@ Volume=/host/dir2:/container/volume2:Z
Volume=./host/dir3:/container/volume3
Volume=/container/empty
Volume=named:/container/named
Volume=quadlet.volume:/container/quadlet
Volume=basic.volume:/container/quadlet
Volume=%h/container:/container/volume4

View File

@@ -2,7 +2,7 @@
## assert-podman-args -v /host/dir2:/container/volume2:Z
## assert-podman-args-regex -v .*/podman-e2e-.*/subtest-.*/quadlet/host/dir3:/container/volume3
## assert-podman-args -v named:/container/named
## assert-podman-args -v systemd-quadlet:/container/quadlet
## assert-podman-args -v systemd-basic:/container/quadlet
## assert-podman-args -v %h/container:/container/volume4
[Container]
@@ -12,5 +12,5 @@ Volume=/host/dir2:/container/volume2:Z
Volume=./host/dir3:/container/volume3
Volume=/container/empty
Volume=named:/container/named
Volume=quadlet.volume:/container/quadlet
Volume=basic.volume:/container/quadlet
Volume=%h/container:/container/volume4

View File

@@ -2,7 +2,7 @@
## assert-podman-pre-args -v /host/dir2:/container/volume2:Z
## assert-podman-pre-args-regex -v .*/podman-e2e-.*/subtest-.*/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 systemd-basic:/container/quadlet
## assert-podman-pre-args -v %h/container:/container/volume4
[Pod]
@@ -11,5 +11,5 @@ Volume=/host/dir2:/container/volume2:Z
Volume=./host/dir3:/container/volume3
Volume=/container/empty
Volume=named:/container/named
Volume=quadlet.volume:/container/quadlet
Volume=basic.volume:/container/quadlet
Volume=%h/container:/container/volume4

View File

@@ -0,0 +1,8 @@
## assert-podman-args "-v" "test-volume:/volume/basic"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "network-online.target" "basic.service"
[Build]
ImageTag=localhost/imagename
SetWorkingDirectory=unit
Volume=service-name.volume:/volume/basic

View File

@@ -0,0 +1,6 @@
[Container]
Image=localhost/imagename
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "network-online.target" "basic.service"
## assert-podman-args -v test-volume:/container/quadlet
Volume=service-name.volume:/container/quadlet

View File

@@ -0,0 +1,6 @@
## assert-podman-pre-args -v test-volume:/container/quadlet
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is "Unit" "After" "basic.service"
[Pod]
Volume=service-name.volume:/container/quadlet

View File

@@ -36,10 +36,7 @@ func getGenericTemplateFile(fileName string) (bool, string) {
return false, ""
}
func loadQuadletTestcase(path string) *quadletTestcase {
data, err := os.ReadFile(path)
Expect(err).ToNot(HaveOccurred())
func calcServiceName(path string) string {
base := filepath.Base(path)
ext := filepath.Ext(base)
service := base[:len(base)-len(ext)]
@@ -55,6 +52,23 @@ func loadQuadletTestcase(path string) *quadletTestcase {
case ".pod":
service += "-pod"
}
return service
}
func loadQuadletTestcase(path string) *quadletTestcase {
return loadQuadletTestcaseWithServiceName(path, "")
}
func loadQuadletTestcaseWithServiceName(path, serviceName string) *quadletTestcase {
data, err := os.ReadFile(path)
Expect(err).ToNot(HaveOccurred())
var service string
if len(serviceName) > 0 {
service = serviceName
} else {
service = calcServiceName(path)
}
service += ".service"
checks := make([][]string, 0)
@@ -609,8 +623,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))
runQuadletTestCaseWithServiceName = func(fileName string, exitCode int, errString string, serviceName string) {
testcase := loadQuadletTestcaseWithServiceName(filepath.Join("quadlet", fileName), serviceName)
// Write the tested file to the quadlet dir
err = os.WriteFile(filepath.Join(quadletDir, fileName), testcase.data, 0644)
@@ -647,6 +661,10 @@ var _ = Describe("quadlet system generator", func() {
testcase.check(generatedDir, session)
}
runQuadletTestCase = func(fileName string, exitCode int, errString string) {
runQuadletTestCaseWithServiceName(fileName, exitCode, errString, "")
}
runSuccessQuadletTestCase = func(fileName string) {
runQuadletTestCase(fileName, 0, "")
}
@@ -831,11 +849,9 @@ BOGUS=foo
Entry("logdriver.container", "logdriver.container"),
Entry("logopt.container", "logopt.container"),
Entry("mask.container", "mask.container"),
Entry("mount.container", "mount.container"),
Entry("name.container", "name.container"),
Entry("nestedselinux.container", "nestedselinux.container"),
Entry("network.container", "network.container"),
Entry("network.quadlet.container", "network.quadlet.container"),
Entry("notify.container", "notify.container"),
Entry("notify-healthy.container", "notify-healthy.container"),
Entry("oneshot.container", "oneshot.container"),
@@ -870,7 +886,6 @@ BOGUS=foo
Entry("unmask.container", "unmask.container"),
Entry("user.container", "user.container"),
Entry("userns.container", "userns.container"),
Entry("volume.container", "volume.container"),
Entry("workingdir.container", "workingdir.container"),
Entry("Container - global args", "globalargs.container"),
Entry("Container - Containers Conf Modules", "containersconfmodule.container"),
@@ -902,7 +917,6 @@ BOGUS=foo
Entry("Kube - PodmanArgs", "podmanargs.kube"),
Entry("Kube - Publish IPv4 ports", "ports.kube"),
Entry("Kube - Publish IPv6 ports", "ports_ipv6.kube"),
Entry("Kube - Quadlet Network", "network.quadlet.kube"),
Entry("Kube - User Remap Auto with IDs", "remap-auto2.kube"),
Entry("Kube - User Remap Auto", "remap-auto.kube"),
Entry("Syslog Identifier", "syslog.identifier.kube"),
@@ -967,7 +981,6 @@ BOGUS=foo
Entry("Build - Containers Conf Modules", "containersconfmodule.build"),
Entry("Build - Label Key", "label.build"),
Entry("Build - Network Key host", "network.build"),
Entry("Build - Network Key quadlet", "network.quadlet.build"),
Entry("Build - PodmanArgs", "podmanargs.build"),
Entry("Build - Pull Key", "pull.build"),
Entry("Build - Secrets", "secrets.build"),
@@ -982,15 +995,11 @@ BOGUS=foo
Entry("Build - Target Key", "target.build"),
Entry("Build - TLSVerify Key", "tls-verify.build"),
Entry("Build - Variant Key", "variant.build"),
Entry("Build - Volume Key", "volume.build"),
Entry("Build - Volume Key quadlet", "volume.quadlet.build"),
Entry("basic.pod", "basic.pod"),
Entry("name.pod", "name.pod"),
Entry("network.pod", "network.pod"),
Entry("network-quadlet.pod", "network.quadlet.pod"),
Entry("podmanargs.pod", "podmanargs.pod"),
Entry("volume.pod", "volume.pod"),
Entry("Pod - NetworkAlias", "network-alias.pod"),
)
@@ -1026,8 +1035,21 @@ BOGUS=foo
Entry("Build - No ImageTag Key", "no-imagetag.build", "converting \"no-imagetag.build\": no ImageTag key specified"),
)
DescribeTable("Running quadlet test case with dependencies",
func(fileName string, exitCode int, errString string, dependencyFiles []string) {
DescribeTable("Running success quadlet with ServiceName test case",
func(fileName, serviceName string) {
runQuadletTestCaseWithServiceName(fileName, 0, "", serviceName)
},
Entry("Build", "service-name.build", "basic"),
Entry("Container", "service-name.container", "basic"),
Entry("Image", "service-name.image", "basic"),
Entry("Kube", "service-name.kube", "basic"),
Entry("Network", "service-name.network", "basic"),
Entry("Pod", "service-name.pod", "basic"),
Entry("Volume", "service-name.volume", "basic"),
)
DescribeTable("Running quadlet success test case with dependencies",
func(fileName string, dependencyFiles []string) {
// Write additional files this test depends on to the quadlet dir
for _, dependencyFileName := range dependencyFiles {
dependencyTestCase := loadQuadletTestcase(filepath.Join("quadlet", dependencyFileName))
@@ -1035,10 +1057,33 @@ BOGUS=foo
Expect(err).ToNot(HaveOccurred())
}
runQuadletTestCase(fileName, exitCode, errString)
runSuccessQuadletTestCase(fileName)
},
Entry("Volume - Quadlet image (.build)", "build.quadlet.volume", 0, "", []string{"basic.build"}),
Entry("Volume - Quadlet image (.image)", "image.quadlet.volume", 0, "", []string{"basic.image"}),
Entry("Container - Mount", "mount.container", []string{"basic.volume"}),
Entry("Container - Quadlet Network", "network.quadlet.container", []string{"basic.network"}),
Entry("Container - Quadlet Volume", "volume.container", []string{"basic.volume"}),
Entry("Container - Mount overriding service name", "mount.servicename.container", []string{"service-name.volume"}),
Entry("Container - Quadlet Network overriding service name", "network.quadlet.servicename.container", []string{"service-name.network"}),
Entry("Container - Quadlet Volume overriding service name", "volume.servicename.container", []string{"service-name.volume"}),
Entry("Volume - Quadlet image (.build)", "build.quadlet.volume", []string{"basic.build"}),
Entry("Volume - Quadlet image (.image)", "image.quadlet.volume", []string{"basic.image"}),
Entry("Volume - Quadlet image (.build) overriding service name", "build.quadlet.servicename.volume", []string{"service-name.build"}),
Entry("Volume - Quadlet image (.image) overriding service name", "image.quadlet.servicename.volume", []string{"service-name.image"}),
Entry("Kube - Quadlet Network", "network.quadlet.kube", []string{"basic.network"}),
Entry("Kube - Quadlet Network overriding service name", "network.quadlet.servicename.kube", []string{"service-name.network"}),
Entry("Build - Network Key quadlet", "network.quadlet.build", []string{"basic.network"}),
Entry("Build - Volume Key", "volume.build", []string{"basic.volume"}),
Entry("Build - Volume Key quadlet", "volume.quadlet.build", []string{"basic.volume"}),
Entry("Build - Network Key quadlet overriding service name", "network.quadlet.servicename.build", []string{"service-name.network"}),
Entry("Build - Volume Key quadlet overriding service name", "volume.quadlet.servicename.build", []string{"service-name.volume"}),
Entry("Pod - Quadlet Network", "network.quadlet.pod", []string{"basic.network"}),
Entry("Pod - Quadlet Volume", "volume.pod", []string{"basic.volume"}),
Entry("Pod - Quadlet Network overriding service name", "network.servicename.quadlet.pod", []string{"service-name.network"}),
Entry("Pod - Quadlet Volume overriding service name", "volume.servicename.pod", []string{"service-name.volume"}),
)
})

View File

@@ -383,8 +383,9 @@ EOF
[Volume]
EOF
local quadlet_tmpdir=$(mktemp -d --tmpdir=$PODMAN_TMPDIR quadlet.XXXXXX)
# Have quadlet create the systemd unit file for the volume unit
run_quadlet "$quadlet_vol_file"
run_quadlet "$quadlet_vol_file" "$quadlet_tmpdir"
# Save the volume service name since the variable will be overwritten
local vol_service=$QUADLET_SERVICE_NAME
@@ -399,7 +400,7 @@ Volume=$quadlet_vol_unit:/tmp
EOF
# Have quadlet create the systemd unit file for the container unit
run_quadlet "$quadlet_file"
run_quadlet "$quadlet_file" "$quadlet_tmpdir"
# Save the container service name for readability
local container_service=$QUADLET_SERVICE_NAME
@@ -510,8 +511,9 @@ EOF
[Network]
EOF
local quadlet_tmpdir=$(mktemp -d --tmpdir=$PODMAN_TMPDIR quadlet.XXXXXX)
# Have quadlet create the systemd unit file for the network unit
run_quadlet "$quadlet_network_file"
run_quadlet "$quadlet_network_file" "$quadlet_tmpdir"
# Save the volume service name since the variable will be overwritten
local network_service=$QUADLET_SERVICE_NAME
@@ -525,7 +527,7 @@ Exec=top
Network=$quadlet_network_unit
EOF
run_quadlet "$quadlet_file"
run_quadlet "$quadlet_file" "$quadlet_tmpdir"
# Save the container service name for readability
local container_service=$QUADLET_SERVICE_NAME