mirror of
				https://github.com/containers/podman.git
				synced 2025-11-04 17:07:20 +08:00 
			
		
		
		
	Moving from Go module v4 to v5 prepares us for public releases. Move done using gomove [1] as with the v3 and v4 moves. [1] https://github.com/KSubedi/gomove Signed-off-by: Matt Heon <mheon@redhat.com>
		
			
				
	
	
		
			174 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//go:build !remote
 | 
						|
 | 
						|
package generate
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/containers/podman/v5/pkg/systemd/define"
 | 
						|
)
 | 
						|
 | 
						|
// 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
 | 
						|
 | 
						|
// validateRestartPolicy checks that the user-provided policy is valid.
 | 
						|
func validateRestartPolicy(restart string) error {
 | 
						|
	for _, i := range define.RestartPolicies {
 | 
						|
		if i == restart {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return fmt.Errorf("%s is not a valid restart policy", restart)
 | 
						|
}
 | 
						|
 | 
						|
const headerTemplate = `# {{{{.ServiceName}}}}{{{{- if (eq .IdentifySpecifier true) }}}}@{{{{- end}}}}.service
 | 
						|
{{{{- if (eq .GenerateNoHeader false) }}}}
 | 
						|
# autogenerated by Podman {{{{.PodmanVersion}}}}
 | 
						|
{{{{- if .TimeStamp}}}}
 | 
						|
# {{{{.TimeStamp}}}}
 | 
						|
{{{{- end}}}}
 | 
						|
{{{{- end}}}}
 | 
						|
 | 
						|
[Unit]
 | 
						|
Description=Podman {{{{.ServiceName}}}}.service{{{{- if (eq .IdentifySpecifier true) }}}} for %I{{{{- end}}}}
 | 
						|
Documentation=man:podman-generate-systemd(1)
 | 
						|
Wants=network-online.target
 | 
						|
After=network-online.target
 | 
						|
RequiresMountsFor={{{{.RunRoot}}}}
 | 
						|
`
 | 
						|
 | 
						|
// filterPodFlags removes --pod, --pod-id-file and --infra-conmon-pidfile from the specified command.
 | 
						|
// argCount is the number of last arguments which should not be filtered, e.g. the container entrypoint.
 | 
						|
func filterPodFlags(command []string, argCount int) []string {
 | 
						|
	processed := make([]string, 0, len(command))
 | 
						|
	for i := 0; i < len(command)-argCount; i++ {
 | 
						|
		s := command[i]
 | 
						|
		if s == "--pod" || s == "--pod-id-file" || s == "--infra-conmon-pidfile" {
 | 
						|
			i++
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if strings.HasPrefix(s, "--pod=") ||
 | 
						|
			strings.HasPrefix(s, "--pod-id-file=") ||
 | 
						|
			strings.HasPrefix(s, "--infra-conmon-pidfile=") {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		processed = append(processed, s)
 | 
						|
	}
 | 
						|
	processed = append(processed, command[len(command)-argCount:]...)
 | 
						|
	return processed
 | 
						|
}
 | 
						|
 | 
						|
// filterCommonContainerFlags removes --sdnotify, --rm and --cgroups from the specified command.
 | 
						|
// argCount is the number of last arguments which should not be filtered, e.g. the container entrypoint.
 | 
						|
func filterCommonContainerFlags(command []string, argCount int) []string {
 | 
						|
	processed := make([]string, 0, len(command))
 | 
						|
	for i := 0; i < len(command)-argCount; i++ {
 | 
						|
		s := command[i]
 | 
						|
 | 
						|
		switch {
 | 
						|
		case s == "--rm":
 | 
						|
			// Boolean flags support --flag and --flag={true,false}.
 | 
						|
			continue
 | 
						|
		case s == "--cgroups", s == "--cidfile", s == "--restart":
 | 
						|
			i++
 | 
						|
			continue
 | 
						|
		case strings.HasPrefix(s, "--rm="),
 | 
						|
			strings.HasPrefix(s, "--cgroups="),
 | 
						|
			strings.HasPrefix(s, "--cidfile="),
 | 
						|
			strings.HasPrefix(s, "--restart="):
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		processed = append(processed, s)
 | 
						|
	}
 | 
						|
	processed = append(processed, command[len(command)-argCount:]...)
 | 
						|
	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] = escapeSystemdArg(command[i])
 | 
						|
	}
 | 
						|
	return command
 | 
						|
}
 | 
						|
 | 
						|
func escapeSystemdArg(arg string) string {
 | 
						|
	arg = strings.ReplaceAll(arg, "$", "$$")
 | 
						|
	arg = strings.ReplaceAll(arg, "%", "%%")
 | 
						|
	if strings.ContainsAny(arg, " \t\"") {
 | 
						|
		arg = strconv.Quote(arg)
 | 
						|
	} else if strings.Contains(arg, `\`) {
 | 
						|
		// strconv.Quote also escapes backslashes so
 | 
						|
		// we should replace only if strconv.Quote was not used
 | 
						|
		arg = strings.ReplaceAll(arg, `\`, `\\`)
 | 
						|
	}
 | 
						|
	return arg
 | 
						|
}
 | 
						|
 | 
						|
func removeSdNotifyArg(args []string, argCount int) []string {
 | 
						|
	processed := make([]string, 0, len(args))
 | 
						|
	for i := 0; i < len(args)-argCount; i++ {
 | 
						|
		s := args[i]
 | 
						|
 | 
						|
		switch {
 | 
						|
		case s == "--sdnotify":
 | 
						|
			i++
 | 
						|
			continue
 | 
						|
		case strings.HasPrefix(s, "--sdnotify="):
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		processed = append(processed, s)
 | 
						|
	}
 | 
						|
	processed = append(processed, args[len(args)-argCount:]...)
 | 
						|
	return processed
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
// This function is used to get name of systemd service from prefix, separator, and
 | 
						|
// container/pod name. If prefix is empty, the service name does not include the
 | 
						|
// separator. This is to avoid a situation where service name starts with the separator
 | 
						|
// which is usually hyphen.
 | 
						|
func getServiceName(prefix string, separator string, name string) string {
 | 
						|
	serviceName := name
 | 
						|
 | 
						|
	if len(prefix) > 0 {
 | 
						|
		serviceName = prefix + separator + name
 | 
						|
	}
 | 
						|
 | 
						|
	return serviceName
 | 
						|
}
 |