2015-03-12 22:21:11 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2019-03-04 22:11:56 +00:00
|
|
|
"errors"
|
2015-03-12 22:21:11 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2016-08-15 13:42:42 +00:00
|
|
|
"strconv"
|
2015-03-12 22:21:11 +00:00
|
|
|
"strings"
|
2015-07-30 17:21:41 +00:00
|
|
|
"time"
|
2015-03-12 22:21:11 +00:00
|
|
|
|
2018-04-05 15:49:21 +00:00
|
|
|
"github.com/hashicorp/errwrap"
|
2018-04-03 00:46:59 +00:00
|
|
|
log "github.com/hashicorp/go-hclog"
|
2016-08-19 20:45:17 +00:00
|
|
|
|
2019-01-09 00:48:57 +00:00
|
|
|
multierror "github.com/hashicorp/go-multierror"
|
2015-03-12 22:21:11 +00:00
|
|
|
"github.com/hashicorp/hcl"
|
2016-03-09 23:59:44 +00:00
|
|
|
"github.com/hashicorp/hcl/hcl/ast"
|
2017-03-07 16:21:22 +00:00
|
|
|
"github.com/hashicorp/vault/helper/parseutil"
|
2015-03-12 22:21:11 +00:00
|
|
|
)
|
|
|
|
|
2019-02-14 20:46:59 +00:00
|
|
|
const (
|
|
|
|
prometheusDefaultRetentionTime = 24 * time.Hour
|
|
|
|
)
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
// Config is the configuration for the vault server.
|
|
|
|
type Config struct {
|
2015-04-17 18:25:20 +00:00
|
|
|
Listeners []*Listener `hcl:"-"`
|
2017-03-08 14:17:00 +00:00
|
|
|
Storage *Storage `hcl:"-"`
|
|
|
|
HAStorage *Storage `hcl:"-"`
|
2015-04-17 18:25:20 +00:00
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
Seals []*Seal `hcl:"-"`
|
2017-02-24 15:45:29 +00:00
|
|
|
|
2018-07-12 20:29:36 +00:00
|
|
|
CacheSize int `hcl:"cache_size"`
|
|
|
|
DisableCache bool `hcl:"-"`
|
|
|
|
DisableCacheRaw interface{} `hcl:"disable_cache"`
|
|
|
|
DisableMlock bool `hcl:"-"`
|
|
|
|
DisableMlockRaw interface{} `hcl:"disable_mlock"`
|
|
|
|
DisablePrintableCheck bool `hcl:"-"`
|
|
|
|
DisablePrintableCheckRaw interface{} `hcl:"disable_printable_check"`
|
2015-07-14 22:27:18 +00:00
|
|
|
|
2017-03-07 16:21:22 +00:00
|
|
|
EnableUI bool `hcl:"-"`
|
|
|
|
EnableUIRaw interface{} `hcl:"ui"`
|
2017-02-24 15:45:29 +00:00
|
|
|
|
2015-07-31 17:24:23 +00:00
|
|
|
Telemetry *Telemetry `hcl:"telemetry"`
|
2015-07-30 13:42:49 +00:00
|
|
|
|
2015-08-27 14:50:16 +00:00
|
|
|
MaxLeaseTTL time.Duration `hcl:"-"`
|
2017-03-07 16:21:22 +00:00
|
|
|
MaxLeaseTTLRaw interface{} `hcl:"max_lease_ttl"`
|
2015-08-27 14:50:16 +00:00
|
|
|
DefaultLeaseTTL time.Duration `hcl:"-"`
|
2017-03-07 16:21:22 +00:00
|
|
|
DefaultLeaseTTLRaw interface{} `hcl:"default_lease_ttl"`
|
2016-07-26 06:25:33 +00:00
|
|
|
|
2018-07-24 21:50:49 +00:00
|
|
|
DefaultMaxRequestDuration time.Duration `hcl:"-"`
|
2018-09-18 21:30:21 +00:00
|
|
|
DefaultMaxRequestDurationRaw interface{} `hcl:"default_max_request_duration"`
|
2018-07-24 21:50:49 +00:00
|
|
|
|
2017-08-30 20:28:23 +00:00
|
|
|
ClusterName string `hcl:"cluster_name"`
|
|
|
|
ClusterCipherSuites string `hcl:"cluster_cipher_suites"`
|
|
|
|
|
2017-04-04 00:52:29 +00:00
|
|
|
PluginDirectory string `hcl:"plugin_directory"`
|
2017-09-15 04:21:35 +00:00
|
|
|
|
2018-09-05 19:52:54 +00:00
|
|
|
LogLevel string `hcl:"log_level"`
|
|
|
|
|
2017-09-16 21:09:37 +00:00
|
|
|
PidFile string `hcl:"pid_file"`
|
2017-09-15 04:21:35 +00:00
|
|
|
EnableRawEndpoint bool `hcl:"-"`
|
|
|
|
EnableRawEndpointRaw interface{} `hcl:"raw_storage_endpoint"`
|
2017-11-08 19:19:41 +00:00
|
|
|
|
|
|
|
APIAddr string `hcl:"api_addr"`
|
|
|
|
ClusterAddr string `hcl:"cluster_addr"`
|
|
|
|
DisableClustering bool `hcl:"-"`
|
|
|
|
DisableClusteringRaw interface{} `hcl:"disable_clustering"`
|
2018-05-30 12:34:27 +00:00
|
|
|
|
2018-08-24 16:09:03 +00:00
|
|
|
DisablePerformanceStandby bool `hcl:"-"`
|
|
|
|
DisablePerformanceStandbyRaw interface{} `hcl:"disable_performance_standby"`
|
|
|
|
|
2018-05-30 12:34:27 +00:00
|
|
|
DisableSealWrap bool `hcl:"-"`
|
|
|
|
DisableSealWrapRaw interface{} `hcl:"disable_sealwrap"`
|
2018-10-23 19:03:17 +00:00
|
|
|
|
2018-10-23 19:09:35 +00:00
|
|
|
DisableIndexing bool `hcl:"-"`
|
|
|
|
DisableIndexingRaw interface{} `hcl:"disable_indexing"`
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2015-03-31 23:44:47 +00:00
|
|
|
// DevConfig is a Config that is used for dev mode of Vault.
|
2017-02-16 21:29:30 +00:00
|
|
|
func DevConfig(ha, transactional bool) *Config {
|
2016-08-15 13:42:42 +00:00
|
|
|
ret := &Config{
|
2017-09-15 04:21:35 +00:00
|
|
|
DisableMlock: true,
|
|
|
|
EnableRawEndpoint: true,
|
2015-04-28 22:11:39 +00:00
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
Storage: &Storage{
|
2015-03-31 23:44:47 +00:00
|
|
|
Type: "inmem",
|
|
|
|
},
|
|
|
|
|
|
|
|
Listeners: []*Listener{
|
|
|
|
&Listener{
|
|
|
|
Type: "tcp",
|
2017-06-22 19:29:53 +00:00
|
|
|
Config: map[string]interface{}{
|
2017-08-02 22:24:12 +00:00
|
|
|
"address": "127.0.0.1:8200",
|
|
|
|
"tls_disable": true,
|
|
|
|
"proxy_protocol_behavior": "allow_authorized",
|
|
|
|
"proxy_protocol_authorized_addrs": "127.0.0.1:8200",
|
2015-03-31 23:44:47 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-07-14 22:27:18 +00:00
|
|
|
|
2017-02-24 15:45:29 +00:00
|
|
|
EnableUI: true,
|
|
|
|
|
2019-02-14 20:46:59 +00:00
|
|
|
Telemetry: &Telemetry{
|
|
|
|
PrometheusRetentionTime: prometheusDefaultRetentionTime,
|
|
|
|
DisableHostname: true,
|
|
|
|
},
|
2015-03-31 23:44:47 +00:00
|
|
|
}
|
2016-08-15 13:42:42 +00:00
|
|
|
|
2017-02-16 21:29:30 +00:00
|
|
|
switch {
|
|
|
|
case ha && transactional:
|
2017-03-08 14:17:00 +00:00
|
|
|
ret.Storage.Type = "inmem_transactional_ha"
|
2017-02-16 21:29:30 +00:00
|
|
|
case !ha && transactional:
|
2017-03-08 14:17:00 +00:00
|
|
|
ret.Storage.Type = "inmem_transactional"
|
2017-02-16 21:29:30 +00:00
|
|
|
case ha && !transactional:
|
2017-03-08 14:17:00 +00:00
|
|
|
ret.Storage.Type = "inmem_ha"
|
2016-08-15 13:42:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
2015-03-31 23:44:47 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
// Listener is the listener configuration for the server.
|
|
|
|
type Listener struct {
|
|
|
|
Type string
|
2017-06-22 19:29:53 +00:00
|
|
|
Config map[string]interface{}
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Listener) GoString() string {
|
|
|
|
return fmt.Sprintf("*%#v", *l)
|
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
// Storage is the underlying storage configuration for the server.
|
|
|
|
type Storage struct {
|
2016-08-15 13:42:42 +00:00
|
|
|
Type string
|
|
|
|
RedirectAddr string
|
|
|
|
ClusterAddr string
|
|
|
|
DisableClustering bool
|
|
|
|
Config map[string]string
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
func (b *Storage) GoString() string {
|
2015-03-12 22:21:11 +00:00
|
|
|
return fmt.Sprintf("*%#v", *b)
|
|
|
|
}
|
|
|
|
|
2017-10-23 21:39:21 +00:00
|
|
|
// Seal contains Seal configuration for the server
|
|
|
|
type Seal struct {
|
2018-10-23 06:34:02 +00:00
|
|
|
Type string
|
|
|
|
Disabled bool
|
|
|
|
Config map[string]string
|
2017-02-24 15:45:29 +00:00
|
|
|
}
|
|
|
|
|
2017-10-23 21:39:21 +00:00
|
|
|
func (h *Seal) GoString() string {
|
2017-02-24 15:45:29 +00:00
|
|
|
return fmt.Sprintf("*%#v", *h)
|
|
|
|
}
|
|
|
|
|
2015-07-14 22:27:18 +00:00
|
|
|
// Telemetry is the telemetry configuration for the server
|
|
|
|
type Telemetry struct {
|
|
|
|
StatsiteAddr string `hcl:"statsite_address"`
|
|
|
|
StatsdAddr string `hcl:"statsd_address"`
|
|
|
|
|
|
|
|
DisableHostname bool `hcl:"disable_hostname"`
|
2016-07-22 19:49:23 +00:00
|
|
|
|
|
|
|
// Circonus: see https://github.com/circonus-labs/circonus-gometrics
|
|
|
|
// for more details on the various configuration options.
|
|
|
|
// Valid configuration combinations:
|
|
|
|
// - CirconusAPIToken
|
|
|
|
// metric management enabled (search for existing check or create a new one)
|
|
|
|
// - CirconusSubmissionUrl
|
|
|
|
// metric management disabled (use check with specified submission_url,
|
|
|
|
// broker must be using a public SSL certificate)
|
|
|
|
// - CirconusAPIToken + CirconusCheckSubmissionURL
|
|
|
|
// metric management enabled (use check with specified submission_url)
|
|
|
|
// - CirconusAPIToken + CirconusCheckID
|
|
|
|
// metric management enabled (use check with specified id)
|
|
|
|
|
|
|
|
// CirconusAPIToken is a valid API Token used to create/manage check. If provided,
|
|
|
|
// metric management is enabled.
|
|
|
|
// Default: none
|
|
|
|
CirconusAPIToken string `hcl:"circonus_api_token"`
|
|
|
|
// CirconusAPIApp is an app name associated with API token.
|
|
|
|
// Default: "consul"
|
|
|
|
CirconusAPIApp string `hcl:"circonus_api_app"`
|
|
|
|
// CirconusAPIURL is the base URL to use for contacting the Circonus API.
|
|
|
|
// Default: "https://api.circonus.com/v2"
|
|
|
|
CirconusAPIURL string `hcl:"circonus_api_url"`
|
|
|
|
// CirconusSubmissionInterval is the interval at which metrics are submitted to Circonus.
|
|
|
|
// Default: 10s
|
|
|
|
CirconusSubmissionInterval string `hcl:"circonus_submission_interval"`
|
|
|
|
// CirconusCheckSubmissionURL is the check.config.submission_url field from a
|
|
|
|
// previously created HTTPTRAP check.
|
|
|
|
// Default: none
|
|
|
|
CirconusCheckSubmissionURL string `hcl:"circonus_submission_url"`
|
|
|
|
// CirconusCheckID is the check id (not check bundle id) from a previously created
|
|
|
|
// HTTPTRAP check. The numeric portion of the check._cid field.
|
|
|
|
// Default: none
|
|
|
|
CirconusCheckID string `hcl:"circonus_check_id"`
|
|
|
|
// CirconusCheckForceMetricActivation will force enabling metrics, as they are encountered,
|
|
|
|
// if the metric already exists and is NOT active. If check management is enabled, the default
|
2018-03-20 18:54:10 +00:00
|
|
|
// behavior is to add new metrics as they are encountered. If the metric already exists in the
|
2016-07-22 19:49:23 +00:00
|
|
|
// check, it will *NOT* be activated. This setting overrides that behavior.
|
|
|
|
// Default: "false"
|
|
|
|
CirconusCheckForceMetricActivation string `hcl:"circonus_check_force_metric_activation"`
|
2018-03-20 18:54:10 +00:00
|
|
|
// CirconusCheckInstanceID serves to uniquely identify the metrics coming from this "instance".
|
2016-07-22 19:49:23 +00:00
|
|
|
// It can be used to maintain metric continuity with transient or ephemeral instances as
|
|
|
|
// they move around within an infrastructure.
|
|
|
|
// Default: hostname:app
|
|
|
|
CirconusCheckInstanceID string `hcl:"circonus_check_instance_id"`
|
|
|
|
// CirconusCheckSearchTag is a special tag which, when coupled with the instance id, helps to
|
|
|
|
// narrow down the search results when neither a Submission URL or Check ID is provided.
|
|
|
|
// Default: service:app (e.g. service:consul)
|
|
|
|
CirconusCheckSearchTag string `hcl:"circonus_check_search_tag"`
|
2016-11-10 21:17:55 +00:00
|
|
|
// CirconusCheckTags is a comma separated list of tags to apply to the check. Note that
|
|
|
|
// the value of CirconusCheckSearchTag will always be added to the check.
|
|
|
|
// Default: none
|
|
|
|
CirconusCheckTags string `mapstructure:"circonus_check_tags"`
|
|
|
|
// CirconusCheckDisplayName is the name for the check which will be displayed in the Circonus UI.
|
|
|
|
// Default: value of CirconusCheckInstanceID
|
|
|
|
CirconusCheckDisplayName string `mapstructure:"circonus_check_display_name"`
|
2016-07-22 19:49:23 +00:00
|
|
|
// CirconusBrokerID is an explicit broker to use when creating a new check. The numeric portion
|
|
|
|
// of broker._cid. If metric management is enabled and neither a Submission URL nor Check ID
|
|
|
|
// is provided, an attempt will be made to search for an existing check using Instance ID and
|
|
|
|
// Search Tag. If one is not found, a new HTTPTRAP check will be created.
|
|
|
|
// Default: use Select Tag if provided, otherwise, a random Enterprise Broker associated
|
|
|
|
// with the specified API token or the default Circonus Broker.
|
|
|
|
// Default: none
|
|
|
|
CirconusBrokerID string `hcl:"circonus_broker_id"`
|
|
|
|
// CirconusBrokerSelectTag is a special tag which will be used to select a broker when
|
|
|
|
// a Broker ID is not provided. The best use of this is to as a hint for which broker
|
|
|
|
// should be used based on *where* this particular instance is running.
|
|
|
|
// (e.g. a specific geo location or datacenter, dc:sfo)
|
|
|
|
// Default: none
|
|
|
|
CirconusBrokerSelectTag string `hcl:"circonus_broker_select_tag"`
|
2017-06-17 03:51:46 +00:00
|
|
|
|
|
|
|
// Dogstats:
|
|
|
|
// DogStatsdAddr is the address of a dogstatsd instance. If provided,
|
|
|
|
// metrics will be sent to that instance
|
|
|
|
DogStatsDAddr string `hcl:"dogstatsd_addr"`
|
|
|
|
|
|
|
|
// DogStatsdTags are the global tags that should be sent with each packet to dogstatsd
|
|
|
|
// It is a list of strings, where each string looks like "my_tag_name:my_tag_value"
|
|
|
|
DogStatsDTags []string `hcl:"dogstatsd_tags"`
|
2019-02-14 20:46:59 +00:00
|
|
|
|
|
|
|
// Prometheus:
|
|
|
|
// PrometheusRetentionTime is the retention time for prometheus metrics if greater than 0.
|
|
|
|
// Default: 24h
|
|
|
|
PrometheusRetentionTime time.Duration `hcl:-`
|
|
|
|
PrometheusRetentionTimeRaw interface{} `hcl:"prometheus_retention_time"`
|
2015-07-14 22:27:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Telemetry) GoString() string {
|
|
|
|
return fmt.Sprintf("*%#v", *s)
|
|
|
|
}
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
// Merge merges two configurations.
|
|
|
|
func (c *Config) Merge(c2 *Config) *Config {
|
2016-07-05 20:49:15 +00:00
|
|
|
if c2 == nil {
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
result := new(Config)
|
|
|
|
for _, l := range c.Listeners {
|
|
|
|
result.Listeners = append(result.Listeners, l)
|
|
|
|
}
|
|
|
|
for _, l := range c2.Listeners {
|
|
|
|
result.Listeners = append(result.Listeners, l)
|
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
result.Storage = c.Storage
|
|
|
|
if c2.Storage != nil {
|
|
|
|
result.Storage = c2.Storage
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
result.HAStorage = c.HAStorage
|
|
|
|
if c2.HAStorage != nil {
|
|
|
|
result.HAStorage = c2.HAStorage
|
2016-03-21 20:56:13 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
for _, s := range c.Seals {
|
|
|
|
result.Seals = append(result.Seals, s)
|
|
|
|
}
|
|
|
|
for _, s := range c2.Seals {
|
|
|
|
result.Seals = append(result.Seals, s)
|
2017-02-24 15:45:29 +00:00
|
|
|
}
|
|
|
|
|
2015-07-14 22:27:18 +00:00
|
|
|
result.Telemetry = c.Telemetry
|
|
|
|
if c2.Telemetry != nil {
|
|
|
|
result.Telemetry = c2.Telemetry
|
2015-04-15 01:44:09 +00:00
|
|
|
}
|
|
|
|
|
2016-08-26 14:27:06 +00:00
|
|
|
result.CacheSize = c.CacheSize
|
|
|
|
if c2.CacheSize != 0 {
|
|
|
|
result.CacheSize = c2.CacheSize
|
|
|
|
}
|
|
|
|
|
2015-10-12 16:55:02 +00:00
|
|
|
// merging these booleans via an OR operation
|
|
|
|
result.DisableCache = c.DisableCache
|
|
|
|
if c2.DisableCache {
|
|
|
|
result.DisableCache = c2.DisableCache
|
|
|
|
}
|
|
|
|
|
2015-07-30 13:42:49 +00:00
|
|
|
result.DisableMlock = c.DisableMlock
|
|
|
|
if c2.DisableMlock {
|
|
|
|
result.DisableMlock = c2.DisableMlock
|
|
|
|
}
|
|
|
|
|
2019-01-23 16:27:21 +00:00
|
|
|
result.DisablePrintableCheck = c.DisablePrintableCheck
|
|
|
|
if c2.DisablePrintableCheckRaw != nil {
|
|
|
|
result.DisablePrintableCheck = c2.DisablePrintableCheck
|
|
|
|
}
|
|
|
|
|
2015-07-30 13:42:49 +00:00
|
|
|
// merge these integers via a MAX operation
|
2015-08-27 14:50:16 +00:00
|
|
|
result.MaxLeaseTTL = c.MaxLeaseTTL
|
|
|
|
if c2.MaxLeaseTTL > result.MaxLeaseTTL {
|
|
|
|
result.MaxLeaseTTL = c2.MaxLeaseTTL
|
2015-07-30 13:42:49 +00:00
|
|
|
}
|
|
|
|
|
2015-08-27 14:50:16 +00:00
|
|
|
result.DefaultLeaseTTL = c.DefaultLeaseTTL
|
|
|
|
if c2.DefaultLeaseTTL > result.DefaultLeaseTTL {
|
|
|
|
result.DefaultLeaseTTL = c2.DefaultLeaseTTL
|
2015-07-30 13:42:49 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 21:50:49 +00:00
|
|
|
result.DefaultMaxRequestDuration = c.DefaultMaxRequestDuration
|
|
|
|
if c2.DefaultMaxRequestDuration > result.DefaultMaxRequestDuration {
|
|
|
|
result.DefaultMaxRequestDuration = c2.DefaultMaxRequestDuration
|
|
|
|
}
|
|
|
|
|
2018-09-05 19:52:54 +00:00
|
|
|
result.LogLevel = c.LogLevel
|
|
|
|
if c2.LogLevel != "" {
|
|
|
|
result.LogLevel = c2.LogLevel
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:11:12 +00:00
|
|
|
result.ClusterName = c.ClusterName
|
|
|
|
if c2.ClusterName != "" {
|
|
|
|
result.ClusterName = c2.ClusterName
|
|
|
|
}
|
|
|
|
|
2017-08-30 20:28:23 +00:00
|
|
|
result.ClusterCipherSuites = c.ClusterCipherSuites
|
|
|
|
if c2.ClusterCipherSuites != "" {
|
|
|
|
result.ClusterCipherSuites = c2.ClusterCipherSuites
|
|
|
|
}
|
|
|
|
|
2017-02-24 15:45:29 +00:00
|
|
|
result.EnableUI = c.EnableUI
|
|
|
|
if c2.EnableUI {
|
|
|
|
result.EnableUI = c2.EnableUI
|
|
|
|
}
|
|
|
|
|
2017-09-15 04:21:35 +00:00
|
|
|
result.EnableRawEndpoint = c.EnableRawEndpoint
|
|
|
|
if c2.EnableRawEndpoint {
|
|
|
|
result.EnableRawEndpoint = c2.EnableRawEndpoint
|
|
|
|
}
|
|
|
|
|
2019-01-23 16:27:21 +00:00
|
|
|
result.APIAddr = c.APIAddr
|
|
|
|
if c2.APIAddr != "" {
|
|
|
|
result.APIAddr = c2.APIAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
result.ClusterAddr = c.ClusterAddr
|
|
|
|
if c2.ClusterAddr != "" {
|
|
|
|
result.ClusterAddr = c2.ClusterAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retain raw value so that it can be assigned to storage objects
|
|
|
|
result.DisableClustering = c.DisableClustering
|
|
|
|
result.DisableClusteringRaw = c.DisableClusteringRaw
|
|
|
|
if c2.DisableClusteringRaw != nil {
|
|
|
|
result.DisableClustering = c2.DisableClustering
|
|
|
|
result.DisableClusteringRaw = c2.DisableClusteringRaw
|
|
|
|
}
|
|
|
|
|
2017-04-13 18:22:53 +00:00
|
|
|
result.PluginDirectory = c.PluginDirectory
|
|
|
|
if c2.PluginDirectory != "" {
|
|
|
|
result.PluginDirectory = c2.PluginDirectory
|
|
|
|
}
|
|
|
|
|
2017-09-16 21:09:37 +00:00
|
|
|
result.PidFile = c.PidFile
|
|
|
|
if c2.PidFile != "" {
|
|
|
|
result.PidFile = c2.PidFile
|
|
|
|
}
|
|
|
|
|
2018-08-24 16:09:03 +00:00
|
|
|
result.DisablePerformanceStandby = c.DisablePerformanceStandby
|
|
|
|
if c2.DisablePerformanceStandby {
|
|
|
|
result.DisablePerformanceStandby = c2.DisablePerformanceStandby
|
|
|
|
}
|
|
|
|
|
2018-05-30 12:34:27 +00:00
|
|
|
result.DisableSealWrap = c.DisableSealWrap
|
|
|
|
if c2.DisableSealWrap {
|
|
|
|
result.DisableSealWrap = c2.DisableSealWrap
|
|
|
|
}
|
|
|
|
|
2018-10-23 19:03:17 +00:00
|
|
|
result.DisableIndexing = c.DisableIndexing
|
|
|
|
if c2.DisableIndexing {
|
|
|
|
result.DisableIndexing = c2.DisableIndexing
|
|
|
|
}
|
|
|
|
|
2019-01-23 16:27:21 +00:00
|
|
|
// Use values from top-level configuration for storage if set
|
|
|
|
if storage := result.Storage; storage != nil {
|
|
|
|
if result.APIAddr != "" {
|
|
|
|
storage.RedirectAddr = result.APIAddr
|
|
|
|
}
|
|
|
|
if result.ClusterAddr != "" {
|
|
|
|
storage.ClusterAddr = result.ClusterAddr
|
|
|
|
}
|
|
|
|
if result.DisableClusteringRaw != nil {
|
|
|
|
storage.DisableClustering = result.DisableClustering
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if haStorage := result.HAStorage; haStorage != nil {
|
|
|
|
if result.APIAddr != "" {
|
|
|
|
haStorage.RedirectAddr = result.APIAddr
|
|
|
|
}
|
|
|
|
if result.ClusterAddr != "" {
|
|
|
|
haStorage.ClusterAddr = result.ClusterAddr
|
|
|
|
}
|
|
|
|
if result.DisableClusteringRaw != nil {
|
|
|
|
haStorage.DisableClustering = result.DisableClustering
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2015-03-12 22:30:07 +00:00
|
|
|
// LoadConfig loads the configuration at the given path, regardless if
|
|
|
|
// its a file or directory.
|
2016-08-19 20:45:17 +00:00
|
|
|
func LoadConfig(path string, logger log.Logger) (*Config, error) {
|
2015-03-12 22:30:07 +00:00
|
|
|
fi, err := os.Stat(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if fi.IsDir() {
|
2016-08-19 20:45:17 +00:00
|
|
|
return LoadConfigDir(path, logger)
|
2015-03-12 22:30:07 +00:00
|
|
|
}
|
2017-09-15 04:21:35 +00:00
|
|
|
return LoadConfigFile(path, logger)
|
2015-03-12 22:30:07 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
// LoadConfigFile loads the configuration from the given file.
|
2016-08-19 20:45:17 +00:00
|
|
|
func LoadConfigFile(path string, logger log.Logger) (*Config, error) {
|
2015-03-12 22:21:11 +00:00
|
|
|
// Read the file
|
|
|
|
d, err := ioutil.ReadFile(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-08-19 20:45:17 +00:00
|
|
|
return ParseConfig(string(d), logger)
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
2015-03-12 22:21:11 +00:00
|
|
|
|
2016-08-19 20:45:17 +00:00
|
|
|
func ParseConfig(d string, logger log.Logger) (*Config, error) {
|
2015-03-12 22:21:11 +00:00
|
|
|
// Parse!
|
2016-03-09 23:59:44 +00:00
|
|
|
obj, err := hcl.Parse(d)
|
2015-03-12 22:21:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start building the result
|
|
|
|
var result Config
|
2015-04-17 18:21:40 +00:00
|
|
|
if err := hcl.DecodeObject(&result, obj); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-03-07 16:21:22 +00:00
|
|
|
if result.MaxLeaseTTLRaw != nil {
|
|
|
|
if result.MaxLeaseTTL, err = parseutil.ParseDurationSecond(result.MaxLeaseTTLRaw); err != nil {
|
2015-07-30 17:21:41 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2017-03-07 16:21:22 +00:00
|
|
|
if result.DefaultLeaseTTLRaw != nil {
|
|
|
|
if result.DefaultLeaseTTL, err = parseutil.ParseDurationSecond(result.DefaultLeaseTTLRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 21:50:49 +00:00
|
|
|
if result.DefaultMaxRequestDurationRaw != nil {
|
|
|
|
if result.DefaultMaxRequestDuration, err = parseutil.ParseDurationSecond(result.DefaultMaxRequestDurationRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-07 16:21:22 +00:00
|
|
|
if result.EnableUIRaw != nil {
|
|
|
|
if result.EnableUI, err = parseutil.ParseBool(result.EnableUIRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.DisableCacheRaw != nil {
|
|
|
|
if result.DisableCache, err = parseutil.ParseBool(result.DisableCacheRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.DisableMlockRaw != nil {
|
|
|
|
if result.DisableMlock, err = parseutil.ParseBool(result.DisableMlockRaw); err != nil {
|
2015-07-30 17:21:41 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-12 20:29:36 +00:00
|
|
|
if result.DisablePrintableCheckRaw != nil {
|
|
|
|
if result.DisablePrintableCheck, err = parseutil.ParseBool(result.DisablePrintableCheckRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-15 04:21:35 +00:00
|
|
|
if result.EnableRawEndpointRaw != nil {
|
|
|
|
if result.EnableRawEndpoint, err = parseutil.ParseBool(result.EnableRawEndpointRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-08 19:19:41 +00:00
|
|
|
if result.DisableClusteringRaw != nil {
|
|
|
|
if result.DisableClustering, err = parseutil.ParseBool(result.DisableClusteringRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-24 16:09:03 +00:00
|
|
|
if result.DisablePerformanceStandbyRaw != nil {
|
|
|
|
if result.DisablePerformanceStandby, err = parseutil.ParseBool(result.DisablePerformanceStandbyRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-30 12:34:27 +00:00
|
|
|
if result.DisableSealWrapRaw != nil {
|
|
|
|
if result.DisableSealWrap, err = parseutil.ParseBool(result.DisableSealWrapRaw); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-23 19:09:35 +00:00
|
|
|
if result.DisableIndexingRaw != nil {
|
|
|
|
if result.DisableIndexing, err = parseutil.ParseBool(result.DisableIndexingRaw); err != nil {
|
2018-10-23 19:03:17 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
list, ok := obj.Node.(*ast.ObjectList)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("error parsing: file doesn't contain a root object")
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
2016-03-09 23:59:44 +00:00
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
// Look for storage but still support old backend
|
|
|
|
if o := list.Filter("storage"); len(o.Items) > 0 {
|
2018-09-25 23:18:22 +00:00
|
|
|
if err := ParseStorage(&result, o, "storage"); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'storage': {{err}}", err)
|
2017-03-08 14:17:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if o := list.Filter("backend"); len(o.Items) > 0 {
|
2018-09-25 23:18:22 +00:00
|
|
|
if err := ParseStorage(&result, o, "backend"); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'backend': {{err}}", err)
|
2017-03-08 14:17:00 +00:00
|
|
|
}
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-14 22:27:18 +00:00
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
if o := list.Filter("ha_storage"); len(o.Items) > 0 {
|
|
|
|
if err := parseHAStorage(&result, o, "ha_storage"); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'ha_storage': {{err}}", err)
|
2017-03-08 14:17:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if o := list.Filter("ha_backend"); len(o.Items) > 0 {
|
|
|
|
if err := parseHAStorage(&result, o, "ha_backend"); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'ha_backend': {{err}}", err)
|
2017-03-08 14:17:00 +00:00
|
|
|
}
|
2015-07-14 22:27:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-24 15:45:29 +00:00
|
|
|
if o := list.Filter("hsm"); len(o.Items) > 0 {
|
2019-03-04 22:11:56 +00:00
|
|
|
if err := parseSeals(&result, o, "hsm"); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'hsm': {{err}}", err)
|
2017-02-24 15:45:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-23 21:39:21 +00:00
|
|
|
if o := list.Filter("seal"); len(o.Items) > 0 {
|
2019-03-04 22:11:56 +00:00
|
|
|
if err := parseSeals(&result, o, "seal"); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'seal': {{err}}", err)
|
2017-10-23 21:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
if o := list.Filter("listener"); len(o.Items) > 0 {
|
|
|
|
if err := parseListeners(&result, o); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'listener': {{err}}", err)
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-12 22:21:11 +00:00
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
if o := list.Filter("telemetry"); len(o.Items) > 0 {
|
|
|
|
if err := parseTelemetry(&result, o); err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf("error parsing 'telemetry': {{err}}", err)
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
2015-07-14 22:27:18 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
return &result, nil
|
2015-07-14 22:27:18 +00:00
|
|
|
}
|
|
|
|
|
2015-03-12 22:21:11 +00:00
|
|
|
// LoadConfigDir loads all the configurations in the given directory
|
|
|
|
// in alphabetical order.
|
2016-08-19 20:45:17 +00:00
|
|
|
func LoadConfigDir(dir string, logger log.Logger) (*Config, error) {
|
2015-03-12 22:21:11 +00:00
|
|
|
f, err := os.Open(dir)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
fi, err := f.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if !fi.IsDir() {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, fmt.Errorf("configuration path must be a directory: %q", dir)
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var files []string
|
|
|
|
err = nil
|
|
|
|
for err != io.EOF {
|
|
|
|
var fis []os.FileInfo
|
|
|
|
fis, err = f.Readdir(128)
|
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, fi := range fis {
|
|
|
|
// Ignore directories
|
|
|
|
if fi.IsDir() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only care about files that are valid to load.
|
|
|
|
name := fi.Name()
|
|
|
|
skip := true
|
|
|
|
if strings.HasSuffix(name, ".hcl") {
|
|
|
|
skip = false
|
|
|
|
} else if strings.HasSuffix(name, ".json") {
|
|
|
|
skip = false
|
|
|
|
}
|
|
|
|
if skip || isTemporaryFile(name) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
path := filepath.Join(dir, name)
|
|
|
|
files = append(files, path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var result *Config
|
|
|
|
for _, f := range files {
|
2016-08-19 20:45:17 +00:00
|
|
|
config, err := LoadConfigFile(f, logger)
|
2015-03-12 22:21:11 +00:00
|
|
|
if err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, errwrap.Wrapf(fmt.Sprintf("error loading %q: {{err}}", f), err)
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if result == nil {
|
|
|
|
result = config
|
|
|
|
} else {
|
|
|
|
result = result.Merge(config)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// isTemporaryFile returns true or false depending on whether the
|
|
|
|
// provided file name is a temporary file for the following editors:
|
|
|
|
// emacs or vim.
|
|
|
|
func isTemporaryFile(name string) bool {
|
|
|
|
return strings.HasSuffix(name, "~") || // vim
|
|
|
|
strings.HasPrefix(name, ".#") || // emacs
|
|
|
|
(strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#")) // emacs
|
|
|
|
}
|
|
|
|
|
2018-09-25 23:18:22 +00:00
|
|
|
func ParseStorage(result *Config, list *ast.ObjectList, name string) error {
|
2016-03-09 23:59:44 +00:00
|
|
|
if len(list.Items) > 1 {
|
2017-03-08 14:17:00 +00:00
|
|
|
return fmt.Errorf("only one %q block is permitted", name)
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get our item
|
|
|
|
item := list.Items[0]
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
key := name
|
2016-03-09 23:59:44 +00:00
|
|
|
if len(item.Keys) > 0 {
|
|
|
|
key = item.Keys[0].Token.Value().(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
var m map[string]string
|
|
|
|
if err := hcl.DecodeObject(&m, item.Val); err != nil {
|
2017-03-08 14:17:00 +00:00
|
|
|
return multierror.Prefix(err, fmt.Sprintf("%s.%s:", name, key))
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
|
2016-08-15 13:42:42 +00:00
|
|
|
// Pull out the redirect address since it's common to all backends
|
|
|
|
var redirectAddr string
|
|
|
|
if v, ok := m["redirect_addr"]; ok {
|
|
|
|
redirectAddr = v
|
|
|
|
delete(m, "redirect_addr")
|
|
|
|
} else if v, ok := m["advertise_addr"]; ok {
|
|
|
|
redirectAddr = v
|
2016-03-09 23:59:44 +00:00
|
|
|
delete(m, "advertise_addr")
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2016-08-15 13:42:42 +00:00
|
|
|
// Pull out the cluster address since it's common to all backends
|
|
|
|
var clusterAddr string
|
|
|
|
if v, ok := m["cluster_addr"]; ok {
|
|
|
|
clusterAddr = v
|
|
|
|
delete(m, "cluster_addr")
|
|
|
|
}
|
|
|
|
|
2016-10-02 18:54:01 +00:00
|
|
|
var disableClustering bool
|
2016-08-15 13:42:42 +00:00
|
|
|
var err error
|
|
|
|
if v, ok := m["disable_clustering"]; ok {
|
|
|
|
disableClustering, err = strconv.ParseBool(v)
|
|
|
|
if err != nil {
|
2017-03-08 14:17:00 +00:00
|
|
|
return multierror.Prefix(err, fmt.Sprintf("%s.%s:", name, key))
|
2016-08-15 13:42:42 +00:00
|
|
|
}
|
|
|
|
delete(m, "disable_clustering")
|
|
|
|
}
|
|
|
|
|
2017-11-08 19:19:41 +00:00
|
|
|
// Override with top-level values if they are set
|
|
|
|
if result.APIAddr != "" {
|
|
|
|
redirectAddr = result.APIAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.ClusterAddr != "" {
|
|
|
|
clusterAddr = result.ClusterAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.DisableClusteringRaw != nil {
|
|
|
|
disableClustering = result.DisableClustering
|
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
result.Storage = &Storage{
|
2016-08-15 13:42:42 +00:00
|
|
|
RedirectAddr: redirectAddr,
|
|
|
|
ClusterAddr: clusterAddr,
|
|
|
|
DisableClustering: disableClustering,
|
|
|
|
Type: strings.ToLower(key),
|
|
|
|
Config: m,
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
func parseHAStorage(result *Config, list *ast.ObjectList, name string) error {
|
2016-03-09 23:59:44 +00:00
|
|
|
if len(list.Items) > 1 {
|
2017-03-08 14:17:00 +00:00
|
|
|
return fmt.Errorf("only one %q block is permitted", name)
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
// Get our item
|
|
|
|
item := list.Items[0]
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
key := name
|
2016-03-09 23:59:44 +00:00
|
|
|
if len(item.Keys) > 0 {
|
|
|
|
key = item.Keys[0].Token.Value().(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
var m map[string]string
|
|
|
|
if err := hcl.DecodeObject(&m, item.Val); err != nil {
|
2017-03-08 14:17:00 +00:00
|
|
|
return multierror.Prefix(err, fmt.Sprintf("%s.%s:", name, key))
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
|
2016-08-15 13:42:42 +00:00
|
|
|
// Pull out the redirect address since it's common to all backends
|
|
|
|
var redirectAddr string
|
|
|
|
if v, ok := m["redirect_addr"]; ok {
|
|
|
|
redirectAddr = v
|
|
|
|
delete(m, "redirect_addr")
|
|
|
|
} else if v, ok := m["advertise_addr"]; ok {
|
|
|
|
redirectAddr = v
|
2016-03-09 23:59:44 +00:00
|
|
|
delete(m, "advertise_addr")
|
|
|
|
}
|
|
|
|
|
2016-08-15 13:42:42 +00:00
|
|
|
// Pull out the cluster address since it's common to all backends
|
|
|
|
var clusterAddr string
|
|
|
|
if v, ok := m["cluster_addr"]; ok {
|
|
|
|
clusterAddr = v
|
|
|
|
delete(m, "cluster_addr")
|
|
|
|
}
|
|
|
|
|
2016-10-02 18:54:01 +00:00
|
|
|
var disableClustering bool
|
2016-08-15 13:42:42 +00:00
|
|
|
var err error
|
|
|
|
if v, ok := m["disable_clustering"]; ok {
|
|
|
|
disableClustering, err = strconv.ParseBool(v)
|
|
|
|
if err != nil {
|
2017-03-08 14:17:00 +00:00
|
|
|
return multierror.Prefix(err, fmt.Sprintf("%s.%s:", name, key))
|
2016-08-15 13:42:42 +00:00
|
|
|
}
|
|
|
|
delete(m, "disable_clustering")
|
|
|
|
}
|
|
|
|
|
2017-11-08 19:19:41 +00:00
|
|
|
// Override with top-level values if they are set
|
|
|
|
if result.APIAddr != "" {
|
|
|
|
redirectAddr = result.APIAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.ClusterAddr != "" {
|
|
|
|
clusterAddr = result.ClusterAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.DisableClusteringRaw != nil {
|
|
|
|
disableClustering = result.DisableClustering
|
|
|
|
}
|
|
|
|
|
2017-03-08 14:17:00 +00:00
|
|
|
result.HAStorage = &Storage{
|
2016-08-15 13:42:42 +00:00
|
|
|
RedirectAddr: redirectAddr,
|
|
|
|
ClusterAddr: clusterAddr,
|
|
|
|
DisableClustering: disableClustering,
|
|
|
|
Type: strings.ToLower(key),
|
|
|
|
Config: m,
|
2016-03-09 23:59:44 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
func parseSeals(result *Config, list *ast.ObjectList, blockName string) error {
|
|
|
|
if len(list.Items) > 2 {
|
|
|
|
return fmt.Errorf("only two or less %q blocks are permitted", blockName)
|
2017-02-24 15:45:29 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
seals := make([]*Seal, 0, len(list.Items))
|
|
|
|
for _, item := range list.Items {
|
|
|
|
key := "seal"
|
|
|
|
if len(item.Keys) > 0 {
|
|
|
|
key = item.Keys[0].Token.Value().(string)
|
|
|
|
}
|
2017-02-24 15:45:29 +00:00
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
var m map[string]string
|
|
|
|
if err := hcl.DecodeObject(&m, item.Val); err != nil {
|
|
|
|
return multierror.Prefix(err, fmt.Sprintf("seal.%s:", key))
|
|
|
|
}
|
2017-02-24 15:45:29 +00:00
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
var disabled bool
|
|
|
|
var err error
|
|
|
|
if v, ok := m["disabled"]; ok {
|
|
|
|
disabled, err = strconv.ParseBool(v)
|
|
|
|
if err != nil {
|
|
|
|
return multierror.Prefix(err, fmt.Sprintf("%s.%s:", blockName, key))
|
|
|
|
}
|
|
|
|
delete(m, "disabled")
|
2018-10-23 06:34:02 +00:00
|
|
|
}
|
2019-03-04 22:11:56 +00:00
|
|
|
seals = append(seals, &Seal{
|
|
|
|
Type: strings.ToLower(key),
|
|
|
|
Disabled: disabled,
|
|
|
|
Config: m,
|
|
|
|
})
|
2018-10-23 06:34:02 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
if len(seals) == 2 &&
|
|
|
|
(seals[0].Disabled && seals[1].Disabled || !seals[0].Disabled && !seals[1].Disabled) {
|
|
|
|
return errors.New("seals: two seals provided but both are disabled or neither are disabled")
|
2017-02-24 15:45:29 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 22:11:56 +00:00
|
|
|
result.Seals = seals
|
|
|
|
|
2017-02-24 15:45:29 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
func parseListeners(result *Config, list *ast.ObjectList) error {
|
|
|
|
listeners := make([]*Listener, 0, len(list.Items))
|
|
|
|
for _, item := range list.Items {
|
|
|
|
key := "listener"
|
|
|
|
if len(item.Keys) > 0 {
|
|
|
|
key = item.Keys[0].Token.Value().(string)
|
|
|
|
}
|
|
|
|
|
2017-06-22 19:29:53 +00:00
|
|
|
var m map[string]interface{}
|
2016-03-09 23:59:44 +00:00
|
|
|
if err := hcl.DecodeObject(&m, item.Val); err != nil {
|
|
|
|
return multierror.Prefix(err, fmt.Sprintf("listeners.%s:", key))
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2016-06-02 16:40:25 +00:00
|
|
|
lnType := strings.ToLower(key)
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
listeners = append(listeners, &Listener{
|
2016-06-02 16:40:25 +00:00
|
|
|
Type: lnType,
|
2016-03-09 23:59:44 +00:00
|
|
|
Config: m,
|
2015-03-12 22:21:11 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
result.Listeners = listeners
|
|
|
|
return nil
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
func parseTelemetry(result *Config, list *ast.ObjectList) error {
|
|
|
|
if len(list.Items) > 1 {
|
|
|
|
return fmt.Errorf("only one 'telemetry' block is permitted")
|
|
|
|
}
|
2015-03-12 22:21:11 +00:00
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
// Get our one item
|
|
|
|
item := list.Items[0]
|
|
|
|
|
|
|
|
var t Telemetry
|
|
|
|
if err := hcl.DecodeObject(&t, item.Val); err != nil {
|
|
|
|
return multierror.Prefix(err, "telemetry:")
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
if result.Telemetry == nil {
|
|
|
|
result.Telemetry = &Telemetry{}
|
2015-03-12 22:21:11 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
if err := hcl.DecodeObject(&result.Telemetry, item.Val); err != nil {
|
|
|
|
return multierror.Prefix(err, "telemetry:")
|
|
|
|
}
|
2019-02-14 20:46:59 +00:00
|
|
|
|
|
|
|
if result.Telemetry.PrometheusRetentionTimeRaw != nil {
|
|
|
|
var err error
|
|
|
|
if result.Telemetry.PrometheusRetentionTime, err = parseutil.ParseDurationSecond(result.Telemetry.PrometheusRetentionTimeRaw); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result.Telemetry.PrometheusRetentionTime = prometheusDefaultRetentionTime
|
|
|
|
}
|
|
|
|
|
2016-03-09 23:59:44 +00:00
|
|
|
return nil
|
|
|
|
}
|