mirror of
https://github.com/containers/podman.git
synced 2025-05-31 15:42:48 +08:00

In a systemd unit dollar and percent signs are used for variables. A backslash is used for escape sequences. If any of these characters are used in the create command we have to properly escape them so systemd does not try to interpret them. Fixes #9176 Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
109 lines
3.3 KiB
Go
109 lines
3.3 KiB
Go
package generate
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// EnvVariable "PODMAN_SYSTEMD_UNIT" is set in all generated systemd units and
|
|
// is set to the unit's (unique) name.
|
|
const EnvVariable = "PODMAN_SYSTEMD_UNIT"
|
|
|
|
// minTimeoutStopSec is the minimal stop timeout for generated systemd units.
|
|
// Once exceeded, processes of the services are killed and the cgroup(s) are
|
|
// cleaned up.
|
|
const minTimeoutStopSec = 60
|
|
|
|
// RestartPolicies includes all valid restart policies to be used in a unit
|
|
// file.
|
|
var RestartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"}
|
|
|
|
// validateRestartPolicy checks that the user-provided policy is valid.
|
|
func validateRestartPolicy(restart string) error {
|
|
for _, i := range RestartPolicies {
|
|
if i == restart {
|
|
return nil
|
|
}
|
|
}
|
|
return errors.Errorf("%s is not a valid restart policy", restart)
|
|
}
|
|
|
|
const headerTemplate = `# {{{{.ServiceName}}}}.service
|
|
# autogenerated by Podman {{{{.PodmanVersion}}}}
|
|
{{{{- if .TimeStamp}}}}
|
|
# {{{{.TimeStamp}}}}
|
|
{{{{- end}}}}
|
|
|
|
[Unit]
|
|
Description=Podman {{{{.ServiceName}}}}.service
|
|
Documentation=man:podman-generate-systemd(1)
|
|
Wants=network.target
|
|
After=network-online.target
|
|
`
|
|
|
|
// filterPodFlags removes --pod and --pod-id-file from the specified command.
|
|
func filterPodFlags(command []string) []string {
|
|
processed := []string{}
|
|
for i := 0; i < len(command); i++ {
|
|
s := command[i]
|
|
if s == "--pod" || s == "--pod-id-file" {
|
|
i++
|
|
continue
|
|
}
|
|
if strings.HasPrefix(s, "--pod=") || strings.HasPrefix(s, "--pod-id-file=") {
|
|
continue
|
|
}
|
|
processed = append(processed, s)
|
|
}
|
|
return processed
|
|
}
|
|
|
|
// escapeSystemdArguments makes sure that all arguments with at least one whitespace
|
|
// are quoted to make sure those are interpreted as one argument instead of
|
|
// multiple ones. Also make sure to escape all characters which have a special
|
|
// meaning to systemd -> $,% and \
|
|
// see: https://www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines
|
|
func escapeSystemdArguments(command []string) []string {
|
|
for i := range command {
|
|
command[i] = strings.ReplaceAll(command[i], "$", "$$")
|
|
command[i] = strings.ReplaceAll(command[i], "%", "%%")
|
|
if strings.ContainsAny(command[i], " \t") {
|
|
command[i] = strconv.Quote(command[i])
|
|
} else if strings.Contains(command[i], `\`) {
|
|
// strconv.Quote also escapes backslashes so
|
|
// we should replace only if strconv.Quote was not used
|
|
command[i] = strings.ReplaceAll(command[i], `\`, `\\`)
|
|
}
|
|
}
|
|
return command
|
|
}
|
|
|
|
func removeDetachArg(args []string, argCount int) []string {
|
|
// "--detach=false" could also be in the container entrypoint
|
|
// split them off so we do not remove it there
|
|
realArgs := args[len(args)-argCount:]
|
|
flagArgs := removeArg("-d=false", args[:len(args)-argCount])
|
|
flagArgs = removeArg("--detach=false", flagArgs)
|
|
return append(flagArgs, realArgs...)
|
|
}
|
|
|
|
func removeReplaceArg(args []string, argCount int) []string {
|
|
// "--replace=false" could also be in the container entrypoint
|
|
// split them off so we do not remove it there
|
|
realArgs := args[len(args)-argCount:]
|
|
flagArgs := removeArg("--replace=false", args[:len(args)-argCount])
|
|
return append(flagArgs, realArgs...)
|
|
}
|
|
|
|
func removeArg(arg string, args []string) []string {
|
|
newArgs := []string{}
|
|
for _, a := range args {
|
|
if a != arg {
|
|
newArgs = append(newArgs, a)
|
|
}
|
|
}
|
|
return newArgs
|
|
}
|