-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow controlling the stop signal for drivers #3591
Changes from 5 commits
079e6b5
9e49836
8356c61
a693666
359613e
0c17fd5
20d1a3b
b1eda32
927c0a4
27b666e
f09e3ec
7d8dda8
73a4a46
ae10b63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -201,6 +201,7 @@ type DockerDriverConfig struct { | |
MacAddress string `mapstructure:"mac_address"` // Pin mac address to container | ||
SecurityOpt []string `mapstructure:"security_opt"` // Flags to pass directly to security-opt | ||
Devices []DockerDevice `mapstructure:"devices"` // To allow mounting USB or other serial control devices | ||
StopSignal string `mapstructure:"stop_signal"` // allow passing through a specific stop signal | ||
} | ||
|
||
func sliceMergeUlimit(ulimitsRaw map[string]string) ([]docker.ULimit, error) { | ||
|
@@ -712,7 +713,6 @@ func (d *DockerDriver) Prestart(ctx *ExecContext, task *structs.Task) (*Prestart | |
} | ||
|
||
func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse, error) { | ||
|
||
pluginLogFile := filepath.Join(ctx.TaskDir.Dir, "executor.out") | ||
executorConfig := &dstructs.ExecutorConfig{ | ||
LogFile: pluginLogFile, | ||
|
@@ -1055,6 +1055,11 @@ func (d *DockerDriver) createContainerConfig(ctx *ExecContext, task *structs.Tas | |
StopTimeout: int(task.KillTimeout.Seconds()), | ||
} | ||
|
||
// Set the stop signal for the docker container. | ||
if task.KillSignal != "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this become:
|
||
config.StopSignal = task.KillSignal | ||
} | ||
|
||
if driverConfig.WorkDir != "" { | ||
config.WorkingDir = driverConfig.WorkDir | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,9 +129,15 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse | |
return nil, fmt.Errorf("failed to set executor context: %v", err) | ||
} | ||
|
||
taskKillSignal, err := getTaskKillSignal(task.KillSignal) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
execCmd := &executor.ExecCommand{ | ||
Cmd: command, | ||
Args: driverConfig.Args, | ||
TaskKillSignal: taskKillSignal, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Java driver too There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See 27b666e |
||
FSIsolation: true, | ||
ResourceLimits: true, | ||
User: getExecutorUser(task), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import ( | |
"strings" | ||
"time" | ||
|
||
"github.com/hashicorp/consul-template/signals" | ||
"github.com/hashicorp/go-multierror" | ||
"github.com/hashicorp/go-plugin" | ||
"github.com/hashicorp/nomad/client/allocdir" | ||
|
@@ -204,3 +205,17 @@ func SetEnvvars(envBuilder *env.Builder, fsi cstructs.FSIsolation, taskDir *allo | |
envBuilder.SetHostEnvvars(filter) | ||
} | ||
} | ||
|
||
// getTaskKillSignal looks up the signal specified for the task if it has been | ||
// specified. If it is not supported on the platform, returns an error. | ||
func getTaskKillSignal(signal string) (os.Signal, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this same validation be used for signals to docker/other containers? |
||
if signal == "" { | ||
return nil, nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not have it default to SIGINT There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was debating whether it should be here or in executor.go- having the default here would be good; changing. |
||
} | ||
|
||
taskKillSignal := signals.SignalLookup[signal] | ||
if taskKillSignal == nil { | ||
return nil, fmt.Errorf("Signal %s is not supported", signal) | ||
} | ||
return taskKillSignal, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -666,6 +666,8 @@ func ApiTgToStructsTG(taskGroup *api.TaskGroup, tg *structs.TaskGroup) { | |
} | ||
} | ||
|
||
// ApiTaskToStructsTask is a copy and type conversion between the API | ||
// representation of a task from a struct representation of a task. | ||
func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) { | ||
structsTask.Name = apiTask.Name | ||
structsTask.Driver = apiTask.Driver | ||
|
@@ -676,6 +678,7 @@ func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) { | |
structsTask.Meta = apiTask.Meta | ||
structsTask.KillTimeout = *apiTask.KillTimeout | ||
structsTask.ShutdownDelay = apiTask.ShutdownDelay | ||
structsTask.KillSignal = apiTask.KillSignal | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add to test |
||
|
||
if l := len(apiTask.Constraints); l != 0 { | ||
structsTask.Constraints = make([]*structs.Constraint, l) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -591,6 +591,7 @@ func parseTasks(jobName string, taskGroupName string, result *[]*api.Task, list | |
"template", | ||
"user", | ||
"vault", | ||
"kill_signal", | ||
} | ||
if err := helper.CheckHCLKeys(listVal, valid); err != nil { | ||
return multierror.Prefix(err, fmt.Sprintf("'%s' ->", n)) | ||
|
@@ -623,6 +624,13 @@ func parseTasks(jobName string, taskGroupName string, result *[]*api.Task, list | |
WeaklyTypedInput: true, | ||
Result: &t, | ||
}) | ||
|
||
// this needs to be manually assigned | ||
killsig := m["kill_signal"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this the case? The mapstructure decode should get this? |
||
if killsig != nil { | ||
t.KillSignal = killsig.(string) | ||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
job "example" { | ||
task "webservice" { | ||
kill_signal = "SIGINT" | ||
driver = "docker" | ||
config | ||
{ | ||
image = "hashicorp/image" | ||
} | ||
} | ||
|
||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1978,6 +1978,11 @@ func (j *Job) RequiredSignals() map[string]map[string][]string { | |
taskSignals[task.Vault.ChangeSignal] = struct{}{} | ||
} | ||
|
||
// If a user has specified a KillSignal, add it to required signals | ||
if task.KillSignal != "" { | ||
taskSignals[task.KillSignal] = struct{}{} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add to test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
// Check if any template change mode uses signals | ||
for _, t := range task.Templates { | ||
if t.ChangeMode != TemplateChangeModeSignal { | ||
|
@@ -3221,6 +3226,10 @@ type Task struct { | |
// ShutdownDelay is the duration of the delay between deregistering a | ||
// task from Consul and sending it a signal to shutdown. See #2441 | ||
ShutdownDelay time.Duration | ||
|
||
// The kill signal to use for the task. This is an optional specification, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
// and if not set, the driver will default to SIGINT | ||
KillSignal string | ||
} | ||
|
||
func (t *Task) Copy() *Task { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be removed since it is specified at the task level now