diff --git a/client/client.go b/client/client.go
index 040d80bbf80..44c12e14f49 100644
--- a/client/client.go
+++ b/client/client.go
@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"strconv"
+ "strings"
"sync"
"time"
@@ -494,9 +495,28 @@ func (c *Client) fingerprintPeriodic(name string, f fingerprint.Fingerprint, d t
// setupDrivers is used to find the available drivers
func (c *Client) setupDrivers() error {
+ // Build the whitelist of drivers.
+ userWhitelist := strings.TrimSpace(c.config.ReadDefault("driver.whitelist", ""))
+ whitelist := make(map[string]struct{})
+ if userWhitelist != "" {
+ for _, driver := range strings.Split(userWhitelist, ",") {
+ trimmed := strings.TrimSpace(driver)
+ whitelist[trimmed] = struct{}{}
+ }
+ }
+ whitelistEnabled := len(whitelist) > 0
+
var avail []string
+ var skipped []string
driverCtx := driver.NewDriverContext("", c.config, c.config.Node, c.logger)
for name := range driver.BuiltinDrivers {
+ // Skip fingerprinting drivers that are not in the whitelist if it is
+ // enabled.
+ if _, ok := whitelist[name]; whitelistEnabled && !ok {
+ skipped = append(skipped, name)
+ continue
+ }
+
d, err := driver.NewDriver(name, driverCtx)
if err != nil {
return err
@@ -509,7 +529,13 @@ func (c *Client) setupDrivers() error {
avail = append(avail, name)
}
}
+
c.logger.Printf("[DEBUG] client: available drivers %v", avail)
+
+ if len(skipped) != 0 {
+ c.logger.Printf("[DEBUG] client: drivers skipped due to whitelist: %v", skipped)
+ }
+
return nil
}
diff --git a/client/client_test.go b/client/client_test.go
index 935c63deaa8..2af44d8da01 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -151,6 +151,33 @@ func TestClient_Drivers(t *testing.T) {
}
}
+func TestClient_Drivers_InWhitelist(t *testing.T) {
+ ctestutil.ExecCompatible(t)
+ c := testClient(t, func(c *config.Config) {
+ // Weird spacing to test trimming
+ c.Options["driver.whitelist"] = " exec , foo "
+ })
+ defer c.Shutdown()
+
+ node := c.Node()
+ if node.Attributes["driver.exec"] == "" {
+ t.Fatalf("missing exec driver")
+ }
+}
+
+func TestClient_Drivers_OutOfWhitelist(t *testing.T) {
+ ctestutil.ExecCompatible(t)
+ c := testClient(t, func(c *config.Config) {
+ c.Options["driver.whitelist"] = "foo,bar,baz"
+ })
+ defer c.Shutdown()
+
+ node := c.Node()
+ if node.Attributes["driver.exec"] != "" {
+ t.Fatalf("found exec driver")
+ }
+}
+
func TestClient_Register(t *testing.T) {
s1, _ := testServer(t, nil)
defer s1.Shutdown()
diff --git a/demo/vagrant/client1.hcl b/demo/vagrant/client1.hcl
index 53bc4e94ae2..1c001daa746 100644
--- a/demo/vagrant/client1.hcl
+++ b/demo/vagrant/client1.hcl
@@ -12,6 +12,9 @@ client {
# this should be like "nomad.service.consul:4647" and a system
# like Consul used for service discovery.
servers = ["127.0.0.1:4647"]
+ options {
+ "driver.whitelist" = " exec, qemu "
+ }
}
# Modify our port to avoid a collision with server1
diff --git a/website/source/docs/agent/config.html.md b/website/source/docs/agent/config.html.md
index d548b7e671f..201bfc2849a 100644
--- a/website/source/docs/agent/config.html.md
+++ b/website/source/docs/agent/config.html.md
@@ -212,13 +212,30 @@ configured on server nodes.
* `meta`: This is a key/value mapping of metadata pairs. This
is a free-form map and can contain any string values.
* `options`: This is a key/value mapping of internal
- configuration for clients, such as for driver configuration.
+ configuration for clients, such as for driver configuration. Please see
+ [here](#options_map) for a description of available options.
* `network_interface`: This is a string to force
network fingerprinting to use a specific network interface
* `network_speed`: This is an int that sets the
default link speed of network interfaces, in megabytes, if their speed can
not be determined dynamically.
+### Client Options Map
+
+The following is not an exhaustive list of options that can be passed to the
+Client, but rather the set of options that configure the Client and not the
+drivers. To find the options supported by an individual driver, see the drivers
+documentation [here](/docs/drivers/index.html)
+
+* `consul.address`: The address to the local Consul agent given in the format of
+ `host:port`. The default is the same as the Consul default address,
+ `127.0.0.1:8500`.
+
+* `driver.whitelist`: A comma seperated list of whitelisted drivers (e.g.
+ "docker,qemu"). If specified, drivers not in the whitelist will be disabled.
+ If the whitelist is empty, all drivers are fingerprinted and enabled where
+ applicable.
+
## Atlas Options
**NOTE**: Nomad integration with Atlas is awaiting release of Atlas features
diff --git a/website/source/docs/jobspec/environment.html.md b/website/source/docs/jobspec/environment.html.md
index 9c698befed3..0b92b1444a5 100644
--- a/website/source/docs/jobspec/environment.html.md
+++ b/website/source/docs/jobspec/environment.html.md
@@ -38,7 +38,9 @@ cluster gets more or less busy.
### Networking
-Nomad assigns IPs and ports to your jobs and exposes them via environment variables. See the [Networking](/docs/jobspec/networking.html) page for more details.
+Nomad assigns IPs and ports to your jobs and exposes them via environment
+variables. See the [Networking](/docs/jobspec/networking.html) page for more
+details.
### Task Directories