From c9ad1da51c6b1aa7eb531a2f9951aa853bdea109 Mon Sep 17 00:00:00 2001 From: Ondra Machacek Date: Thu, 2 Dec 2021 13:44:35 +0100 Subject: Add restart-sec option to systemd generate Signed-off-by: Ondra Machacek --- cmd/podman/generate/systemd.go | 8 ++++ docs/source/markdown/podman-generate-systemd.1.md | 5 +++ pkg/api/handlers/libpod/generate.go | 2 + pkg/api/server/register_generate.go | 5 +++ pkg/bindings/generate/types.go | 2 + pkg/bindings/generate/types_systemd_options.go | 15 ++++++++ pkg/domain/entities/generate.go | 2 + pkg/domain/infra/tunnel/generate.go | 3 ++ pkg/systemd/generate/pods.go | 9 +++++ pkg/systemd/generate/pods_test.go | 46 +++++++++++++++++++++++ test/e2e/generate_systemd_test.go | 13 +++++++ 11 files changed, 110 insertions(+) diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go index 173b3656b..a363b7e94 100644 --- a/cmd/podman/generate/systemd.go +++ b/cmd/podman/generate/systemd.go @@ -23,6 +23,7 @@ const ( stopTimeoutFlagName = "stop-timeout" stopTimeoutCompatFlagName = "time" restartPolicyFlagName = "restart-policy" + restartSecFlagName = "restart-sec" newFlagName = "new" ) @@ -30,6 +31,7 @@ var ( files bool format string systemdRestart string + systemdRestartSec uint startTimeout uint stopTimeout uint systemdOptions = entities.GenerateSystemdOptions{} @@ -88,6 +90,9 @@ func init() { flags.StringVar(&systemdRestart, restartPolicyFlagName, systemDefine.DefaultRestartPolicy, "Systemd restart-policy") _ = systemdCmd.RegisterFlagCompletionFunc(restartPolicyFlagName, common.AutocompleteSystemdRestartOptions) + flags.UintVarP(&systemdRestartSec, restartSecFlagName, "", 0, "Systemd restart-sec") + _ = systemdCmd.RegisterFlagCompletionFunc(restartSecFlagName, completion.AutocompleteNone) + formatFlagName := "format" flags.StringVar(&format, formatFlagName, "", "Print the created units in specified format (json)") _ = systemdCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(nil)) @@ -111,6 +116,9 @@ func systemd(cmd *cobra.Command, args []string) error { systemdOptions.New = true } + if cmd.Flags().Changed(restartSecFlagName) { + systemdOptions.RestartSec = &systemdRestartSec + } if cmd.Flags().Changed(startTimeoutFlagName) { systemdOptions.StartTimeout = &startTimeout } diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index bdcaa8ef1..363d042ae 100644 --- a/docs/source/markdown/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md @@ -51,6 +51,11 @@ Override the default stop timeout for the container with the given value in seco Set the systemd restart policy. The restart-policy must be one of: "no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", or "always". The default policy is *on-failure*. +#### **--restart-sec**=*time* + +Set the systemd service restartsec value. Configures the time to sleep before restarting a service (as configured with restart-policy). +Takes a value in seconds. + #### **--container-prefix**=*prefix* Set the systemd unit name prefix for containers. The default is *container*. diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go index 1411c680e..88fd69d45 100644 --- a/pkg/api/handlers/libpod/generate.go +++ b/pkg/api/handlers/libpod/generate.go @@ -22,6 +22,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) { NoHeader bool `schema:"noHeader"` TemplateUnitFile bool `schema:"templateUnitFile"` RestartPolicy *string `schema:"restartPolicy"` + RestartSec uint `schema:"restartSec"` StopTimeout uint `schema:"stopTimeout"` StartTimeout uint `schema:"startTimeout"` ContainerPrefix string `schema:"containerPrefix"` @@ -53,6 +54,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) { ContainerPrefix: query.ContainerPrefix, PodPrefix: query.PodPrefix, Separator: query.Separator, + RestartSec: &query.RestartSec, } report, err := containerEngine.GenerateSystemd(r.Context(), utils.GetName(r), options) diff --git a/pkg/api/server/register_generate.go b/pkg/api/server/register_generate.go index 0e36394cf..65340bf56 100644 --- a/pkg/api/server/register_generate.go +++ b/pkg/api/server/register_generate.go @@ -67,6 +67,11 @@ func (s *APIServer) registerGenerateHandlers(r *mux.Router) error { // type: string // default: "-" // description: Systemd unit name separator between name/id and prefix. + // - in: query + // name: restartSec + // type: integer + // default: 0 + // description: Configures the time to sleep before restarting a service. // produces: // - application/json // responses: diff --git a/pkg/bindings/generate/types.go b/pkg/bindings/generate/types.go index 092474e4a..ce560c547 100644 --- a/pkg/bindings/generate/types.go +++ b/pkg/bindings/generate/types.go @@ -20,6 +20,8 @@ type SystemdOptions struct { TemplateUnitFile *bool // RestartPolicy - systemd restart policy. RestartPolicy *string + // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service. + RestartSec *uint // StartTimeout - time when starting the container. StartTimeout *uint // StopTimeout - time when stopping the container. diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go index d60f1d70e..504d4da7f 100644 --- a/pkg/bindings/generate/types_systemd_options.go +++ b/pkg/bindings/generate/types_systemd_options.go @@ -92,6 +92,21 @@ func (o *SystemdOptions) GetRestartPolicy() string { return *o.RestartPolicy } +// WithRestartSec set field RestartSec to given value +func (o *SystemdOptions) WithRestartSec(value uint) *SystemdOptions { + o.RestartSec = &value + return o +} + +// GetRestartSec returns value of field RestartSec +func (o *SystemdOptions) GetRestartSec() uint { + if o.RestartSec == nil { + var z uint + return z + } + return *o.RestartSec +} + // WithStartTimeout set field StartTimeout to given value func (o *SystemdOptions) WithStartTimeout(value uint) *SystemdOptions { o.StartTimeout = &value diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go index 7e80e5d2d..e431a70af 100644 --- a/pkg/domain/entities/generate.go +++ b/pkg/domain/entities/generate.go @@ -10,6 +10,8 @@ type GenerateSystemdOptions struct { New bool // RestartPolicy - systemd restart policy. RestartPolicy *string + // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service. + RestartSec *uint // StartTimeout - time when starting the container. StartTimeout *uint // StopTimeout - time when stopping the container. diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go index d62a318d6..dd895b61f 100644 --- a/pkg/domain/infra/tunnel/generate.go +++ b/pkg/domain/infra/tunnel/generate.go @@ -19,6 +19,9 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, if opts.RestartPolicy != nil { options.WithRestartPolicy(*opts.RestartPolicy) } + if opts.RestartSec != nil { + options.WithRestartSec(*opts.RestartSec) + } return generate.Systemd(ic.ClientCtx, nameOrID, options) } diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go index 48252c737..f2d04dadc 100644 --- a/pkg/systemd/generate/pods.go +++ b/pkg/systemd/generate/pods.go @@ -30,6 +30,8 @@ type podInfo struct { StopTimeout uint // RestartPolicy of the systemd unit (e.g., no, on-failure, always). RestartPolicy string + // RestartSec of the systemd unit. Configures the time to sleep before restarting a service. + RestartSec uint // PIDFile of the service. Required for forking services. Must point to the // PID of the associated conmon process. PIDFile string @@ -89,6 +91,9 @@ Before={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{ [Service] Environment={{{{.EnvVariable}}}}=%n Restart={{{{.RestartPolicy}}}} +{{{{- if .RestartSec}}}} +RestartSec={{{{.RestartSec}}}} +{{{{- end}}}} TimeoutStopSec={{{{.TimeoutStopSec}}}} {{{{- if .ExecStartPre1}}}} ExecStartPre={{{{.ExecStartPre1}}}} @@ -242,6 +247,10 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) info.RestartPolicy = *options.RestartPolicy } + if options.RestartSec != nil { + info.RestartSec = *options.RestartSec + } + // Make sure the executable is set. if info.Executable == "" { executable, err := os.Executable() diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go index 612908991..0889507a5 100644 --- a/pkg/systemd/generate/pods_test.go +++ b/pkg/systemd/generate/pods_test.go @@ -67,6 +67,33 @@ WantedBy=default.target podGood := serviceInfo + headerInfo + podContent podGoodNoHeaderInfo := serviceInfo + podContent + podGoodRestartSec := `# pod-123abc.service +# autogenerated by Podman CI + +[Unit] +Description=Podman pod-123abc.service +Documentation=man:podman-generate-systemd(1) +Wants=network-online.target +After=network-online.target +RequiresMountsFor=/var/run/containers/storage +Requires=container-1.service container-2.service +Before=container-1.service container-2.service + +[Service] +Environment=PODMAN_SYSTEMD_UNIT=%n +Restart=on-failure +RestartSec=15 +TimeoutStopSec=102 +ExecStart=/usr/bin/podman start jadda-jadda-infra +ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra +ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra +PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid +Type=forking + +[Install] +WantedBy=default.target +` + podGoodNamedNew := `# pod-123abc.service # autogenerated by Podman CI @@ -205,6 +232,25 @@ WantedBy=default.target false, false, }, + {"pod restartSec", + podInfo{ + Executable: "/usr/bin/podman", + ServiceName: "pod-123abc", + InfraNameOrID: "jadda-jadda-infra", + PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid", + StopTimeout: 42, + PodmanVersion: "CI", + GraphRoot: "/var/lib/containers/storage", + RunRoot: "/var/run/containers/storage", + RequiredServices: []string{"container-1", "container-2"}, + CreateCommand: []string{"podman", "pod", "create", "--name", "foo", "bar=arg with space"}, + RestartSec: 15, + }, + podGoodRestartSec, + false, + false, + false, + }, {"pod noHeader", podInfo{ Executable: "/usr/bin/podman", diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index 1cffdc62e..fd9ae5037 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -282,6 +282,19 @@ var _ = Describe("Podman generate systemd", func() { Expect(session.OutputToString()).To(ContainSubstring(" pod create ")) }) + It("podman generate systemd --restart-sec 15 --name foo", func() { + n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"}) + n.WaitWithDefaultTimeout() + Expect(n).Should(Exit(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--restart-sec", "15", "--name", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // Grepping the output (in addition to unit tests) + Expect(session.OutputToString()).To(ContainSubstring("RestartSec=15")) + }) + It("podman generate systemd --new=false pod", func() { n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"}) n.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf