Support reading multiple configuration files(#2504)
feat(config): Support multiple files This updates the three subcommands that take a `-config` flag to to support multiple config files via a repeated `-config` flag. It updates the following subcommands: - `server` - `database init` - `database migrate` Note that the multiple file support only works if all config files are HCL, not JSON. Also note that the config files are concatenated together. There is no attempt to merge config files, so having the same stanza in multiple files can yield unexpected results, with only one of the stanzas being used. When used with these limitations understood, this provides a way to take different actions for different kinds of dynamic configuration changes. An example would be when using consul-template to render the configuration files for boundary. With the multi file support consul-template can render one config file for the controller stanza, and provide boundary with a dynamic database credential via vault. Then when the credential is rotated, consul-template can send boundary a SIGHUP to switch to the new credential without a restart. A separate template could be used to render a config for a stanza that does not support SIGHUP, such as the events stanza that gets its values via consul's KV. If these values change, consul-template can restart boundary so the new configuration is used. Co-authored-by: Timothy Messier <tim.messier@gmail.com> Co-authored-by: Jeff Mitchell <jeffrey.mitchell@gmail.com>
This commit is contained in:
1 parent
441ca59ea3
commit
d896f37493
22 files changed
+2279
-178
No files matched your search
@@ -5,19 +5,12 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
kms_plugin_assets "github.com/hashicorp/boundary/plugins/kms"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/configutil/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/mlock"
|
||||
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
@@ -41,7 +34,7 @@ type InitCommand struct {
|
||||
// deferred function on the Run method.
|
||||
configWrapperCleanupFunc func() error
|
||||
|
||||
flagConfig string
|
||||
flagConfig []string
|
||||
flagConfigKms string
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
@@ -87,7 +80,7 @@ func (c *InitCommand) Flags() *base.FlagSets {
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "config",
|
||||
Target: &c.flagConfig,
|
||||
Completion: complete.PredictOr(
|
||||
@@ -475,49 +468,7 @@ func (c *InitCommand) ParseFlagsAndConfig(args []string) int {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
wrapperPath := c.flagConfig
|
||||
if c.flagConfigKms != "" {
|
||||
wrapperPath = c.flagConfigKms
|
||||
}
|
||||
wrapper, cleanupFunc, err := wrapper.GetWrapperFromPath(
|
||||
c.Context,
|
||||
wrapperPath,
|
||||
globals.KmsPurposeConfig,
|
||||
configutil.WithPluginOptions(
|
||||
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
||||
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
||||
),
|
||||
// TODO: How would we want to expose this kind of log to users when
|
||||
// using recovery configs? Generally with normal CLI commands we
|
||||
// don't print out all of these logs. We may want a logger with a
|
||||
// custom writer behind our existing gate where we print nothing
|
||||
// unless there is an error, then dump all of it.
|
||||
configutil.WithLogger(hclog.NewNullLogger()),
|
||||
)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return base.CommandUserError
|
||||
}
|
||||
if wrapper != nil {
|
||||
c.configWrapperCleanupFunc = cleanupFunc
|
||||
if ifWrapper, ok := wrapper.(wrapping.InitFinalizer); ok {
|
||||
if err := ifWrapper.Init(c.Context); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
c.UI.Error(fmt.Errorf("Could not initialize kms: %w", err).Error())
|
||||
return base.CommandUserError
|
||||
}
|
||||
c.configWrapperCleanupFunc = func() error {
|
||||
if err := ifWrapper.Finalize(context.Background()); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
c.UI.Warn(fmt.Errorf("Could not finalize kms: %w", err).Error())
|
||||
}
|
||||
if cleanupFunc != nil {
|
||||
return cleanupFunc()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
|
||||
c.Config, err = config.Load(c.Context, c.flagConfig, c.flagConfigKms)
|
||||
if err != nil {
|
||||
c.UI.Error("Error parsing config: " + err.Error())
|
||||
return base.CommandUserError
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/db/schema"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
host_plugin_assets "github.com/hashicorp/boundary/plugins/host"
|
||||
kms_plugin_assets "github.com/hashicorp/boundary/plugins/kms"
|
||||
external_host_plugins "github.com/hashicorp/boundary/sdk/plugins/host"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/configutil/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/mlock"
|
||||
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
|
||||
@@ -49,7 +42,7 @@ type MigrateCommand struct {
|
||||
|
||||
selectedRepairs schema.RepairMigrations
|
||||
|
||||
flagConfig string
|
||||
flagConfig []string
|
||||
flagConfigKms string
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
@@ -79,7 +72,7 @@ func (c *MigrateCommand) Flags() *base.FlagSets {
|
||||
|
||||
f := set.NewFlagSet("Command options")
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "config",
|
||||
Target: &c.flagConfig,
|
||||
Completion: complete.PredictOr(
|
||||
@@ -320,49 +313,7 @@ func (c *MigrateCommand) ParseFlagsAndConfig(args []string) int {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
wrapperPath := c.flagConfig
|
||||
if c.flagConfigKms != "" {
|
||||
wrapperPath = c.flagConfigKms
|
||||
}
|
||||
wrapper, cleanupFunc, err := wrapper.GetWrapperFromPath(
|
||||
c.Context,
|
||||
wrapperPath,
|
||||
globals.KmsPurposeConfig,
|
||||
configutil.WithPluginOptions(
|
||||
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
||||
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
||||
),
|
||||
// TODO: How would we want to expose this kind of log to users when
|
||||
// using recovery configs? Generally with normal CLI commands we
|
||||
// don't print out all of these logs. We may want a logger with a
|
||||
// custom writer behind our existing gate where we print nothing
|
||||
// unless there is an error, then dump all of it.
|
||||
configutil.WithLogger(hclog.NewNullLogger()),
|
||||
)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return base.CommandUserError
|
||||
}
|
||||
if wrapper != nil {
|
||||
c.configWrapperCleanupFunc = cleanupFunc
|
||||
if ifWrapper, ok := wrapper.(wrapping.InitFinalizer); ok {
|
||||
if err := ifWrapper.Init(c.Context); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
c.UI.Error(fmt.Errorf("Could not initialize kms: %w", err).Error())
|
||||
return base.CommandUserError
|
||||
}
|
||||
c.configWrapperCleanupFunc = func() error {
|
||||
if err := ifWrapper.Finalize(context.Background()); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
c.UI.Warn(fmt.Errorf("Could not finalize kms: %w", err).Error())
|
||||
}
|
||||
if cleanupFunc != nil {
|
||||
return cleanupFunc()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
|
||||
c.Config, err = config.Load(c.Context, c.flagConfig, c.flagConfigKms)
|
||||
if err != nil {
|
||||
c.UI.Error("Error parsing config: " + err.Error())
|
||||
return base.CommandUserError
|
||||
|
||||
@@ -23,15 +23,10 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
kms_plugin_assets "github.com/hashicorp/boundary/plugins/kms"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/go-secure-stdlib/configutil/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/mlock"
|
||||
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
@@ -56,7 +51,7 @@ type Command struct {
|
||||
controller *controller.Controller
|
||||
worker *worker.Worker
|
||||
|
||||
flagConfig string
|
||||
flagConfig []string
|
||||
flagConfigKms string
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
@@ -90,14 +85,14 @@ func (c *Command) Flags() *base.FlagSets {
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "config",
|
||||
Target: &c.flagConfig,
|
||||
Completion: complete.PredictOr(
|
||||
complete.PredictFiles("*.hcl"),
|
||||
complete.PredictFiles("*.json"),
|
||||
),
|
||||
Usage: "Path to the configuration file.",
|
||||
Usage: "Path to the configuration file. Can be specified multiple times for multiple configuration files (only if using HCL format).",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
@@ -548,63 +543,17 @@ func (c *Command) reloadConfig() (*config.Config, int) {
|
||||
switch {
|
||||
case c.presetConfig != nil:
|
||||
cfg, err = config.Parse(c.presetConfig.Load())
|
||||
if err != nil {
|
||||
event.WriteError(c.Context, op, err, event.WithInfoMsg("could not parse presetConfig", "config", c.presetConfig))
|
||||
return nil, base.CommandUserError
|
||||
}
|
||||
|
||||
default:
|
||||
wrapperPath := c.flagConfig
|
||||
if c.flagConfigKms != "" {
|
||||
wrapperPath = c.flagConfigKms
|
||||
cfg, err = config.Load(c.Context, c.flagConfig, c.flagConfigKms)
|
||||
if err != nil {
|
||||
c.UI.Error("Error parsing config: " + err.Error())
|
||||
return nil, base.CommandUserError
|
||||
}
|
||||
var configWrapper wrapping.Wrapper
|
||||
var ifWrapper wrapping.InitFinalizer
|
||||
var cleanupFunc func() error
|
||||
if wrapperPath != "" {
|
||||
configWrapper, cleanupFunc, err = wrapper.GetWrapperFromPath(
|
||||
c.Context,
|
||||
wrapperPath,
|
||||
globals.KmsPurposeConfig,
|
||||
configutil.WithPluginOptions(
|
||||
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
||||
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
||||
),
|
||||
// TODO: How would we want to expose this kind of log to users when
|
||||
// using recovery configs? Generally with normal CLI commands we
|
||||
// don't print out all of these logs. We may want a logger with a
|
||||
// custom writer behind our existing gate where we print nothing
|
||||
// unless there is an error, then dump all of it.
|
||||
configutil.WithLogger(hclog.NewNullLogger()),
|
||||
)
|
||||
if err != nil {
|
||||
event.WriteError(c.Context, op, err, event.WithInfoMsg("could not get kms wrapper from config", "path", c.flagConfig))
|
||||
return nil, base.CommandUserError
|
||||
}
|
||||
if cleanupFunc != nil {
|
||||
defer func() {
|
||||
if err := cleanupFunc(); err != nil {
|
||||
event.WriteError(c.Context, op, err, event.WithInfoMsg("could not clean up kms wrapper", "path", c.flagConfig))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if configWrapper != nil {
|
||||
ifWrapper, _ = configWrapper.(wrapping.InitFinalizer)
|
||||
}
|
||||
}
|
||||
if ifWrapper != nil {
|
||||
if err := ifWrapper.Init(c.Context); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
event.WriteError(c.Context, op, err, event.WithInfoMsg("could not initialize kms", "path", c.flagConfig))
|
||||
return nil, base.CommandCliError
|
||||
}
|
||||
}
|
||||
cfg, err = config.LoadFile(c.flagConfig, configWrapper)
|
||||
if ifWrapper != nil {
|
||||
if err := ifWrapper.Finalize(context.Background()); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
event.WriteError(context.Background(), op, err, event.WithInfoMsg("could not finalize kms", "path", c.flagConfig))
|
||||
return nil, base.CommandCliError
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
event.WriteError(c.Context, op, err, event.WithInfoMsg("could not parse config", "path", c.flagConfig))
|
||||
return nil, base.CommandUserError
|
||||
}
|
||||
return cfg, 0
|
||||
}
|
||||
@@ -754,7 +703,7 @@ func (c *Command) WaitForInterrupt() int {
|
||||
var newConf *config.Config
|
||||
var out int
|
||||
|
||||
if c.flagConfig == "" && c.presetConfig == nil {
|
||||
if len(c.flagConfig) == 0 && c.presetConfig == nil {
|
||||
goto RUNRELOADFUNCS
|
||||
}
|
||||
|
||||
|
||||
@@ -2,25 +2,31 @@ package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
kms_plugin_assets "github.com/hashicorp/boundary/plugins/kms"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
configutil "github.com/hashicorp/go-secure-stdlib/configutil/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/listenerutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/parseutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/hashicorp/hcl"
|
||||
"github.com/hashicorp/hcl/hcl/ast"
|
||||
@@ -324,23 +330,100 @@ func New() *Config {
|
||||
}
|
||||
}
|
||||
|
||||
// LoadFile loads the configuration from the given file.
|
||||
func LoadFile(path string, wrapper wrapping.Wrapper) (*Config, error) {
|
||||
d, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Load will create a Config from the given config files. It concatenates the
|
||||
// contents of the files together. This allows for composing a config from
|
||||
// separate files, but notably does not attempt any merging of configs. Thus it
|
||||
// is possible that the concatenation results in an invalid config file. This
|
||||
// also supports decrypting the config, either with a kms block in one of the
|
||||
// given files, or as a separate file in wrapperPath.
|
||||
//
|
||||
// Note that having multiple config files is only supported properly if they are
|
||||
// all hcl files. If they are json files, only the first file is used. A mix of
|
||||
// hcl and json will result in an error.
|
||||
func Load(ctx context.Context, paths []string, wrapperPath string) (*Config, error) {
|
||||
const op = "config.Load"
|
||||
|
||||
var err error
|
||||
var cfg *Config
|
||||
|
||||
configStrs := make([]string, 0, len(paths))
|
||||
for _, path := range paths {
|
||||
fileBytes, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
event.WriteError(ctx, op, err, event.WithInfoMsg("could not read config file", "path", path, "error", err))
|
||||
return nil, err
|
||||
}
|
||||
configStrs = append(configStrs, string(fileBytes))
|
||||
}
|
||||
configString := strings.Join(configStrs, "\n")
|
||||
|
||||
wrapperString := configString
|
||||
if wrapperPath != "" {
|
||||
wrapperBytes, err := os.ReadFile(wrapperPath)
|
||||
if err != nil {
|
||||
event.WriteError(ctx, op, err, event.WithInfoMsg("could not read kms config file", "path", wrapperPath, "error", err))
|
||||
return nil, err
|
||||
}
|
||||
wrapperString = string(wrapperBytes)
|
||||
}
|
||||
|
||||
raw := string(d)
|
||||
var configWrapper wrapping.Wrapper
|
||||
var ifWrapper wrapping.InitFinalizer
|
||||
var cleanupFunc func() error
|
||||
if wrapperString != "" {
|
||||
configWrapper, cleanupFunc, err = wrapper.GetWrapperFromHcl(
|
||||
ctx,
|
||||
wrapperString,
|
||||
globals.KmsPurposeConfig,
|
||||
configutil.WithPluginOptions(
|
||||
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
||||
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
||||
),
|
||||
// TODO: How would we want to expose this kind of log to users when
|
||||
// using recovery configs? Generally with normal CLI commands we
|
||||
// don't print out all of these logs. We may want a logger with a
|
||||
// custom writer behind our existing gate where we print nothing
|
||||
// unless there is an error, then dump all of it.
|
||||
configutil.WithLogger(hclog.NewNullLogger()),
|
||||
)
|
||||
if err != nil {
|
||||
event.WriteError(ctx, op, err, event.WithInfoMsg("could not get kms wrapper from config", "path", wrapperPath))
|
||||
return nil, err
|
||||
}
|
||||
if cleanupFunc != nil {
|
||||
defer func() {
|
||||
if err := cleanupFunc(); err != nil {
|
||||
event.WriteError(ctx, op, err, event.WithInfoMsg("could not clean up kms wrapper", "path", wrapperPath))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if configWrapper != nil {
|
||||
ifWrapper, _ = configWrapper.(wrapping.InitFinalizer)
|
||||
}
|
||||
}
|
||||
if ifWrapper != nil {
|
||||
if err := ifWrapper.Init(ctx); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
event.WriteError(ctx, op, err, event.WithInfoMsg("could not initialize kms", "path", wrapperPath))
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if wrapper != nil {
|
||||
raw, err = configutil.EncryptDecrypt(raw, true, true, wrapper)
|
||||
if configWrapper != nil {
|
||||
configString, err = configutil.EncryptDecrypt(configString, true, true, configWrapper)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return Parse(raw)
|
||||
cfg, err = Parse(configString)
|
||||
|
||||
if ifWrapper != nil {
|
||||
if err := ifWrapper.Finalize(context.Background()); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
|
||||
event.WriteError(context.Background(), op, err, event.WithInfoMsg("could not finalize kms", "path", wrapperPath))
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func Parse(d string) (*Config, error) {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,28 @@
|
||||
disable_mlock = true
|
||||
|
||||
controller {
|
||||
name = "controller0"
|
||||
description = "A controller"
|
||||
|
||||
database {
|
||||
url = "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "api"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "cluster"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "ops"
|
||||
tls_disable = true
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
worker {
|
||||
name = "worker0"
|
||||
description = "A worker"
|
||||
address = "boundary"
|
||||
initial_upstreams = ["boundary:9201"]
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "proxy"
|
||||
tls_disable = true
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
kms "aead" {
|
||||
purpose = "root"
|
||||
aead_type = "aes-gcm"
|
||||
key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
|
||||
key_id = "global_root"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "worker-auth"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_worker-auth"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "recovery"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_recovery"
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
disable_mlock = true
|
||||
|
||||
controller {
|
||||
name = "controller0"
|
||||
description = "A controller"
|
||||
|
||||
database {
|
||||
url = "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "api"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "cluster"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "ops"
|
||||
tls_disable = true
|
||||
}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
controller {
|
||||
name = "controller0"
|
||||
description = "A controller but duplicated"
|
||||
|
||||
database {
|
||||
url = "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
worker {
|
||||
name = "worker0"
|
||||
description = "A worker"
|
||||
address = "boundary"
|
||||
initial_upstreams = ["boundary:9201"]
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "proxy"
|
||||
tls_disable = true
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
kms "aead" {
|
||||
purpose = "root"
|
||||
aead_type = "aes-gcm"
|
||||
key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
|
||||
key_id = "global_root"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "worker-auth"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_worker-auth"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "recovery"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_recovery"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"disable_mlock": true,
|
||||
"controller": [
|
||||
{
|
||||
"database": [
|
||||
{
|
||||
"url": "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
],
|
||||
"description": "A controller",
|
||||
"name": "controller0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"worker": [
|
||||
{
|
||||
"address": "boundary",
|
||||
"description": "A worker",
|
||||
"initial_upstreams": [
|
||||
"boundary:9201"
|
||||
],
|
||||
"name": "worker0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"kms": [
|
||||
{
|
||||
"aead": {
|
||||
"aead_type": "aes-gcm",
|
||||
"key": "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung=",
|
||||
"key_id": "global_root",
|
||||
"purpose": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"aead": {
|
||||
"aead_type": "aes-gcm",
|
||||
"key": "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ=",
|
||||
"key_id": "global_worker-auth",
|
||||
"purpose": "worker-auth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"aead": {
|
||||
"aead_type": "aes-gcm",
|
||||
"key": "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ=",
|
||||
"key_id": "global_recovery",
|
||||
"purpose": "recovery"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"listener": [
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "api",
|
||||
"tls_disable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "cluster",
|
||||
"tls_disable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "ops",
|
||||
"tls_disable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "proxy",
|
||||
"tls_disable": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
disable_mlock = true
|
||||
|
||||
controller {
|
||||
name = "controller0"
|
||||
description = "A controller"
|
||||
|
||||
database {
|
||||
url = "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "api"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "cluster"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "ops"
|
||||
tls_disable = true
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"worker": [
|
||||
{
|
||||
"address": "boundary",
|
||||
"description": "A worker",
|
||||
"initial_upstreams": [
|
||||
"boundary:9201"
|
||||
],
|
||||
"name": "worker0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
kms "aead" {
|
||||
purpose = "root"
|
||||
aead_type = "aes-gcm"
|
||||
key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
|
||||
key_id = "global_root"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "worker-auth"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_worker-auth"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "recovery"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_recovery"
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
disable_mlock = true
|
||||
|
||||
controller {
|
||||
name = "controller0"
|
||||
description = "A controller"
|
||||
|
||||
database {
|
||||
url = "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
}
|
||||
|
||||
worker {
|
||||
name = "worker0"
|
||||
description = "A worker"
|
||||
address = "boundary"
|
||||
initial_upstreams = ["boundary:9201"]
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "api"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "cluster"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "proxy"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "boundary"
|
||||
purpose = "ops"
|
||||
tls_disable = true
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "root"
|
||||
aead_type = "aes-gcm"
|
||||
key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
|
||||
key_id = "global_root"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "worker-auth"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_worker-auth"
|
||||
}
|
||||
|
||||
kms "aead" {
|
||||
purpose = "recovery"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "global_recovery"
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"controller": [
|
||||
{
|
||||
"database": [
|
||||
{
|
||||
"url": "env://LOAD_TEST_BOUNDARY_POSTGRES_URL"
|
||||
}
|
||||
],
|
||||
"description": "A controller",
|
||||
"name": "controller0"
|
||||
}
|
||||
],
|
||||
"disable_mlock": true,
|
||||
"kms": [
|
||||
{
|
||||
"aead": {
|
||||
"aead_type": "aes-gcm",
|
||||
"key": "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung=",
|
||||
"key_id": "global_root",
|
||||
"purpose": "root"
|
||||
}
|
||||
},
|
||||
{
|
||||
"aead": {
|
||||
"aead_type": "aes-gcm",
|
||||
"key": "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ=",
|
||||
"key_id": "global_worker-auth",
|
||||
"purpose": "worker-auth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"aead": {
|
||||
"aead_type": "aes-gcm",
|
||||
"key": "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ=",
|
||||
"key_id": "global_recovery",
|
||||
"purpose": "recovery"
|
||||
}
|
||||
}
|
||||
],
|
||||
"listener": [
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "api",
|
||||
"tls_disable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "cluster",
|
||||
"tls_disable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "proxy",
|
||||
"tls_disable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tcp": {
|
||||
"address": "boundary",
|
||||
"purpose": "ops",
|
||||
"tls_disable": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"worker": [
|
||||
{
|
||||
"address": "boundary",
|
||||
"description": "A worker",
|
||||
"initial_upstreams": [
|
||||
"boundary:9201"
|
||||
],
|
||||
"name": "worker0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
@@ -72,7 +73,7 @@ func WithConfigFile(f string) Option {
|
||||
return fmt.Errorf("WithConfigFile provided more than once.")
|
||||
}
|
||||
c.setWithConfigFile = true
|
||||
cfg, err := config.LoadFile(f, nil)
|
||||
cfg, err := config.Load(context.Background(), []string{f}, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user