mirror of
https://github.com/containers/podman.git
synced 2025-11-30 01:58:46 +08:00
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:
@@ -879,6 +879,15 @@ func (f *UnitFile) Add(groupName string, key string, value string) {
|
|||||||
group.add(key, value)
|
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) {
|
func (f *UnitFile) AddCmdline(groupName string, key string, args []string) {
|
||||||
f.Add(groupName, key, escapeWords(args))
|
f.Add(groupName, key, escapeWords(args))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1151,7 +1151,7 @@ func ConvertVolume(volume *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, i
|
|||||||
if devValid {
|
if devValid {
|
||||||
podman.add("--opt", fmt.Sprintf("type=%s", devType))
|
podman.add("--opt", fmt.Sprintf("type=%s", devType))
|
||||||
if devType == "bind" {
|
if devType == "bind" {
|
||||||
service.Add(UnitGroup, "RequiresMountsFor", dev)
|
service.AddEscaped(UnitGroup, "RequiresMountsFor", dev)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, warnings, fmt.Errorf("key Type can't be used without Device")
|
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] == '/' {
|
if source[0] == '/' {
|
||||||
// Absolute path
|
// 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") {
|
} else if strings.HasSuffix(source, ".volume") || (checkImage && strings.HasSuffix(source, ".image")) || strings.HasSuffix(source, ".artifact") {
|
||||||
sourceUnitInfo, ok := unitsInfoMap[source]
|
sourceUnitInfo, ok := unitsInfoMap[source]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
## assert-key-contains Service ExecStart " --opt type=bind "
|
## assert-last-key-contains Service ExecStart " --opt type=bind "
|
||||||
## assert-key-contains Service ExecStart " --opt device=/var/lib/data "
|
## assert-last-key-contains Service ExecStart " --opt device=/var/lib/data "
|
||||||
## assert-key-contains Service ExecStart " --opt nocopy "
|
## assert-last-key-contains Service ExecStart " --opt nocopy "
|
||||||
## assert-key-contains Unit RequiresMountsFor "/var/lib/data"
|
## assert-last-key-contains Unit RequiresMountsFor "/var/lib/data"
|
||||||
|
|
||||||
[Volume]
|
[Volume]
|
||||||
Device=/var/lib/data
|
Device=/var/lib/data
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
|
## assert-last-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
|
||||||
## assert-key-contains Service ExecStart " --opt type=btrfs "
|
## assert-last-key-contains Service ExecStart " --opt type=btrfs "
|
||||||
## assert-key-contains Service ExecStart " --opt device=/dev/vda1 "
|
## assert-last-key-contains Service ExecStart " --opt device=/dev/vda1 "
|
||||||
## assert-key-contains Service ExecStart " --opt copy "
|
## assert-last-key-contains Service ExecStart " --opt copy "
|
||||||
|
|
||||||
[Volume]
|
[Volume]
|
||||||
# Test usernames too
|
# Test usernames too
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
## assert-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
|
## assert-last-key-contains Service ExecStart " --opt o=uid=0,gid=11,rw,compress=zstd "
|
||||||
## assert-key-contains Service ExecStart " --opt type=btrfs "
|
## assert-last-key-contains Service ExecStart " --opt type=btrfs "
|
||||||
## assert-key-contains Service ExecStart " --opt device=/dev/vda1 "
|
## assert-last-key-contains Service ExecStart " --opt device=/dev/vda1 "
|
||||||
## assert-key-contains Service ExecStart " --opt nocopy "
|
## assert-last-key-contains Service ExecStart " --opt nocopy "
|
||||||
|
|
||||||
[Volume]
|
[Volume]
|
||||||
# Test usernames too
|
# Test usernames too
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
## assert-podman-args "--ipv6"
|
## assert-podman-args "--ipv6"
|
||||||
## assert-key-is Service Type exec
|
## assert-key-is Service Type exec
|
||||||
## assert-key-is Service RemainAfterExit no
|
## assert-key-is Service RemainAfterExit no
|
||||||
## assert-key-contains Service SyslogIdentifier "Modify %N"
|
## assert-last-key-contains Service SyslogIdentifier "Modify %N"
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
IPv6=yes
|
IPv6=yes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## assert-key-contains Service ExecStart " --label org.foo.Arg1=arg1 "
|
## assert-last-key-contains Service ExecStart " --label org.foo.Arg1=arg1 "
|
||||||
## assert-key-contains Service ExecStart " --label org.foo.Arg2=arg2 "
|
## assert-last-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.Arg3=arg3 "
|
||||||
|
|
||||||
[Volume]
|
[Volume]
|
||||||
Label=org.foo.Arg1=arg1
|
Label=org.foo.Arg1=arg1
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
[Container]
|
[Container]
|
||||||
Image=localhost/imagename
|
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"
|
## 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
|
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"
|
## 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
|
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"
|
## assert-podman-args-key-val "--mount" "," "type=bind,source=/path/on/host,dst=/path/in/container,relabel=shared,U=true"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
## assert-key-contains "Unit" "Wants" "startwithpod_yes.service"
|
## assert-last-key-contains "Unit" "Wants" "startwithpod_yes.service"
|
||||||
## assert-key-contains "Unit" "Before" "startwithpod_yes.service"
|
## assert-last-key-contains "Unit" "Before" "startwithpod_yes.service"
|
||||||
|
|
||||||
## assert-key-not-contains "Unit" "Wants" "startwithpod_no.service"
|
## assert-last-key-not-contains "Unit" "Wants" "startwithpod_no.service"
|
||||||
## assert-key-not-contains "Unit" "Before" "startwithpod_no.service"
|
## assert-last-key-not-contains "Unit" "Before" "startwithpod_no.service"
|
||||||
|
|
||||||
[Pod]
|
[Pod]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# assert-key-contains "Unit" "After" "startwithpod-pod.service"
|
# assert-last-key-contains "Unit" "After" "startwithpod-pod.service"
|
||||||
# assert-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
|
# assert-last-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
|
||||||
|
|
||||||
[Container]
|
[Container]
|
||||||
Image=localhost/image
|
Image=localhost/image
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# assert-key-contains "Unit" "After" "startwithpod-pod.service"
|
# assert-last-key-contains "Unit" "After" "startwithpod-pod.service"
|
||||||
# assert-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
|
# assert-last-key-contains "Unit" "BindsTo" "startwithpod-pod.service"
|
||||||
|
|
||||||
[Container]
|
[Container]
|
||||||
Image=localhost/image
|
Image=localhost/image
|
||||||
|
|||||||
@@ -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 Type oneshot
|
||||||
## assert-key-is Service RemainAfterExit no
|
## assert-key-is Service RemainAfterExit no
|
||||||
## assert-key-contains Service SyslogIdentifier "Modify %N"
|
## assert-last-key-contains Service SyslogIdentifier "Modify %N"
|
||||||
|
|
||||||
[Volume]
|
[Volume]
|
||||||
# Test usernames too
|
# Test usernames too
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/podman/v6/pkg/systemd/parser"
|
"github.com/containers/podman/v6/pkg/systemd/parser"
|
||||||
@@ -172,6 +173,16 @@ func (t *quadletTestcase) assertKeyIs(args []string, unit *parser.UnitFile) bool
|
|||||||
return true
|
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 {
|
func (t *quadletTestcase) assertKeyIsEmpty(args []string, unit *parser.UnitFile) bool {
|
||||||
Expect(args).To(HaveLen(2))
|
Expect(args).To(HaveLen(2))
|
||||||
group := args[0]
|
group := args[0]
|
||||||
@@ -219,7 +230,7 @@ func (t *quadletTestcase) assertLastKeyIsRegex(args []string, unit *parser.UnitF
|
|||||||
return true
|
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))
|
Expect(args).To(HaveLen(3))
|
||||||
group := args[0]
|
group := args[0]
|
||||||
key := args[1]
|
key := args[1]
|
||||||
@@ -229,8 +240,8 @@ func (t *quadletTestcase) assertKeyContains(args []string, unit *parser.UnitFile
|
|||||||
return ok && strings.Contains(realValue, value)
|
return ok && strings.Contains(realValue, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *quadletTestcase) assertKeyNotContains(args []string, unit *parser.UnitFile) bool {
|
func (t *quadletTestcase) assertLastKeyNotContains(args []string, unit *parser.UnitFile) bool {
|
||||||
return !t.assertKeyContains(args, unit)
|
return !t.assertLastKeyContains(args, unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *quadletTestcase) assertPodmanArgs(args []string, unit *parser.UnitFile, key string, allowRegex, globalOnly bool) bool {
|
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)
|
ok = t.assertStdErrContains(args, session)
|
||||||
case "assert-key-is":
|
case "assert-key-is":
|
||||||
ok = t.assertKeyIs(args, unit)
|
ok = t.assertKeyIs(args, unit)
|
||||||
|
case "assert-has-key":
|
||||||
|
ok = t.assertHasKey(args, unit)
|
||||||
case "assert-key-is-empty":
|
case "assert-key-is-empty":
|
||||||
ok = t.assertKeyIsEmpty(args, unit)
|
ok = t.assertKeyIsEmpty(args, unit)
|
||||||
case "assert-key-is-regex":
|
case "assert-key-is-regex":
|
||||||
ok = t.assertKeyIsRegex(args, unit)
|
ok = t.assertKeyIsRegex(args, unit)
|
||||||
case "assert-key-contains":
|
case "assert-last-key-contains":
|
||||||
ok = t.assertKeyContains(args, unit)
|
ok = t.assertLastKeyContains(args, unit)
|
||||||
case "assert-key-not-contains":
|
case "assert-last-key-not-contains":
|
||||||
ok = t.assertKeyNotContains(args, unit)
|
ok = t.assertLastKeyNotContains(args, unit)
|
||||||
case "assert-last-key-is-regex":
|
case "assert-last-key-is-regex":
|
||||||
ok = t.assertLastKeyIsRegex(args, unit)
|
ok = t.assertLastKeyIsRegex(args, unit)
|
||||||
case "assert-podman-args":
|
case "assert-podman-args":
|
||||||
|
|||||||
Reference in New Issue
Block a user