Merge pull request #4631 from hashicorp/f-plugin-config
Parse plugin configs
This commit is contained in:
commit
4f89cabd34
|
@ -87,6 +87,9 @@ func NewAgent(config *Config, logOutput io.Writer, inmem *metrics.InmemSink) (*A
|
|||
if err := a.setupConsul(config.Consul); err != nil {
|
||||
return nil, fmt.Errorf("Failed to initialize Consul client: %v", err)
|
||||
}
|
||||
|
||||
// TODO setup plugin loader
|
||||
|
||||
if err := a.setupServer(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ func (c *Command) readConfig() *Config {
|
|||
flags.StringVar(&cmdConfig.BindAddr, "bind", "", "")
|
||||
flags.StringVar(&cmdConfig.Region, "region", "", "")
|
||||
flags.StringVar(&cmdConfig.DataDir, "data-dir", "", "")
|
||||
flags.StringVar(&cmdConfig.PluginDir, "plugin-dir", "", "")
|
||||
flags.StringVar(&cmdConfig.Datacenter, "dc", "", "")
|
||||
flags.StringVar(&cmdConfig.LogLevel, "log-level", "", "")
|
||||
flags.StringVar(&cmdConfig.NodeName, "node", "", "")
|
||||
|
@ -265,6 +266,12 @@ func (c *Command) readConfig() *Config {
|
|||
}
|
||||
}
|
||||
|
||||
// Default the plugin directory to be under that of the data directory if it
|
||||
// isn't explicitly specified.
|
||||
if config.PluginDir == "" && config.DataDir != "" {
|
||||
config.PluginDir = filepath.Join(config.DataDir, "plugins")
|
||||
}
|
||||
|
||||
if dev {
|
||||
// Skip validation for dev mode
|
||||
return config
|
||||
|
@ -289,9 +296,10 @@ func (c *Command) readConfig() *Config {
|
|||
|
||||
// Verify the paths are absolute.
|
||||
dirs := map[string]string{
|
||||
"data-dir": config.DataDir,
|
||||
"alloc-dir": config.Client.AllocDir,
|
||||
"state-dir": config.Client.StateDir,
|
||||
"data-dir": config.DataDir,
|
||||
"plugin-dir": config.PluginDir,
|
||||
"alloc-dir": config.Client.AllocDir,
|
||||
"state-dir": config.Client.StateDir,
|
||||
}
|
||||
for k, dir := range dirs {
|
||||
if dir == "" {
|
||||
|
@ -304,7 +312,7 @@ func (c *Command) readConfig() *Config {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure that we have the directories we neet to run.
|
||||
// Ensure that we have the directories we need to run.
|
||||
if config.Server.Enabled && config.DataDir == "" {
|
||||
c.Ui.Error("Must specify data directory")
|
||||
return nil
|
||||
|
@ -313,8 +321,8 @@ func (c *Command) readConfig() *Config {
|
|||
// The config is valid if the top-level data-dir is set or if both
|
||||
// alloc-dir and state-dir are set.
|
||||
if config.Client.Enabled && config.DataDir == "" {
|
||||
if config.Client.AllocDir == "" || config.Client.StateDir == "" {
|
||||
c.Ui.Error("Must specify both the state and alloc dir if data-dir is omitted.")
|
||||
if config.Client.AllocDir == "" || config.Client.StateDir == "" || config.PluginDir == "" {
|
||||
c.Ui.Error("Must specify the state, alloc dir, and plugin dir if data-dir is omitted.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -1012,6 +1020,10 @@ General Options (clients and servers):
|
|||
downloaded artifacts used by drivers. On server nodes, the data
|
||||
dir is also used to store the replicated log.
|
||||
|
||||
-plugin-dir=<path>
|
||||
The plugin directory is used to discover Nomad plugins. If not specified,
|
||||
the plugin directory defaults to be that of <data-dir>/plugins/.
|
||||
|
||||
-dc=<datacenter>
|
||||
The name of the datacenter this Nomad agent is a member of. By
|
||||
default this is set to "dc1".
|
||||
|
|
|
@ -46,7 +46,7 @@ func TestCommand_Args(t *testing.T) {
|
|||
},
|
||||
{
|
||||
[]string{"-client", "-alloc-dir="},
|
||||
"Must specify both the state and alloc dir if data-dir is omitted.",
|
||||
"Must specify the state, alloc dir, and plugin dir if data-dir is omitted.",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcases {
|
||||
|
|
|
@ -2,6 +2,7 @@ region = "foobar"
|
|||
datacenter = "dc2"
|
||||
name = "my-web"
|
||||
data_dir = "/tmp/nomad"
|
||||
plugin_dir = "/tmp/nomad-plugins"
|
||||
log_level = "ERR"
|
||||
bind_addr = "192.168.0.1"
|
||||
enable_debug = true
|
||||
|
@ -190,3 +191,17 @@ autopilot {
|
|||
server_stabilization_time = "23057s"
|
||||
enable_custom_upgrades = true
|
||||
}
|
||||
plugin "docker" {
|
||||
args = ["foo", "bar"]
|
||||
config {
|
||||
foo = "bar"
|
||||
nested {
|
||||
bam = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
plugin "exec" {
|
||||
config {
|
||||
foo = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ type Config struct {
|
|||
// DataDir is the directory to store our state in
|
||||
DataDir string `mapstructure:"data_dir"`
|
||||
|
||||
// PluginDir is the directory to lookup plugins.
|
||||
PluginDir string `mapstructure:"plugin_dir"`
|
||||
|
||||
// LogLevel is the level of the logs to putout
|
||||
LogLevel string `mapstructure:"log_level"`
|
||||
|
||||
|
@ -133,6 +136,9 @@ type Config struct {
|
|||
|
||||
// Autopilot contains the configuration for Autopilot behavior.
|
||||
Autopilot *config.AutopilotConfig `mapstructure:"autopilot"`
|
||||
|
||||
// Plugins is the set of configured plugins
|
||||
Plugins []*config.PluginConfig `hcl:"plugin,expand"`
|
||||
}
|
||||
|
||||
// ClientConfig is configuration specific to the client mode
|
||||
|
@ -734,6 +740,9 @@ func (c *Config) Merge(b *Config) *Config {
|
|||
if b.DataDir != "" {
|
||||
result.DataDir = b.DataDir
|
||||
}
|
||||
if b.PluginDir != "" {
|
||||
result.PluginDir = b.PluginDir
|
||||
}
|
||||
if b.LogLevel != "" {
|
||||
result.LogLevel = b.LogLevel
|
||||
}
|
||||
|
@ -855,6 +864,16 @@ func (c *Config) Merge(b *Config) *Config {
|
|||
result.Autopilot = result.Autopilot.Merge(b.Autopilot)
|
||||
}
|
||||
|
||||
if len(result.Plugins) == 0 && len(b.Plugins) != 0 {
|
||||
copy := make([]*config.PluginConfig, len(b.Plugins))
|
||||
for i, v := range b.Plugins {
|
||||
copy[i] = v.Copy()
|
||||
}
|
||||
result.Plugins = copy
|
||||
} else if len(b.Plugins) != 0 {
|
||||
result.Plugins = config.PluginConfigSetMerge(result.Plugins, b.Plugins)
|
||||
}
|
||||
|
||||
// Merge config files lists
|
||||
result.Files = append(result.Files, b.Files...)
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
"datacenter",
|
||||
"name",
|
||||
"data_dir",
|
||||
"plugin_dir",
|
||||
"log_level",
|
||||
"bind_addr",
|
||||
"enable_debug",
|
||||
|
@ -101,6 +102,7 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
"acl",
|
||||
"sentinel",
|
||||
"autopilot",
|
||||
"plugin",
|
||||
}
|
||||
if err := helper.CheckHCLKeys(list, valid); err != nil {
|
||||
return multierror.Prefix(err, "config:")
|
||||
|
@ -125,6 +127,7 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
delete(m, "acl")
|
||||
delete(m, "sentinel")
|
||||
delete(m, "autopilot")
|
||||
delete(m, "plugin")
|
||||
|
||||
// Decode the rest
|
||||
if err := mapstructure.WeakDecode(m, result); err != nil {
|
||||
|
@ -215,6 +218,13 @@ func parseConfig(result *Config, list *ast.ObjectList) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Parse Plugin configs
|
||||
if o := list.Filter("plugin"); len(o.Items) > 0 {
|
||||
if err := parsePlugins(&result.Plugins, o); err != nil {
|
||||
return multierror.Prefix(err, "plugin->")
|
||||
}
|
||||
}
|
||||
|
||||
// Parse out http_api_response_headers fields. These are in HCL as a list so
|
||||
// we need to iterate over them and merge them.
|
||||
if headersO := list.Filter("http_api_response_headers"); len(headersO.Items) > 0 {
|
||||
|
@ -986,3 +996,38 @@ func parseAutopilot(result **config.AutopilotConfig, list *ast.ObjectList) error
|
|||
*result = autopilotConfig
|
||||
return nil
|
||||
}
|
||||
|
||||
func parsePlugins(result *[]*config.PluginConfig, list *ast.ObjectList) error {
|
||||
listLen := len(list.Items)
|
||||
plugins := make([]*config.PluginConfig, listLen)
|
||||
|
||||
// Check for invalid keys
|
||||
valid := []string{
|
||||
"args",
|
||||
"config",
|
||||
}
|
||||
|
||||
for i := 0; i < listLen; i++ {
|
||||
// Get the current plugin object
|
||||
listVal := list.Items[i]
|
||||
|
||||
if err := helper.CheckHCLKeys(listVal.Val, valid); err != nil {
|
||||
return fmt.Errorf("invalid keys in plugin config %d: %v", i+1, err)
|
||||
}
|
||||
|
||||
// Ensure there is a key
|
||||
if len(listVal.Keys) != 1 {
|
||||
return fmt.Errorf("plugin config %d doesn't incude a name key", i+1)
|
||||
}
|
||||
|
||||
var plugin config.PluginConfig
|
||||
if err := hcl.DecodeObject(&plugin, listVal); err != nil {
|
||||
return fmt.Errorf("error decoding plugin config %d: %v", i+1, err)
|
||||
}
|
||||
|
||||
plugins[i] = &plugin
|
||||
}
|
||||
|
||||
*result = plugins
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ func TestConfig_Parse(t *testing.T) {
|
|||
Datacenter: "dc2",
|
||||
NodeName: "my-web",
|
||||
DataDir: "/tmp/nomad",
|
||||
PluginDir: "/tmp/nomad-plugins",
|
||||
LogLevel: "ERR",
|
||||
BindAddr: "192.168.0.1",
|
||||
EnableDebug: true,
|
||||
|
@ -215,6 +216,26 @@ func TestConfig_Parse(t *testing.T) {
|
|||
DisableUpgradeMigration: &trueValue,
|
||||
EnableCustomUpgrades: &trueValue,
|
||||
},
|
||||
Plugins: []*config.PluginConfig{
|
||||
{
|
||||
Name: "docker",
|
||||
Args: []string{"foo", "bar"},
|
||||
Config: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"nested": []map[string]interface{}{
|
||||
{
|
||||
"bam": 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "exec",
|
||||
Config: map[string]interface{}{
|
||||
"foo": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
|
@ -225,6 +246,7 @@ func TestConfig_Parse(t *testing.T) {
|
|||
Datacenter: "",
|
||||
NodeName: "",
|
||||
DataDir: "",
|
||||
PluginDir: "",
|
||||
LogLevel: "",
|
||||
BindAddr: "",
|
||||
EnableDebug: false,
|
||||
|
@ -275,8 +297,8 @@ func TestConfig_Parse(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
require := require.New(t)
|
||||
t.Run(tc.File, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
path, err := filepath.Abs(filepath.Join("./config-test-fixtures", tc.File))
|
||||
if err != nil {
|
||||
t.Fatalf("file: %s\n\n%s", tc.File, err)
|
||||
|
|
|
@ -45,6 +45,7 @@ func TestConfig_Merge(t *testing.T) {
|
|||
Datacenter: "dc1",
|
||||
NodeName: "node1",
|
||||
DataDir: "/tmp/dir1",
|
||||
PluginDir: "/tmp/pluginDir1",
|
||||
LogLevel: "INFO",
|
||||
EnableDebug: false,
|
||||
LeaveOnInt: false,
|
||||
|
@ -175,6 +176,15 @@ func TestConfig_Merge(t *testing.T) {
|
|||
DisableUpgradeMigration: &falseValue,
|
||||
EnableCustomUpgrades: &falseValue,
|
||||
},
|
||||
Plugins: []*config.PluginConfig{
|
||||
{
|
||||
Name: "docker",
|
||||
Args: []string{"foo"},
|
||||
Config: map[string]interface{}{
|
||||
"bar": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
c3 := &Config{
|
||||
|
@ -182,6 +192,7 @@ func TestConfig_Merge(t *testing.T) {
|
|||
Datacenter: "dc2",
|
||||
NodeName: "node2",
|
||||
DataDir: "/tmp/dir2",
|
||||
PluginDir: "/tmp/pluginDir2",
|
||||
LogLevel: "DEBUG",
|
||||
EnableDebug: true,
|
||||
LeaveOnInt: true,
|
||||
|
@ -341,6 +352,22 @@ func TestConfig_Merge(t *testing.T) {
|
|||
DisableUpgradeMigration: &trueValue,
|
||||
EnableCustomUpgrades: &trueValue,
|
||||
},
|
||||
Plugins: []*config.PluginConfig{
|
||||
{
|
||||
Name: "docker",
|
||||
Args: []string{"bam"},
|
||||
Config: map[string]interface{}{
|
||||
"baz": 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "exec",
|
||||
Args: []string{"arg"},
|
||||
Config: map[string]interface{}{
|
||||
"config": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result := c0.Merge(c1)
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package config
|
||||
|
||||
import "github.com/mitchellh/copystructure"
|
||||
|
||||
// PluginConfig is used to configure a plugin explicitly
|
||||
type PluginConfig struct {
|
||||
Name string `hcl:",key"`
|
||||
Args []string `hcl:"args"`
|
||||
Config map[string]interface{} `hcl:"config"`
|
||||
}
|
||||
|
||||
func (p *PluginConfig) Merge(o *PluginConfig) *PluginConfig {
|
||||
m := *p
|
||||
|
||||
if len(o.Name) != 0 {
|
||||
m.Name = o.Name
|
||||
}
|
||||
if len(o.Args) != 0 {
|
||||
m.Args = o.Args
|
||||
}
|
||||
if len(o.Config) != 0 {
|
||||
m.Config = o.Config
|
||||
}
|
||||
|
||||
return m.Copy()
|
||||
}
|
||||
|
||||
func (p *PluginConfig) Copy() *PluginConfig {
|
||||
c := *p
|
||||
if i, err := copystructure.Copy(p.Config); err != nil {
|
||||
panic(err.Error())
|
||||
} else {
|
||||
c.Config = i.(map[string]interface{})
|
||||
}
|
||||
return &c
|
||||
}
|
||||
|
||||
// PluginConfigSetMerge merges to sets of plugin configs. For plugins with the
|
||||
// same name, the configs are merged.
|
||||
func PluginConfigSetMerge(first, second []*PluginConfig) []*PluginConfig {
|
||||
findex := make(map[string]*PluginConfig, len(first))
|
||||
for _, p := range first {
|
||||
findex[p.Name] = p
|
||||
}
|
||||
|
||||
sindex := make(map[string]*PluginConfig, len(second))
|
||||
for _, p := range second {
|
||||
sindex[p.Name] = p
|
||||
}
|
||||
|
||||
var out []*PluginConfig
|
||||
|
||||
// Go through the first set and merge any value that exist in both
|
||||
for pluginName, original := range findex {
|
||||
second, ok := sindex[pluginName]
|
||||
if !ok {
|
||||
out = append(out, original.Copy())
|
||||
continue
|
||||
}
|
||||
|
||||
out = append(out, original.Merge(second))
|
||||
}
|
||||
|
||||
// Go through the second set and add any value that didn't exist in both
|
||||
for pluginName, plugin := range sindex {
|
||||
_, ok := findex[pluginName]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
|
||||
out = append(out, plugin)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPluginConfig_Merge(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
a := &PluginConfig{
|
||||
Name: "foo",
|
||||
Args: []string{"bar"},
|
||||
Config: map[string]interface{}{
|
||||
"baz": true,
|
||||
},
|
||||
}
|
||||
|
||||
e1 := &PluginConfig{
|
||||
Name: "replaced",
|
||||
Args: []string{"bar"},
|
||||
Config: map[string]interface{}{
|
||||
"baz": true,
|
||||
},
|
||||
}
|
||||
o1 := a.Merge(&PluginConfig{Name: "replaced"})
|
||||
require.Equal(e1, o1)
|
||||
|
||||
e2 := &PluginConfig{
|
||||
Name: "foo",
|
||||
Args: []string{"replaced", "another"},
|
||||
Config: map[string]interface{}{
|
||||
"baz": true,
|
||||
},
|
||||
}
|
||||
o2 := a.Merge(&PluginConfig{
|
||||
Args: []string{"replaced", "another"},
|
||||
})
|
||||
require.Equal(e2, o2)
|
||||
|
||||
e3 := &PluginConfig{
|
||||
Name: "foo",
|
||||
Args: []string{"bar"},
|
||||
Config: map[string]interface{}{
|
||||
"replaced": 1,
|
||||
},
|
||||
}
|
||||
o3 := a.Merge(&PluginConfig{
|
||||
Config: map[string]interface{}{
|
||||
"replaced": 1,
|
||||
},
|
||||
})
|
||||
require.Equal(e3, o3)
|
||||
}
|
||||
|
||||
func TestPluginConfigSet_Merge(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
a := &PluginConfig{
|
||||
Name: "a",
|
||||
Args: []string{"a1"},
|
||||
Config: map[string]interface{}{
|
||||
"a1": true,
|
||||
},
|
||||
}
|
||||
b1 := &PluginConfig{
|
||||
Name: "b",
|
||||
Args: []string{"b1"},
|
||||
Config: map[string]interface{}{
|
||||
"b1": true,
|
||||
},
|
||||
}
|
||||
b2 := &PluginConfig{
|
||||
Name: "b",
|
||||
Args: []string{"b2"},
|
||||
Config: map[string]interface{}{
|
||||
"b2": true,
|
||||
},
|
||||
}
|
||||
c := &PluginConfig{
|
||||
Name: "c",
|
||||
Args: []string{"c"},
|
||||
Config: map[string]interface{}{
|
||||
"c1": true,
|
||||
},
|
||||
}
|
||||
|
||||
s1 := []*PluginConfig{a, b1}
|
||||
s2 := []*PluginConfig{b2, c}
|
||||
|
||||
out := PluginConfigSetMerge(s1, s2)
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
return out[i].Name < out[j].Name
|
||||
})
|
||||
|
||||
expected := []*PluginConfig{a, b2, c}
|
||||
require.EqualValues(expected, out)
|
||||
}
|
|
@ -51,7 +51,7 @@ via CLI arguments. The `agent` command accepts the following arguments:
|
|||
* `-consul-ssl`: Equivalent to the [ssl](/docs/configuration/consul.html#ssl) config option.
|
||||
* `-consul-token=<token>`: Equivalent to the [token](/docs/configuration/consul.html#token) config option.
|
||||
* `-consul-verify-ssl`: Equivalent to the [verify_ssl](/docs/configuration/consul.html#verify_ssl) config option.
|
||||
* `-data-dir=<path>`: Equivalent to the [data_dir](#data_dir) config option.
|
||||
* `-data-dir=<path>`: Equivalent to the [data_dir](/docs/configuration/index.html#data_dir) config option.
|
||||
* `-dc=<datacenter>`: Equivalent to the [datacenter](#datacenter) config option.
|
||||
* `-dev`: Start the agent in development mode. This enables a pre-configured
|
||||
dual-role agent (client + server) which is useful for developing or testing
|
||||
|
@ -68,6 +68,7 @@ via CLI arguments. The `agent` command accepts the following arguments:
|
|||
* `-node=<name>`: Equivalent to the [name](#name) config option.
|
||||
* `-node-class=<class>`: Equivalent to the Client [node_class](#node_class)
|
||||
config option.
|
||||
* `-plugin-dir=<path>`: Equivalent to the [plugin_dir](/docs/configuration/index.html#plugin_dir) config option.
|
||||
* `-region=<region>`: Equivalent to the [region](#region) config option.
|
||||
* `-rejoin`: Equivalent to the [rejoin_after_leave](#rejoin_after_leave) config option.
|
||||
* `-retry-interval`: Equivalent to the [retry_interval](#retry_interval) config option.
|
||||
|
|
|
@ -33,7 +33,7 @@ client {
|
|||
- `alloc_dir` `(string: "[data_dir]/alloc")` - Specifies the directory to use
|
||||
for allocation data. By default, this is the top-level
|
||||
[data_dir](/docs/configuration/index.html#data_dir) suffixed with
|
||||
"alloc", like `"/opt/nomad/alloc"`. This must be an absolute path
|
||||
"alloc", like `"/opt/nomad/alloc"`. This must be an absolute path.
|
||||
|
||||
- `chroot_env` <code>([ChrootEnv](#chroot_env-parameters): nil)</code> -
|
||||
Specifies a key-value mapping that defines the chroot environment for jobs
|
||||
|
|
|
@ -173,6 +173,16 @@ testing.
|
|||
value is used to identify individual agents. When specified on a server, the
|
||||
name must be unique within the region.
|
||||
|
||||
- `plugin_dir` `(string: "[data_dir]/plugins")` - Specifies the directory to
|
||||
use for looking up plugins. By default, this is the top-level
|
||||
[data_dir](#data_dir) suffixed with "plugins", like `"/opt/nomad/plugins"`.
|
||||
This must be an absolute path.
|
||||
|
||||
- `plugin` <code>([Plugin][plugin]: nil)</code> - Specifies configuration for a
|
||||
specific plugin. The plugin stanza may be repeated, once for each plugin being
|
||||
configured. The key of the stanza is the plugin's executable name relative to
|
||||
the [plugin_dir](#plugin_dir).
|
||||
|
||||
- `ports` `(Port: see below)` - Specifies the network ports used for different
|
||||
services required by the Nomad agent.
|
||||
|
||||
|
@ -243,3 +253,4 @@ http_api_response_headers {
|
|||
[sentinel]: /docs/configuration/sentinel.html "Nomad Agent sentinel Configuration"
|
||||
[server]: /docs/configuration/server.html "Nomad Agent server Configuration"
|
||||
[acl]: /docs/configuration/acl.html "Nomad Agent ACL Configuration"
|
||||
[plugin]: /docs/configuration/plugin.html "Nomad Agent Plugin Configuration"
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "plugin Stanza - Agent Configuration"
|
||||
sidebar_current: "docs-configuration-plugin"
|
||||
description: |-
|
||||
The "plugin" stanza is used to configure a Nomad plugin.
|
||||
---
|
||||
|
||||
# `plugin` Stanza
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<th width="120">Placement</th>
|
||||
<td>
|
||||
<code>**plugin**</code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The `plugin` stanza is used to configure an individual plugin.
|
||||
|
||||
```hcl
|
||||
plugin "example-plugin" {
|
||||
args = ["-my-flag"]
|
||||
config {
|
||||
foo = "bar"
|
||||
bam {
|
||||
baz = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The name of the plugin is the plugin's executable name relative to to the
|
||||
[plugin_dir](/docs/configuration/index.html#plugin_dir). If the plugin has a
|
||||
suffix, such as `.exe`, this should be omitted.
|
||||
|
||||
## `plugin` Parameters
|
||||
|
||||
- `args` `(array<string>: [])` - Specifies a set of arguments to pass to the
|
||||
plugin binary when it is executed.
|
||||
|
||||
- `config` `(hcl/json: nil)` - Specifies configuration values for the plugin
|
||||
either as HCL or JSON. The accepted values are plugin specific. Please refer
|
||||
to the individual plugin's documentation.
|
|
@ -38,6 +38,9 @@
|
|||
<li <%= sidebar_current("docs-configuration-consul") %>>
|
||||
<a href="/docs/configuration/consul.html">consul</a>
|
||||
</li>
|
||||
<li <%= sidebar_current("docs-configuration-plugin") %>>
|
||||
<a href="/docs/configuration/plugin.html">plugin</a>
|
||||
</li>
|
||||
<li <%= sidebar_current("docs-configuration-sentinel") %>>
|
||||
<a href="/docs/configuration/sentinel.html">sentinel</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue