diff --git a/agent/config/builder.go b/agent/config/builder.go index 9cd5956ed0..031c4b0cf9 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -635,17 +635,16 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { var configEntries []structs.ConfigEntry - if len(c.ConfigEntries.Bootstrap.ProxyDefaults) > 0 { - for name, config := range c.ConfigEntries.Bootstrap.ProxyDefaults { - if name != structs.ProxyConfigGlobal { - return RuntimeConfig{}, fmt.Errorf("invalid config.proxy_defaults name (%q), only %q is supported", name, structs.ProxyConfigGlobal) + if len(c.ConfigEntries.Bootstrap) > 0 { + for i, rawEntry := range c.ConfigEntries.Bootstrap { + entry, err := structs.DecodeConfigEntry(rawEntry) + if err != nil { + return RuntimeConfig{}, fmt.Errorf("config_entries.bootstrap[%d]: %s", i, err) } - - configEntries = append(configEntries, &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: config, - }) + if err := entry.Validate(); err != nil { + return RuntimeConfig{}, fmt.Errorf("config_entries.bootstrap[%d]: %s", i, err) + } + configEntries = append(configEntries, entry) } } diff --git a/agent/config/config.go b/agent/config/config.go index 1e769118d6..9cbfa2ad32 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -97,6 +97,8 @@ func Parse(data string, format string) (c Config, err error) { "services.connect.sidecar_service.checks", "service.connect.sidecar_service.proxy.upstreams", "services.connect.sidecar_service.proxy.upstreams", + + "config_entries.bootstrap", }) // There is a difference of representation of some fields depending on @@ -654,9 +656,10 @@ type Tokens struct { } type ConfigEntries struct { - Bootstrap ConfigEntriesBootstrap `json:"bootstrap,omitempty" hcl:"bootstrap" mapstructure:"bootstrap"` -} - -type ConfigEntriesBootstrap struct { - ProxyDefaults map[string]map[string]interface{} `json:"proxy_defaults,omitempty" hcl:"proxy_defaults" mapstructure:"proxy_defaults"` + // Bootstrap is the list of config_entries that should only be persisted to + // cluster on initial startup of a new leader if no such config exists + // already. The type is map not structs.ConfigEntry for decoding reasons - we + // need to figure out the right concrete type before we can decode it + // unabiguously. + Bootstrap []map[string]interface{} `json:"bootstrap,omitempty" hcl:"bootstrap" mapstructure:"bootstrap"` } diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 18d9a7e354..5a7515c26b 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2693,6 +2693,82 @@ func TestConfigFlagsAndEdgecases(t *testing.T) { } }, }, + + // ------------------------------------------------------------ + // ConfigEntry Handling + // + { + desc: "ConfigEntry bootstrap doesn't parse", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ + "config_entries": { + "bootstrap": [ + { + "foo": "bar" + } + ] + } + }`}, + hcl: []string{` + config_entries { + bootstrap { + foo = "bar" + } + }`}, + err: "config_entries.bootstrap[0]: Payload does not contain a kind/Kind", + }, + { + desc: "ConfigEntry bootstrap unknown kind", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ + "config_entries": { + "bootstrap": [ + { + "kind": "foo", + "name": "bar", + "baz": 1 + } + ] + } + }`}, + hcl: []string{` + config_entries { + bootstrap { + kind = "foo" + name = "bar" + baz = 1 + } + }`}, + err: "config_entries.bootstrap[0]: invalid config entry kind: foo", + }, + { + desc: "ConfigEntry bootstrap invalid", + args: []string{`-data-dir=` + dataDir}, + json: []string{`{ + "config_entries": { + "bootstrap": [ + { + "kind": "proxy-defaults", + "name": "invalid-name", + "config": { + "foo": "bar" + } + } + ] + } + }`}, + hcl: []string{` + config_entries { + bootstrap { + kind = "proxy-defaults" + name = "invalid-name" + config { + foo = "bar" + } + } + }`}, + err: "config_entries.bootstrap[0]: invalid name (\"invalid-name\"), only \"global\" is supported", + }, } testConfig(t, tests, dataDir) @@ -3009,14 +3085,16 @@ func TestFullConfig(t *testing.T) { "check_update_interval": "16507s", "client_addr": "93.83.18.19", "config_entries": { - "bootstrap": { - "proxy_defaults": { - "global": { + "bootstrap": [ + { + "kind": "proxy-defaults", + "name": "global", + "config": { "foo": "bar", "bar": 1.0 } } - } + ] }, "connect": { "ca_provider": "consul", @@ -3573,9 +3651,14 @@ func TestFullConfig(t *testing.T) { check_update_interval = "16507s" client_addr = "93.83.18.19" config_entries { - bootstrap proxy_defaults global { - foo = "bar" - bar = 1.0 + # This is using the repeated block-to-array HCL magic + bootstrap { + kind = "proxy-defaults" + name = "global" + config { + foo = "bar" + bar = 1.0 + } } } connect {