diff options
author | Valentin Rothberg <rothberg@redhat.com> | 2020-01-09 12:27:24 +0100 |
---|---|---|
committer | Valentin Rothberg <rothberg@redhat.com> | 2020-01-09 16:12:12 +0100 |
commit | 816e50ba02837946afade83e3cad06dd44d213ec (patch) | |
tree | 67834eb73ab890cb4c9fba8d37f68e3fdec9dcd6 /pkg/systemdgen/systemdgen.go | |
parent | f3fc10feb42930def6922fc050096ea38bafed7a (diff) | |
download | podman-816e50ba02837946afade83e3cad06dd44d213ec.tar.gz podman-816e50ba02837946afade83e3cad06dd44d213ec.tar.bz2 podman-816e50ba02837946afade83e3cad06dd44d213ec.zip |
podman-generate-systemd --new
Add a --new flag to podman-generate-systemd to create a new container
via podman-run instead of starting an existing container.
Creating a new container presents the challenge to find a reverse
mapping from a container to the CLI flags it can be created with. We
are doing this via `(Container).Config.CreateCommand` field, which
includes a copy of the process' command from procFS at creating time.
This field may not be useful when the container was not created via the
Podman CLI (e.g., via a Python script). Hence, we do not guarantee the
correctness of the generated files.
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'pkg/systemdgen/systemdgen.go')
-rw-r--r-- | pkg/systemdgen/systemdgen.go | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemdgen/systemdgen.go index 09d3c6fd5..b6167a23e 100644 --- a/pkg/systemdgen/systemdgen.go +++ b/pkg/systemdgen/systemdgen.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "sort" + "strings" "text/template" "time" @@ -48,6 +49,14 @@ type ContainerInfo struct { Executable string // TimeStamp at the time of creating the unit file. Will be set internally. TimeStamp string + // New controls if a new container is created or if an existing one is started. + New bool + // CreateCommand is the full command plus arguments of the process the + // container has been created with. + CreateCommand []string + // RunCommand is a post-processed variant of CreateCommand and used for + // the ExecStart field in generic unit files. + RunCommand string } var restartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"} @@ -84,17 +93,35 @@ Before={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ [Service] Restart={{.RestartPolicy}} +{{- if .New}} +ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid +ExecStart={{.RunCommand}} +ExecStop={{.Executable}} stop --cidfile /%t/%n-cid {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} +ExecStopPost={{.Executable}} rm -f --cidfile /%t/%n-cid +PIDFile=/%t/%n-pid +{{- else}} ExecStart={{.Executable}} start {{.ContainerName}} ExecStop={{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.ContainerName}} +PIDFile={{.PIDFile}} +{{- end}} KillMode=none Type=forking -PIDFile={{.PIDFile}} [Install] WantedBy=multi-user.target` +// Options include different options to control the unit file generation. +type Options struct { + // When set, generate service files in the current working directory and + // return the paths to these files instead of returning all contents in one + // big string. + Files bool + // New controls if a new container is created or if an existing one is started. + New bool +} + // CreateContainerSystemdUnit creates a systemd unit file for a container. -func CreateContainerSystemdUnit(info *ContainerInfo, generateFiles bool) (string, error) { +func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, error) { if err := validateRestartPolicy(info.RestartPolicy); err != nil { return "", err } @@ -109,6 +136,36 @@ func CreateContainerSystemdUnit(info *ContainerInfo, generateFiles bool) (string info.Executable = executable } + // Assemble the ExecStart command when creating a new container. + // + // Note that we cannot catch all corner cases here such that users + // *must* manually check the generated files. A container might have + // been created via a Python script, which would certainly yield an + // invalid `info.CreateCommand`. Hence, we're doing a best effort unit + // generation and don't try aiming at completeness. + if opts.New { + // The create command must at least have three arguments: + // /usr/bin/podman run $IMAGE + index := 2 + if info.CreateCommand[1] == "container" { + index = 3 + } + if len(info.CreateCommand) < index+1 { + return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand) + } + // We're hard-coding the first four arguments and append the + // CreatCommand with a stripped command and subcomand. + command := []string{ + info.Executable, + "run", + "--conmon-pidfile", "/%t/%n-pid", + "--cidfile", "/%t/%n-cid", + } + command = append(command, info.CreateCommand[index:]...) + info.RunCommand = strings.Join(command, " ") + info.New = true + } + if info.PodmanVersion == "" { info.PodmanVersion = version.Version } @@ -131,7 +188,7 @@ func CreateContainerSystemdUnit(info *ContainerInfo, generateFiles bool) (string return "", err } - if !generateFiles { + if !opts.Files { return buf.String(), nil } |