From 8664311cad8648c8d1db70fa3e56e1cf51ee1d3b Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Tue, 18 Feb 2025 23:42:31 +0000 Subject: [PATCH] feat: add signal option to containerRestart Signed-off-by: Arjun Raja Yogidas --- cmd/nerdctl/container/container_restart.go | 12 ++++++++ .../container/container_restart_linux_test.go | 29 +++++++++++++++++++ docs/command-reference.md | 2 ++ pkg/api/types/container_types.go | 2 ++ pkg/cmd/container/restart.go | 2 +- 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container/container_restart.go b/cmd/nerdctl/container/container_restart.go index b1875a77853..60c0f100e41 100644 --- a/cmd/nerdctl/container/container_restart.go +++ b/cmd/nerdctl/container/container_restart.go @@ -38,6 +38,7 @@ func NewRestartCommand() *cobra.Command { SilenceErrors: true, } restartCommand.Flags().UintP("time", "t", 10, "Seconds to wait for stop before killing it") + restartCommand.Flags().StringP("signal", "s", "", "Signal to send to stop the container, before killing it") return restartCommand } @@ -58,10 +59,21 @@ func processContainerRestartOptions(cmd *cobra.Command) (types.ContainerRestartO timeout = &t } + var signal string + if cmd.Flags().Changed("signal") { + // Signal to send to stop the container, before killing it + sig, err := cmd.Flags().GetString("signal") + if err != nil { + return types.ContainerRestartOptions{}, err + } + signal = sig + } + return types.ContainerRestartOptions{ Stdout: cmd.OutOrStdout(), GOption: globalOptions, Timeout: timeout, + Signal: signal, }, err } diff --git a/cmd/nerdctl/container/container_restart_linux_test.go b/cmd/nerdctl/container/container_restart_linux_test.go index 3565f9f11ad..12a011fa751 100644 --- a/cmd/nerdctl/container/container_restart_linux_test.go +++ b/cmd/nerdctl/container/container_restart_linux_test.go @@ -121,3 +121,32 @@ func TestRestartWithTime(t *testing.T) { // ensure that stop took at least 5 seconds assert.Assert(t, timePostRestart.Sub(timePreRestart) >= time.Second*5) } + +func TestRestartWithSignal(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + + base.Cmd("run", "-d", "--name", tID, testutil.AlpineImage, "sh", "-c", ` + trap 'echo "Received SIGUSR1"; exit 0' SIGUSR1 + echo "Starting" + while true; do + sleep 1 + done + `).AssertOK() + defer base.Cmd("rm", "-f", tID).Run() + + base.EnsureContainerStarted(tID) + + inspect := base.InspectContainer(tID) + initialPid := inspect.State.Pid + + base.Cmd("restart", "--signal", "SIGUSR1", tID).AssertOK() + base.EnsureContainerStarted(tID) + + newInspect := base.InspectContainer(tID) + newPid := newInspect.State.Pid + + assert.Assert(t, initialPid != newPid, "Container PID should have changed after restart") + +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 73e0c451d0d..898bd2a4069 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -573,6 +573,7 @@ Flags: - :whale: `-t, --time=SECONDS`: Seconds to wait for stop before killing it (default "10") - Tips: If the init process in container is exited after receiving SIGTERM or exited before the time you specified, the container will be exited immediately +- :whale: `-s, --signal=SIGNAL`: Signal to send to the container (e.g. SIGINT). ### :whale: nerdctl start @@ -597,6 +598,7 @@ Flags: - :whale: `-t, --time=SECONDS`: Seconds to wait for stop before killing it (default "10") - Tips: If the init process in container is exited after receiving SIGTERM or exited before the time you specified, the container will be exited immediately +- :whale: `-s, --signal=SIGNAL`: Signal to send to the container (e.g. SIGINT). ### :whale: nerdctl update diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index d38a0e5da11..3d0ae773ce1 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -286,6 +286,8 @@ type ContainerRestartOptions struct { GOption GlobalCommandOptions // Time to wait after sending a SIGTERM and before sending a SIGKILL. Timeout *time.Duration + // Signal to send to stop the container, before sending SIGKILL + Signal string } // ContainerPauseOptions specifies options for `nerdctl (container) pause`. diff --git a/pkg/cmd/container/restart.go b/pkg/cmd/container/restart.go index 1be264e056f..6b60b082236 100644 --- a/pkg/cmd/container/restart.go +++ b/pkg/cmd/container/restart.go @@ -35,7 +35,7 @@ func Restart(ctx context.Context, client *containerd.Client, containers []string if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := containerutil.Stop(ctx, found.Container, options.Timeout, "SIGTERM"); err != nil { + if err := containerutil.Stop(ctx, found.Container, options.Timeout, options.Signal); err != nil { return err } if err := containerutil.Start(ctx, found.Container, false, client, ""); err != nil {