Merge pull request #30754 from yongtang/25696-stop-signal
Add `--stop-signal` for `service create` and `service update`
This commit is contained in:
commit
bb9f19503c
10 changed files with 106 additions and 39 deletions
|
@ -1921,6 +1921,9 @@ definitions:
|
|||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/Mount"
|
||||
StopSignal:
|
||||
description: "Signal to stop the container."
|
||||
type: "string"
|
||||
StopGracePeriod:
|
||||
description: "Amount of time to wait for the container to terminate before forcefully killing it."
|
||||
type: "integer"
|
||||
|
|
|
@ -32,6 +32,7 @@ type ContainerSpec struct {
|
|||
Dir string `json:",omitempty"`
|
||||
User string `json:",omitempty"`
|
||||
Groups []string `json:",omitempty"`
|
||||
StopSignal string `json:",omitempty"`
|
||||
TTY bool `json:",omitempty"`
|
||||
OpenStdin bool `json:",omitempty"`
|
||||
ReadOnly bool `json:",omitempty"`
|
||||
|
|
|
@ -269,6 +269,7 @@ type serviceOptions struct {
|
|||
workdir string
|
||||
user string
|
||||
groups opts.ListOpts
|
||||
stopSignal string
|
||||
tty bool
|
||||
readOnly bool
|
||||
mounts opts.MountOpt
|
||||
|
@ -372,17 +373,18 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
|
|||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
Image: opts.image,
|
||||
Args: opts.args,
|
||||
Env: currentEnv,
|
||||
Hostname: opts.hostname,
|
||||
Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
|
||||
Dir: opts.workdir,
|
||||
User: opts.user,
|
||||
Groups: opts.groups.GetAll(),
|
||||
TTY: opts.tty,
|
||||
ReadOnly: opts.readOnly,
|
||||
Mounts: opts.mounts.Value(),
|
||||
Image: opts.image,
|
||||
Args: opts.args,
|
||||
Env: currentEnv,
|
||||
Hostname: opts.hostname,
|
||||
Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
|
||||
Dir: opts.workdir,
|
||||
User: opts.user,
|
||||
Groups: opts.groups.GetAll(),
|
||||
StopSignal: opts.stopSignal,
|
||||
TTY: opts.tty,
|
||||
ReadOnly: opts.readOnly,
|
||||
Mounts: opts.mounts.Value(),
|
||||
DNSConfig: &swarm.DNSConfig{
|
||||
Nameservers: opts.dns.GetAll(),
|
||||
Search: opts.dnsSearch.GetAll(),
|
||||
|
@ -470,6 +472,9 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
|
|||
|
||||
flags.BoolVar(&opts.readOnly, flagReadOnly, false, "Mount the container's root filesystem as read only")
|
||||
flags.SetAnnotation(flagReadOnly, "version", []string{"1.27"})
|
||||
|
||||
flags.StringVar(&opts.stopSignal, flagStopSignal, "", "Signal to stop the container")
|
||||
flags.SetAnnotation(flagStopSignal, "version", []string{"1.27"})
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -523,6 +528,7 @@ const (
|
|||
flagRestartMaxAttempts = "restart-max-attempts"
|
||||
flagRestartWindow = "restart-window"
|
||||
flagStopGracePeriod = "stop-grace-period"
|
||||
flagStopSignal = "stop-signal"
|
||||
flagTTY = "tty"
|
||||
flagUpdateDelay = "update-delay"
|
||||
flagUpdateFailureAction = "update-failure-action"
|
||||
|
|
|
@ -349,6 +349,8 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
|
|||
cspec.ReadOnly = readOnly
|
||||
}
|
||||
|
||||
updateString(flagStopSignal, &cspec.StopSignal)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -441,3 +441,25 @@ func TestUpdateReadOnly(t *testing.T) {
|
|||
updateService(flags, spec)
|
||||
assert.Equal(t, cspec.ReadOnly, false)
|
||||
}
|
||||
|
||||
func TestUpdateStopSignal(t *testing.T) {
|
||||
spec := &swarm.ServiceSpec{}
|
||||
cspec := &spec.TaskTemplate.ContainerSpec
|
||||
|
||||
// Update with --stop-signal=SIGUSR1
|
||||
flags := newUpdateCommand(nil).Flags()
|
||||
flags.Set("stop-signal", "SIGUSR1")
|
||||
updateService(flags, spec)
|
||||
assert.Equal(t, cspec.StopSignal, "SIGUSR1")
|
||||
|
||||
// Update without --stop-signal, no change
|
||||
flags = newUpdateCommand(nil).Flags()
|
||||
updateService(flags, spec)
|
||||
assert.Equal(t, cspec.StopSignal, "SIGUSR1")
|
||||
|
||||
// Update with --stop-signal=SIGWINCH
|
||||
flags = newUpdateCommand(nil).Flags()
|
||||
flags.Set("stop-signal", "SIGWINCH")
|
||||
updateService(flags, spec)
|
||||
assert.Equal(t, cspec.StopSignal, "SIGWINCH")
|
||||
}
|
||||
|
|
|
@ -14,20 +14,21 @@ import (
|
|||
|
||||
func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
|
||||
containerSpec := types.ContainerSpec{
|
||||
Image: c.Image,
|
||||
Labels: c.Labels,
|
||||
Command: c.Command,
|
||||
Args: c.Args,
|
||||
Hostname: c.Hostname,
|
||||
Env: c.Env,
|
||||
Dir: c.Dir,
|
||||
User: c.User,
|
||||
Groups: c.Groups,
|
||||
TTY: c.TTY,
|
||||
OpenStdin: c.OpenStdin,
|
||||
ReadOnly: c.ReadOnly,
|
||||
Hosts: c.Hosts,
|
||||
Secrets: secretReferencesFromGRPC(c.Secrets),
|
||||
Image: c.Image,
|
||||
Labels: c.Labels,
|
||||
Command: c.Command,
|
||||
Args: c.Args,
|
||||
Hostname: c.Hostname,
|
||||
Env: c.Env,
|
||||
Dir: c.Dir,
|
||||
User: c.User,
|
||||
Groups: c.Groups,
|
||||
StopSignal: c.StopSignal,
|
||||
TTY: c.TTY,
|
||||
OpenStdin: c.OpenStdin,
|
||||
ReadOnly: c.ReadOnly,
|
||||
Hosts: c.Hosts,
|
||||
Secrets: secretReferencesFromGRPC(c.Secrets),
|
||||
}
|
||||
|
||||
if c.DNSConfig != nil {
|
||||
|
@ -136,20 +137,21 @@ func secretReferencesFromGRPC(sr []*swarmapi.SecretReference) []*types.SecretRef
|
|||
|
||||
func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
|
||||
containerSpec := &swarmapi.ContainerSpec{
|
||||
Image: c.Image,
|
||||
Labels: c.Labels,
|
||||
Command: c.Command,
|
||||
Args: c.Args,
|
||||
Hostname: c.Hostname,
|
||||
Env: c.Env,
|
||||
Dir: c.Dir,
|
||||
User: c.User,
|
||||
Groups: c.Groups,
|
||||
TTY: c.TTY,
|
||||
OpenStdin: c.OpenStdin,
|
||||
ReadOnly: c.ReadOnly,
|
||||
Hosts: c.Hosts,
|
||||
Secrets: secretReferencesToGRPC(c.Secrets),
|
||||
Image: c.Image,
|
||||
Labels: c.Labels,
|
||||
Command: c.Command,
|
||||
Args: c.Args,
|
||||
Hostname: c.Hostname,
|
||||
Env: c.Env,
|
||||
Dir: c.Dir,
|
||||
User: c.User,
|
||||
Groups: c.Groups,
|
||||
StopSignal: c.StopSignal,
|
||||
TTY: c.TTY,
|
||||
OpenStdin: c.OpenStdin,
|
||||
ReadOnly: c.ReadOnly,
|
||||
Hosts: c.Hosts,
|
||||
Secrets: secretReferencesToGRPC(c.Secrets),
|
||||
}
|
||||
|
||||
if c.DNSConfig != nil {
|
||||
|
|
|
@ -185,6 +185,7 @@ func (c *containerConfig) exposedPorts() map[nat.Port]struct{} {
|
|||
func (c *containerConfig) config() *enginecontainer.Config {
|
||||
config := &enginecontainer.Config{
|
||||
Labels: c.labels(),
|
||||
StopSignal: c.spec().StopSignal,
|
||||
Tty: c.spec().TTY,
|
||||
OpenStdin: c.spec().OpenStdin,
|
||||
User: c.spec().User,
|
||||
|
|
|
@ -58,6 +58,7 @@ Options:
|
|||
--restart-window duration Window used to evaluate the restart policy (ns|us|ms|s|m|h)
|
||||
--secret secret Specify secrets to expose to the service
|
||||
--stop-grace-period duration Time to wait before force killing a container (ns|us|ms|s|m|h)
|
||||
--stop-signal string Signal to stop the container
|
||||
-t, --tty Allocate a pseudo-TTY
|
||||
--update-delay duration Delay between updates (ns|us|ms|s|m|h) (default 0s)
|
||||
--update-failure-action string Action on update failure ("pause"|"continue") (default "pause")
|
||||
|
|
|
@ -70,6 +70,7 @@ Options:
|
|||
--secret-add secret Add or update a secret on a service
|
||||
--secret-rm list Remove a secret (default [])
|
||||
--stop-grace-period duration Time to wait before force killing a container (ns|us|ms|s|m|h)
|
||||
--stop-signal string Signal to stop the container
|
||||
-t, --tty Allocate a pseudo-TTY
|
||||
--update-delay duration Delay between updates (ns|us|ms|s|m|h) (default 0s)
|
||||
--update-failure-action string Action on update failure ("pause"|"continue") (default "pause")
|
||||
|
|
|
@ -1764,3 +1764,31 @@ func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *check.C) {
|
|||
c.Assert(err, checker.NotNil, check.Commentf(out))
|
||||
c.Assert(out, checker.Contains, "network foo is ambiguous (2 matches found based on name)")
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestSwarmStopSignal(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, UserNamespaceROMount)
|
||||
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
out, err := d.Cmd("service", "create", "--name", "top", "--stop-signal=SIGHUP", "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
// make sure task has been deployed.
|
||||
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
|
||||
|
||||
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.StopSignal }}", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "SIGHUP")
|
||||
|
||||
containers := d.ActiveContainers()
|
||||
out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.StopSignal}}", containers[0])
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "SIGHUP")
|
||||
|
||||
out, err = d.Cmd("service", "update", "--stop-signal=SIGUSR1", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.StopSignal }}", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "SIGUSR1")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue