Merge pull request #27385 from KonishchevDmitry/bind-mounts-with-spaces

Escape RequiresMountsFor value to properly handle bind mounts with spaces in path
This commit is contained in:
openshift-merge-bot[bot]
2025-10-28 13:22:03 +00:00
committed by GitHub
13 changed files with 61 additions and 35 deletions

View File

@@ -879,6 +879,15 @@ func (f *UnitFile) Add(groupName string, key string, value string) {
group.add(key, value)
}
func (f *UnitFile) AddEscaped(groupName string, key string, value string) {
if wordNeedEscape(value) {
var escaped strings.Builder
appendEscapeWord(&escaped, value)
value = escaped.String()
}
f.Add(groupName, key, value)
}
func (f *UnitFile) AddCmdline(groupName string, key string, args []string) {
f.Add(groupName, key, escapeWords(args))
}

View File

@@ -1151,7 +1151,7 @@ func ConvertVolume(volume *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, i
if devValid {
podman.add("--opt", fmt.Sprintf("type=%s", devType))
if devType == "bind" {
service.Add(UnitGroup, "RequiresMountsFor", dev)
service.AddEscaped(UnitGroup, "RequiresMountsFor", dev)
}
} else {
return nil, warnings, fmt.Errorf("key Type can't be used without Device")
@@ -1929,7 +1929,7 @@ func handleStorageSource(quadletUnitFile, serviceUnitFile *parser.UnitFile, sour
}
if source[0] == '/' {
// Absolute path
serviceUnitFile.Add(UnitGroup, "RequiresMountsFor", source)
serviceUnitFile.AddEscaped(UnitGroup, "RequiresMountsFor", source)
} else if strings.HasSuffix(source, ".volume") || (checkImage && strings.HasSuffix(source, ".image")) || strings.HasSuffix(source, ".artifact") {
sourceUnitInfo, ok := unitsInfoMap[source]
if !ok {

View File

@@ -1,7 +1,7 @@
## assert-key-contains Service ExecStart " --opt type=bind "
## assert-key-contains Service ExecStart " --opt device=/var/lib/data "
## assert-key-contains Service ExecStart " --opt nocopy "
## assert-key-contains Unit RequiresMountsFor "/var/lib/data"
## assert-last-key-contains Service ExecStart " --opt type=bind "
## assert-last-key-contains Service ExecStart " --opt device=/var/lib/data "
## assert-last-key-contains Service ExecStart " --opt nocopy "
## assert-last-key-contains Unit RequiresMountsFor "/var/lib/data"
[Volume]
Device=/var/lib/data

View File

@@ -1,7 +1,7 @@
## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
## assert-key-contains Service ExecStart " --opt type=btrfs "
## assert-key-contains Service ExecStart " --opt device=/dev/vda1 "
## assert-key-contains Service ExecStart " --opt copy "
## assert-last-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
## assert-last-key-contains Service ExecStart " --opt type=btrfs "
## assert-last-key-contains Service ExecStart " --opt device=/dev/vda1 "
## assert-last-key-contains Service ExecStart " --opt copy "
[Volume]
# Test usernames too

View File

@@ -1,7 +1,7 @@
## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
## assert-key-contains Service ExecStart " --opt type=btrfs "
## assert-key-contains Service ExecStart " --opt device=/dev/vda1 "
## assert-key-contains Service ExecStart " --opt nocopy "
## assert-last-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
## assert-last-key-contains Service ExecStart " --opt type=btrfs "
## assert-last-key-contains Service ExecStart " --opt device=/dev/vda1 "
## assert-last-key-contains Service ExecStart " --opt nocopy "
[Volume]
# Test usernames too

View File

@@ -2,7 +2,7 @@
## assert-podman-args "--ipv6"
## assert-key-is Service Type exec
## assert-key-is Service RemainAfterExit no
## assert-key-contains Service SyslogIdentifier "Modify %N"
## assert-last-key-contains Service SyslogIdentifier "Modify %N"
[Network]
IPv6=yes

View File

@@ -1,6 +1,6 @@
## assert-key-contains Service ExecStart " --label org.foo.Arg1=arg1 "
## assert-key-contains Service ExecStart " --label org.foo.Arg2=arg2 "
## assert-key-contains Service ExecStart " --label org.foo.Arg3=arg3 "
## assert-last-key-contains Service ExecStart " --label org.foo.Arg1=arg1 "
## assert-last-key-contains Service ExecStart " --label org.foo.Arg2=arg2 "
## assert-last-key-contains Service ExecStart " --label org.foo.Arg3=arg3 "
[Volume]
Label=org.foo.Arg1=arg1

View File

@@ -1,7 +1,11 @@
[Container]
Image=localhost/imagename
## assert-has-key Unit RequiresMountsFor "/path/on/host"
## assert-podman-args-key-val "--mount" "," "type=bind,source=/path/on/host,destination=/path/in/container"
Mount=type=bind,source=/path/on/host,destination=/path/in/container
## assert-has-key Unit RequiresMountsFor "\"/path/on/host\\x20with\\x20spaces\""
## assert-podman-args-key-val "--mount" "," "type=bind,source=/path/on/host with spaces,dst=/path"
Mount="type=bind,src=/path/on/host with spaces,dst=/path"
## assert-podman-args-key-val "--mount" "," "type=bind,source=/path/on/host,dst=/path/in/container,relabel=shared"
Mount=type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared
## assert-podman-args-key-val "--mount" "," "type=bind,source=/path/on/host,dst=/path/in/container,relabel=shared,U=true"

View File

@@ -1,7 +1,7 @@
## assert-key-contains "Unit" "Wants" "startwithpod_yes.service"
## assert-key-contains "Unit" "Before" "startwithpod_yes.service"
## assert-last-key-contains "Unit" "Wants" "startwithpod_yes.service"
## assert-last-key-contains "Unit" "Before" "startwithpod_yes.service"
## assert-key-not-contains "Unit" "Wants" "startwithpod_no.service"
## assert-key-not-contains "Unit" "Before" "startwithpod_no.service"
## assert-last-key-not-contains "Unit" "Wants" "startwithpod_no.service"
## assert-last-key-not-contains "Unit" "Before" "startwithpod_no.service"
[Pod]

View File

@@ -1,5 +1,5 @@
# assert-key-contains "Unit" "After" "startwithpod-pod.service"
# assert-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
# assert-last-key-contains "Unit" "After" "startwithpod-pod.service"
# assert-last-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
[Container]
Image=localhost/image

View File

@@ -1,5 +1,5 @@
# assert-key-contains "Unit" "After" "startwithpod-pod.service"
# assert-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
# assert-last-key-contains "Unit" "After" "startwithpod-pod.service"
# assert-last-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
[Container]
Image=localhost/image

View File

@@ -1,7 +1,7 @@
## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11 "
## assert-last-key-contains Service ExecStart " --opt o=uid=0,gid=11 "
## assert-key-is Service Type oneshot
## assert-key-is Service RemainAfterExit no
## assert-key-contains Service SyslogIdentifier "Modify %N"
## assert-last-key-contains Service SyslogIdentifier "Modify %N"
[Volume]
# Test usernames too

View File

@@ -9,6 +9,7 @@ import (
"path/filepath"
"reflect"
"regexp"
"slices"
"strings"
"github.com/containers/podman/v6/pkg/systemd/parser"
@@ -172,6 +173,16 @@ func (t *quadletTestcase) assertKeyIs(args []string, unit *parser.UnitFile) bool
return true
}
func (t *quadletTestcase) assertHasKey(args []string, unit *parser.UnitFile) bool {
Expect(args).To(HaveLen(3))
group := args[0]
key := args[1]
value := args[2]
realValues := unit.LookupAll(group, key)
return slices.Contains(realValues, value)
}
func (t *quadletTestcase) assertKeyIsEmpty(args []string, unit *parser.UnitFile) bool {
Expect(args).To(HaveLen(2))
group := args[0]
@@ -219,7 +230,7 @@ func (t *quadletTestcase) assertLastKeyIsRegex(args []string, unit *parser.UnitF
return true
}
func (t *quadletTestcase) assertKeyContains(args []string, unit *parser.UnitFile) bool {
func (t *quadletTestcase) assertLastKeyContains(args []string, unit *parser.UnitFile) bool {
Expect(args).To(HaveLen(3))
group := args[0]
key := args[1]
@@ -229,8 +240,8 @@ func (t *quadletTestcase) assertKeyContains(args []string, unit *parser.UnitFile
return ok && strings.Contains(realValue, value)
}
func (t *quadletTestcase) assertKeyNotContains(args []string, unit *parser.UnitFile) bool {
return !t.assertKeyContains(args, unit)
func (t *quadletTestcase) assertLastKeyNotContains(args []string, unit *parser.UnitFile) bool {
return !t.assertLastKeyContains(args, unit)
}
func (t *quadletTestcase) assertPodmanArgs(args []string, unit *parser.UnitFile, key string, allowRegex, globalOnly bool) bool {
@@ -540,14 +551,16 @@ func (t *quadletTestcase) doAssert(check []string, unit *parser.UnitFile, sessio
ok = t.assertStdErrContains(args, session)
case "assert-key-is":
ok = t.assertKeyIs(args, unit)
case "assert-has-key":
ok = t.assertHasKey(args, unit)
case "assert-key-is-empty":
ok = t.assertKeyIsEmpty(args, unit)
case "assert-key-is-regex":
ok = t.assertKeyIsRegex(args, unit)
case "assert-key-contains":
ok = t.assertKeyContains(args, unit)
case "assert-key-not-contains":
ok = t.assertKeyNotContains(args, unit)
case "assert-last-key-contains":
ok = t.assertLastKeyContains(args, unit)
case "assert-last-key-not-contains":
ok = t.assertLastKeyNotContains(args, unit)
case "assert-last-key-is-regex":
ok = t.assertLastKeyIsRegex(args, unit)
case "assert-podman-args":