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