diff options
Diffstat (limited to 'pkg/systemd/generate/containers.go')
-rw-r--r-- | pkg/systemd/generate/containers.go | 109 |
1 files changed, 65 insertions, 44 deletions
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go index fb0ea5cf9..f316d4452 100644 --- a/pkg/systemd/generate/containers.go +++ b/pkg/systemd/generate/containers.go @@ -11,22 +11,20 @@ import ( "text/template" "time" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/version" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) -// 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" - -// ContainerInfo contains data required for generating a container's systemd +// containerInfo contains data required for generating a container's systemd // unit file. -type ContainerInfo struct { +type containerInfo struct { // ServiceName of the systemd service. ServiceName string // Name or ID of the container. - ContainerName string + ContainerNameOrID string // StopTimeout sets the timeout Podman waits before killing the container // during service stop. StopTimeout uint @@ -63,29 +61,7 @@ type ContainerInfo struct { EnvVariable string } -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 containerTemplate = `# {{.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 +const containerTemplate = headerTemplate + ` {{- if .BoundToServices}} RefuseManualStart=yes RefuseManualStop=yes @@ -107,8 +83,8 @@ ExecStop={{.Executable}} stop --ignore --cidfile %t/%n-ctr-id {{if (ge .StopTime ExecStopPost={{.Executable}} rm --ignore -f --cidfile %t/%n-ctr-id PIDFile=%t/%n-pid {{- else}} -ExecStart={{.Executable}} start {{.ContainerName}} -ExecStop={{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.ContainerName}} +ExecStart={{.Executable}} start {{.ContainerNameOrID}} +ExecStop={{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.ContainerNameOrID}} PIDFile={{.PIDFile}} {{- end}} KillMode=none @@ -117,18 +93,19 @@ Type=forking [Install] WantedBy=multi-user.target default.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 +// ContainerUnit generates a systemd unit for the specified container. Based +// on the options, the return value might be the entire unit or a file it has +// been written to. +func ContainerUnit(ctr *libpod.Container, options entities.GenerateSystemdOptions) (string, error) { + info, err := generateContainerInfo(ctr, options) + if err != nil { + return "", err + } + return createContainerSystemdUnit(info, options) } -// CreateContainerSystemdUnit creates a systemd unit file for a container. -func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, error) { +// createContainerSystemdUnit creates a systemd unit file for a container. +func createContainerSystemdUnit(info *containerInfo, options entities.GenerateSystemdOptions) (string, error) { if err := validateRestartPolicy(info.RestartPolicy); err != nil { return "", err } @@ -152,7 +129,7 @@ func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, erro // 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 { + if options.New { // The create command must at least have three arguments: // /usr/bin/podman run $IMAGE index := 2 @@ -218,7 +195,7 @@ func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, erro return "", err } - if !opts.Files { + if !options.Files { return buf.String(), nil } @@ -233,3 +210,47 @@ func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, erro } return path, nil } + +func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSystemdOptions) (*containerInfo, error) { + timeout := ctr.StopTimeout() + if options.StopTimeout != nil { + timeout = *options.StopTimeout + } + + config := ctr.Config() + conmonPidFile := config.ConmonPidFile + if conmonPidFile == "" { + return nil, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag") + } + + createCommand := []string{} + if config.CreateCommand != nil { + createCommand = config.CreateCommand + } else if options.New { + return nil, errors.Errorf("cannot use --new on container %q: no create command found", ctr.ID()) + } + + nameOrID, serviceName := containerServiceName(ctr, options) + + info := containerInfo{ + ServiceName: serviceName, + ContainerNameOrID: nameOrID, + RestartPolicy: options.RestartPolicy, + PIDFile: conmonPidFile, + StopTimeout: timeout, + GenerateTimestamp: true, + CreateCommand: createCommand, + } + return &info, nil +} + +// containerServiceName returns the nameOrID and the service name of the +// container. +func containerServiceName(ctr *libpod.Container, options entities.GenerateSystemdOptions) (string, string) { + nameOrID := ctr.ID() + if options.Name { + nameOrID = ctr.Name() + } + serviceName := fmt.Sprintf("%s%s%s", options.ContainerPrefix, options.Separator, nameOrID) + return nameOrID, serviceName +} |