Skip to content

Commit

Permalink
quadlet: fix inter-dependency of containers in Network=
Browse files Browse the repository at this point in the history
Signed-off-by: Misaki Kasumi <[email protected]>
  • Loading branch information
ruihe774 committed Dec 10, 2024
1 parent 8ff491b commit ecf9b0a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 14 deletions.
59 changes: 45 additions & 14 deletions pkg/systemd/quadlet/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,15 +559,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[
}
}

containerName, ok := container.Lookup(ContainerGroup, KeyContainerName)
if !ok || len(containerName) == 0 {
// By default, We want to name the container by the service name
if strings.Contains(container.Filename, "@") {
containerName = "systemd-%p_%i"
} else {
containerName = "systemd-%N"
}
}
containerName := getContainerName(container)

// Set PODMAN_SYSTEMD_UNIT so that podman auto-update can restart the service.
service.Add(ServiceGroup, "Environment", "PODMAN_SYSTEMD_UNIT=%n")
Expand Down Expand Up @@ -868,14 +860,46 @@ func ConvertContainer(container *parser.UnitFile, isUser bool, unitsInfoMap map[

service.AddCmdline(ServiceGroup, "ExecStart", podman.Args)

unitInfo.ResourceName = getContainerResourceName(container, unitInfo)

return service, nil
}

// Get the unresolved container name that may contain '%'.
func getContainerName(container *parser.UnitFile) string {
containerName, ok := container.Lookup(ContainerGroup, KeyContainerName)
if !ok || len(containerName) == 0 {
// By default, We want to name the container by the service name.
if strings.Contains(container.Filename, "@") {
containerName = "systemd-%p_%i"
} else {
containerName = "systemd-%N"
}
}
return containerName
}

// Get the resolved container name that contains no '%'.
// Returns an empty string if not resolvable.
func getContainerResourceName(container *parser.UnitFile, unitInfo *UnitInfo) string {
if len(unitInfo.ResourceName) != 0 {
// Shortcut: already resolved before.
return unitInfo.ResourceName
}

containerName := getContainerName(container)

// XXX: only %N is handled.
// it is difficult to properly implement specifiers handling without consulting systemd.
resourceName := strings.ReplaceAll(containerName, "%N", unitInfo.ServiceName)

if !strings.Contains(resourceName, "%") {
unitInfo.ResourceName = resourceName
} else {
unitInfo.ResourceName = ""
}

return service, nil
return unitInfo.ResourceName
}

func defaultOneshotServiceGroup(service *parser.UnitFile, remainAfterExit bool) {
Expand Down Expand Up @@ -1793,8 +1817,15 @@ func addNetworks(quadletUnitFile *parser.UnitFile, groupName string, serviceUnit
return fmt.Errorf("requested Quadlet unit %s was not found", quadletNetworkName)
}

var resourceName string
if isContainerUnit {
resourceName = getContainerResourceName(quadletUnitFile, unitInfo)
} else {
resourceName = unitInfo.ResourceName
}

// XXX: this is usually because a '@' in service name
if len(unitInfo.ResourceName) == 0 {
if len(resourceName) == 0 {
return fmt.Errorf("cannot get the resource name of %s", quadletNetworkName)
}

Expand All @@ -1808,12 +1839,12 @@ func addNetworks(quadletUnitFile *parser.UnitFile, groupName string, serviceUnit
if isContainerUnit {
return fmt.Errorf("extra options are not supported when joining another container's network")
}
network = fmt.Sprintf("%s:%s", unitInfo.ResourceName, options)
network = fmt.Sprintf("%s:%s", resourceName, options)
} else {
if isContainerUnit {
network = fmt.Sprintf("container:%s", unitInfo.ResourceName)
network = fmt.Sprintf("container:%s", resourceName)
} else {
network = unitInfo.ResourceName
network = resourceName
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions test/e2e/quadlet/a.network.reuse.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-args "--network" "container:systemd-basic"
## assert-key-is "Unit" "Requires" "basic.service"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service" "basic.service"

[Container]
Image=localhost/imagename
Network=basic.container
7 changes: 7 additions & 0 deletions test/e2e/quadlet/a.network.reuse.name.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-args "--network" "container:foobar"
## assert-key-is "Unit" "Requires" "name.service"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service" "name.service"

[Container]
Image=localhost/imagename
Network=name.container
2 changes: 2 additions & 0 deletions test/e2e/quadlet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,8 @@ BOGUS=foo
Entry("Container - Quadlet build with multiple tags", "build.multiple-tags.container", []string{"multiple-tags.build"}),
Entry("Container - Reuse another container's network", "network.reuse.container", []string{"basic.container"}),
Entry("Container - Reuse another named container's network", "network.reuse.name.container", []string{"name.container"}),
Entry("Container - Reuse another container's network", "a.network.reuse.container", []string{"basic.container"}),
Entry("Container - Reuse another named container's network", "a.network.reuse.name.container", []string{"name.container"}),

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

0 comments on commit ecf9b0a

Please sign in to comment.