diff --git a/client/driver/docker.go b/client/driver/docker.go index ffc05fe7e..b4cc01d92 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -266,6 +266,12 @@ func (d *DockerDriver) Validate(config map[string]interface{}) error { return nil } +func (d *DockerDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: true, + } +} + // dockerClients creates two *docker.Client, one for long running operations and // the other for shorter operations. In test / dev mode we can use ENV vars to // connect to the docker daemon. In production mode we will read docker.endpoint diff --git a/client/driver/driver.go b/client/driver/driver.go index 8774f208e..b0f2eb696 100644 --- a/client/driver/driver.go +++ b/client/driver/driver.go @@ -59,6 +59,15 @@ type Driver interface { // Drivers must validate their configuration Validate(map[string]interface{}) error + + // Abilities returns the abilities of the driver + Abilities() DriverAbilities +} + +// DriverAbilities marks the abilities the driver has. +type DriverAbilities struct { + // SendSignals marks the driver as being able to send signals + SendSignals bool } // DriverContext is a means to inject dependencies such as loggers, configs, and diff --git a/client/driver/exec.go b/client/driver/exec.go index ddc8325cd..b5c1f6b4b 100644 --- a/client/driver/exec.go +++ b/client/driver/exec.go @@ -82,6 +82,12 @@ func (d *ExecDriver) Validate(config map[string]interface{}) error { return nil } +func (d *ExecDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: true, + } +} + func (d *ExecDriver) Periodic() (bool, time.Duration) { return true, 15 * time.Second } diff --git a/client/driver/java.go b/client/driver/java.go index ba0fd239a..6d457c628 100644 --- a/client/driver/java.go +++ b/client/driver/java.go @@ -94,6 +94,12 @@ func (d *JavaDriver) Validate(config map[string]interface{}) error { return nil } +func (d *JavaDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: true, + } +} + func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { // Get the current status so that we can log any debug messages only if the // state changes diff --git a/client/driver/mock_driver.go b/client/driver/mock_driver.go index e1ef41998..ad6e2486e 100644 --- a/client/driver/mock_driver.go +++ b/client/driver/mock_driver.go @@ -62,6 +62,12 @@ func NewMockDriver(ctx *DriverContext) Driver { return &MockDriver{DriverContext: *ctx} } +func (d *MockDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: false, + } +} + // Start starts the mock driver func (m *MockDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) { var driverConfig MockDriverConfig diff --git a/client/driver/qemu.go b/client/driver/qemu.go index 9455e3ac2..e37f405f8 100644 --- a/client/driver/qemu.go +++ b/client/driver/qemu.go @@ -97,6 +97,12 @@ func (d *QemuDriver) Validate(config map[string]interface{}) error { return nil } +func (d *QemuDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: false, + } +} + func (d *QemuDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { // Get the current status so that we can log any debug messages only if the // state changes diff --git a/client/driver/raw_exec.go b/client/driver/raw_exec.go index b13208e90..2834d8e35 100644 --- a/client/driver/raw_exec.go +++ b/client/driver/raw_exec.go @@ -81,6 +81,12 @@ func (d *RawExecDriver) Validate(config map[string]interface{}) error { return nil } +func (d *RawExecDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: true, + } +} + func (d *RawExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { // Get the current status so that we can log any debug messages only if the // state changes diff --git a/client/driver/rkt.go b/client/driver/rkt.go index ac422ec6e..c4823e8b5 100644 --- a/client/driver/rkt.go +++ b/client/driver/rkt.go @@ -128,6 +128,12 @@ func (d *RktDriver) Validate(config map[string]interface{}) error { return nil } +func (d *RktDriver) Abilities() DriverAbilities { + return DriverAbilities{ + SendSignals: false, + } +} + func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { // Get the current status so that we can log any debug messages only if the // state changes diff --git a/client/fingerprint/fingerprint.go b/client/fingerprint/fingerprint.go index 98520b306..51ed50145 100644 --- a/client/fingerprint/fingerprint.go +++ b/client/fingerprint/fingerprint.go @@ -25,6 +25,7 @@ func init() { builtinFingerprintMap["memory"] = NewMemoryFingerprint builtinFingerprintMap["network"] = NewNetworkFingerprint builtinFingerprintMap["nomad"] = NewNomadFingerprint + builtinFingerprintMap["signal"] = NewSignalFingerprint builtinFingerprintMap["storage"] = NewStorageFingerprint builtinFingerprintMap["vault"] = NewVaultFingerprint diff --git a/client/fingerprint/signal.go b/client/fingerprint/signal.go new file mode 100644 index 000000000..d20cec07b --- /dev/null +++ b/client/fingerprint/signal.go @@ -0,0 +1,33 @@ +package fingerprint + +import ( + "log" + "strings" + + "github.com/hashicorp/consul-template/signals" + "github.com/hashicorp/nomad/client/config" + "github.com/hashicorp/nomad/nomad/structs" +) + +// SignalFingerprint is used to fingerprint the available signals +type SignalFingerprint struct { + StaticFingerprinter + logger *log.Logger +} + +// NewSignalFingerprint is used to create a Signal fingerprint +func NewSignalFingerprint(logger *log.Logger) Fingerprint { + f := &SignalFingerprint{logger: logger} + return f +} + +func (f *SignalFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { + // Build the list of available signals + sigs := make([]string, 0, len(signals.SignalLookup)) + for signal := range signals.SignalLookup { + sigs = append(sigs, signal) + } + + node.Attributes["os.signals"] = strings.Join(sigs, ",") + return true, nil +} diff --git a/client/fingerprint/signal_test.go b/client/fingerprint/signal_test.go new file mode 100644 index 000000000..2157cf0c5 --- /dev/null +++ b/client/fingerprint/signal_test.go @@ -0,0 +1,17 @@ +package fingerprint + +import ( + "testing" + + "github.com/hashicorp/nomad/nomad/structs" +) + +func TestSignalFingerprint(t *testing.T) { + fp := NewSignalFingerprint(testLogger()) + node := &structs.Node{ + Attributes: make(map[string]string), + } + + assertFingerprintOK(t, fp, node) + assertNodeAttributeContains(t, node, "os.signals") +}