From 135041be41dc4275da4d8ffeb17c3165efe079a2 Mon Sep 17 00:00:00 2001 From: Ondra Machacek Date: Thu, 2 Dec 2021 13:44:35 +0100 Subject: [PATCH] Add restart-sec option to systemd generate Signed-off-by: Ondra Machacek --- cmd/podman/generate/systemd.go | 9 ++++ .../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 + .../generate/types_systemd_options.go | 15 ++++++ pkg/domain/entities/generate.go | 2 + pkg/domain/infra/tunnel/generate.go | 4 ++ pkg/systemd/generate/pods.go | 9 ++++ pkg/systemd/generate/pods_test.go | 46 +++++++++++++++++++ test/e2e/generate_systemd_test.go | 13 ++++++ 11 files changed, 112 insertions(+) diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go index 2ab33c26b7..d7680a94c4 100644 --- a/cmd/podman/generate/systemd.go +++ b/cmd/podman/generate/systemd.go @@ -21,6 +21,7 @@ import ( const ( restartPolicyFlagName = "restart-policy" timeFlagName = "time" + restartSecFlagName = "restart-sec" ) var ( @@ -28,6 +29,7 @@ var ( format string systemdTimeout uint systemdRestart string + systemdRestartSec uint systemdOptions = entities.GenerateSystemdOptions{} systemdDescription = `Generate systemd units for a pod or container. The generated units can later be controlled via systemctl(1).` @@ -74,6 +76,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)) @@ -93,6 +98,10 @@ func systemd(cmd *cobra.Command, args []string) error { logrus.Warnln("The generated units should be placed on your remote system") } + if cmd.Flags().Changed(restartSecFlagName) { + systemdOptions.RestartSec = &systemdRestartSec + } + reports, err := registry.ContainerEngine().GenerateSystemd(registry.GetContext(), args[0], systemdOptions) if err != nil { return err diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index 8393aec119..27143bc375 100644 --- a/docs/source/markdown/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md @@ -47,6 +47,11 @@ Override the default stop timeout for the container with the given value. 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 117c5e2aa5..f32c68b70c 100644 --- a/pkg/api/handlers/libpod/generate.go +++ b/pkg/api/handlers/libpod/generate.go @@ -21,6 +21,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) { New bool `schema:"new"` NoHeader bool `schema:"noHeader"` RestartPolicy *string `schema:"restartPolicy"` + RestartSec uint `schema:"restartSec"` StopTimeout uint `schema:"stopTimeout"` ContainerPrefix string `schema:"containerPrefix"` PodPrefix string `schema:"podPrefix"` @@ -48,6 +49,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 e10c7029cc..427fac9f96 100644 --- a/pkg/api/server/register_generate.go +++ b/pkg/api/server/register_generate.go @@ -62,6 +62,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 3c9ea87d41..f9306df7c7 100644 --- a/pkg/bindings/generate/types.go +++ b/pkg/bindings/generate/types.go @@ -18,6 +18,8 @@ type SystemdOptions struct { NoHeader *bool // RestartPolicy - systemd restart policy. RestartPolicy *string + // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service. + RestartSec *uint // StopTimeout - time when stopping the container. StopTimeout *uint // ContainerPrefix - systemd unit name prefix for containers diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go index 7a778a52b6..4477b13532 100644 --- a/pkg/bindings/generate/types_systemd_options.go +++ b/pkg/bindings/generate/types_systemd_options.go @@ -77,6 +77,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 +} + // WithStopTimeout set field StopTimeout to given value func (o *SystemdOptions) WithStopTimeout(value uint) *SystemdOptions { o.StopTimeout = &value diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go index 7809c52414..13ee2ce58d 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 // StopTimeout - time when stopping the container. StopTimeout *uint // ContainerPrefix - systemd unit name prefix for containers diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go index 9f69abb1a0..efd3ed7eaa 100644 --- a/pkg/domain/infra/tunnel/generate.go +++ b/pkg/domain/infra/tunnel/generate.go @@ -16,6 +16,10 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, if to := opts.StopTimeout; to != nil { options.WithStopTimeout(*opts.StopTimeout) } + 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 e755b8eea9..242d1fc2dd 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 @@ -87,6 +89,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}}}} @@ -237,6 +242,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 c565a30ed9..b2d2153e5a 100644 --- a/pkg/systemd/generate/pods_test.go +++ b/pkg/systemd/generate/pods_test.go @@ -67,6 +67,33 @@ WantedBy=multi-user.target 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=multi-user.target default.target +` + podGoodNamedNew := `# pod-123abc.service # autogenerated by Podman CI @@ -205,6 +232,25 @@ WantedBy=multi-user.target 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 121f09a111..522178cba7 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -273,6 +273,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()