mirror of https://github.com/hashicorp/consul
Add config changes for UI metrics
parent
0df4371be2
commit
526bab6164
|
@ -334,6 +334,9 @@ func New(bd BaseDeps) (*Agent, error) {
|
|||
cache: bd.Cache,
|
||||
}
|
||||
|
||||
// Initialize the UI Config
|
||||
a.uiConfig.Store(a.config.UIConfig)
|
||||
|
||||
a.serviceManager = NewServiceManager(&a)
|
||||
|
||||
// TODO: do this somewhere else, maybe move to newBaseDeps
|
||||
|
@ -3823,3 +3826,14 @@ func defaultIfEmpty(val, defaultVal string) string {
|
|||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
// getUIConfig is the canonical way to read the value of the UIConfig at
|
||||
// runtime. It is thread safe and returns the most recent configuration which
|
||||
// may have changed since the agent started due to config reload.
|
||||
func (a *Agent) getUIConfig() config.UIConfig {
|
||||
if cfg, ok := a.uiConfig.Load().(config.UIConfig); ok {
|
||||
return cfg
|
||||
}
|
||||
// Shouldn't happen but be defensive
|
||||
return config.UIConfig{}
|
||||
}
|
||||
|
|
|
@ -3503,6 +3503,36 @@ func TestAgent_ReloadConfigTLSConfigFailure(t *testing.T) {
|
|||
require.Len(t, tlsConf.RootCAs.Subjects(), 1)
|
||||
}
|
||||
|
||||
func TestAgent_ReloadConfigUIConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
dataDir := testutil.TempDir(t, "agent") // we manage the data dir
|
||||
hcl := `
|
||||
data_dir = "` + dataDir + `"
|
||||
ui_config {
|
||||
enabled = true // note that this is _not_ reloadable
|
||||
metrics_provider = "foo"
|
||||
}
|
||||
`
|
||||
a := NewTestAgent(t, hcl)
|
||||
defer a.Shutdown()
|
||||
|
||||
uiCfg := a.getUIConfig()
|
||||
require.Equal(t, "foo", uiCfg.MetricsProvider)
|
||||
|
||||
hcl = `
|
||||
data_dir = "` + dataDir + `"
|
||||
ui_config {
|
||||
enabled = true
|
||||
metrics_provider = "bar"
|
||||
}
|
||||
`
|
||||
c := TestConfig(testutil.Logger(t), config.FileSource{Name: t.Name(), Format: "hcl", Data: hcl})
|
||||
require.NoError(t, a.reloadConfigInternal(c))
|
||||
|
||||
uiCfg = a.getUIConfig()
|
||||
require.Equal(t, "bar", uiCfg.MetricsProvider)
|
||||
}
|
||||
|
||||
func TestAgent_consulConfig_AutoEncryptAllowTLS(t *testing.T) {
|
||||
t.Parallel()
|
||||
dataDir := testutil.TempDir(t, "agent") // we manage the data dir
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
@ -797,6 +798,26 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
|
|||
return RuntimeConfig{}, fmt.Errorf("serf_wan_allowed_cidrs: %s", err)
|
||||
}
|
||||
|
||||
// Handle Deprecated UI config fields
|
||||
if c.UI != nil {
|
||||
b.warn("The 'ui' field is deprecated. Use the 'ui_config.enabled' field instead.")
|
||||
if c.UIConfig.Enabled == nil {
|
||||
c.UIConfig.Enabled = c.UI
|
||||
}
|
||||
}
|
||||
if c.UIDir != nil {
|
||||
b.warn("The 'ui_dir' field is deprecated. Use the 'ui_config.dir' field instead.")
|
||||
if c.UIConfig.Dir == nil {
|
||||
c.UIConfig.Dir = c.UIDir
|
||||
}
|
||||
}
|
||||
if c.UIContentPath != nil {
|
||||
b.warn("The 'ui_content_path' field is deprecated. Use the 'ui_config.content_path' field instead.")
|
||||
if c.UIConfig.ContentPath == nil {
|
||||
c.UIConfig.ContentPath = c.UIContentPath
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// build runtime config
|
||||
//
|
||||
|
@ -981,19 +1002,17 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
|
|||
EnableDebug: b.boolVal(c.EnableDebug),
|
||||
EnableRemoteScriptChecks: enableRemoteScriptChecks,
|
||||
EnableLocalScriptChecks: enableLocalScriptChecks,
|
||||
|
||||
EnableUI: b.boolVal(c.UI),
|
||||
EncryptKey: b.stringVal(c.EncryptKey),
|
||||
EncryptVerifyIncoming: b.boolVal(c.EncryptVerifyIncoming),
|
||||
EncryptVerifyOutgoing: b.boolVal(c.EncryptVerifyOutgoing),
|
||||
GRPCPort: grpcPort,
|
||||
GRPCAddrs: grpcAddrs,
|
||||
HTTPMaxConnsPerClient: b.intVal(c.Limits.HTTPMaxConnsPerClient),
|
||||
HTTPSHandshakeTimeout: b.durationVal("limits.https_handshake_timeout", c.Limits.HTTPSHandshakeTimeout),
|
||||
KeyFile: b.stringVal(c.KeyFile),
|
||||
KVMaxValueSize: b.uint64Val(c.Limits.KVMaxValueSize),
|
||||
LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
|
||||
LeaveOnTerm: leaveOnTerm,
|
||||
EncryptKey: b.stringVal(c.EncryptKey),
|
||||
EncryptVerifyIncoming: b.boolVal(c.EncryptVerifyIncoming),
|
||||
EncryptVerifyOutgoing: b.boolVal(c.EncryptVerifyOutgoing),
|
||||
GRPCPort: grpcPort,
|
||||
GRPCAddrs: grpcAddrs,
|
||||
HTTPMaxConnsPerClient: b.intVal(c.Limits.HTTPMaxConnsPerClient),
|
||||
HTTPSHandshakeTimeout: b.durationVal("limits.https_handshake_timeout", c.Limits.HTTPSHandshakeTimeout),
|
||||
KeyFile: b.stringVal(c.KeyFile),
|
||||
KVMaxValueSize: b.uint64Val(c.Limits.KVMaxValueSize),
|
||||
LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
|
||||
LeaveOnTerm: leaveOnTerm,
|
||||
Logging: logging.Config{
|
||||
LogLevel: b.stringVal(c.LogLevel),
|
||||
LogJSON: b.boolVal(c.LogJSON),
|
||||
|
@ -1058,8 +1077,7 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
|
|||
TaggedAddresses: c.TaggedAddresses,
|
||||
TranslateWANAddrs: b.boolVal(c.TranslateWANAddrs),
|
||||
TxnMaxReqLen: b.uint64Val(c.Limits.TxnMaxReqLen),
|
||||
UIDir: b.stringVal(c.UIDir),
|
||||
UIContentPath: UIPathBuilder(b.stringVal(c.UIContentPath)),
|
||||
UIConfig: b.uiConfigVal(c.UIConfig),
|
||||
UnixSocketGroup: b.stringVal(c.UnixSocket.Group),
|
||||
UnixSocketMode: b.stringVal(c.UnixSocket.Mode),
|
||||
UnixSocketUser: b.stringVal(c.UnixSocket.User),
|
||||
|
@ -1094,7 +1112,8 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
|
|||
// Validate performs semantic validation of the runtime configuration.
|
||||
func (b *Builder) Validate(rt RuntimeConfig) error {
|
||||
// reDatacenter defines a regexp for a valid datacenter name
|
||||
var reDatacenter = regexp.MustCompile("^[a-z0-9_-]+$")
|
||||
var reBasicName = regexp.MustCompile("^[a-z0-9_-]+$")
|
||||
var reDatacenter = reBasicName
|
||||
|
||||
// validContentPath defines a regexp for a valid content path name.
|
||||
var validContentPath = regexp.MustCompile(`^[A-Za-z0-9/_-]+$`)
|
||||
|
@ -1113,12 +1132,50 @@ func (b *Builder) Validate(rt RuntimeConfig) error {
|
|||
return fmt.Errorf("data_dir cannot be empty")
|
||||
}
|
||||
|
||||
if !validContentPath.MatchString(rt.UIContentPath) {
|
||||
return fmt.Errorf("ui-content-path can only contain alphanumeric, -, _, or /. received: %s", rt.UIContentPath)
|
||||
if !validContentPath.MatchString(rt.UIConfig.ContentPath) {
|
||||
return fmt.Errorf("ui-content-path can only contain alphanumeric, -, _, or /. received: %q", rt.UIConfig.ContentPath)
|
||||
}
|
||||
|
||||
if hasVersion.MatchString(rt.UIContentPath) {
|
||||
return fmt.Errorf("ui-content-path cannot have 'v[0-9]'. received: %s", rt.UIContentPath)
|
||||
if hasVersion.MatchString(rt.UIConfig.ContentPath) {
|
||||
return fmt.Errorf("ui-content-path cannot have 'v[0-9]'. received: %q", rt.UIConfig.ContentPath)
|
||||
}
|
||||
|
||||
if rt.UIConfig.MetricsProvider != "" &&
|
||||
!reBasicName.MatchString(rt.UIConfig.MetricsProvider) {
|
||||
return fmt.Errorf("ui_config.metrics_provider can only contain lowercase "+
|
||||
"alphanumeric or _ characters. received: %q", rt.UIConfig.MetricsProvider)
|
||||
}
|
||||
if rt.UIConfig.MetricsProviderOptionsJSON != "" {
|
||||
// Attempt to parse the JSON to ensure it's valid, parsing into a map
|
||||
// ensures we get an object.
|
||||
var dummyMap map[string]interface{}
|
||||
err := json.Unmarshal([]byte(rt.UIConfig.MetricsProviderOptionsJSON),
|
||||
&dummyMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ui_config.metrics_provider_options_json must be empty "+
|
||||
"or a string containing a valid JSON object. received: %q",
|
||||
rt.UIConfig.MetricsProviderOptionsJSON)
|
||||
}
|
||||
}
|
||||
if rt.UIConfig.MetricsProxy.BaseURL != "" {
|
||||
u, err := url.Parse(rt.UIConfig.MetricsProxy.BaseURL)
|
||||
if err != nil || !(u.Scheme == "http" || u.Scheme == "https") {
|
||||
return fmt.Errorf("ui_config.metrics_proxy.base_url must be a valid http"+
|
||||
" or https URL. received: %q",
|
||||
rt.UIConfig.MetricsProxy.BaseURL)
|
||||
}
|
||||
}
|
||||
for k, v := range rt.UIConfig.DashboardURLTemplates {
|
||||
if !reBasicName.MatchString(k) {
|
||||
return fmt.Errorf("ui_config.dashboard_url_templates key names can only "+
|
||||
"contain lowercase alphanumeric or _ characters. received: %q", k)
|
||||
}
|
||||
u, err := url.Parse(v)
|
||||
if err != nil || !(u.Scheme == "http" || u.Scheme == "https") {
|
||||
return fmt.Errorf("ui_config.dashboard_url_templates values must be a"+
|
||||
" valid http or https URL. received: %q",
|
||||
rt.UIConfig.MetricsProxy.BaseURL)
|
||||
}
|
||||
}
|
||||
|
||||
if !rt.DevMode {
|
||||
|
@ -1194,11 +1251,11 @@ func (b *Builder) Validate(rt RuntimeConfig) error {
|
|||
return fmt.Errorf("acl_datacenter cannot be %q. Please use only [a-z0-9-_]", rt.ACLDatacenter)
|
||||
}
|
||||
// In DevMode, UI is enabled by default, so to enable rt.UIDir, don't perform this check
|
||||
if !rt.DevMode && rt.EnableUI && rt.UIDir != "" {
|
||||
if !rt.DevMode && rt.UIConfig.Enabled && rt.UIConfig.Dir != "" {
|
||||
return fmt.Errorf(
|
||||
"Both the ui and ui-dir flags were specified, please provide only one.\n" +
|
||||
"If trying to use your own web UI resources, use the ui-dir flag.\n" +
|
||||
"The web UI is included in the binary so use ui to enable it")
|
||||
"Both the ui_config.enabled and ui_config.dir (or -ui and -ui-dir) were specified, please provide only one.\n" +
|
||||
"If trying to use your own web UI resources, use ui_config.dir or the -ui-dir flag.\n" +
|
||||
"The web UI is included in the binary so use ui_config.enabled or the -ui flag to enable it")
|
||||
}
|
||||
if rt.DNSUDPAnswerLimit < 0 {
|
||||
return fmt.Errorf("dns_config.udp_answer_limit cannot be %d. Must be greater than or equal to zero", rt.DNSUDPAnswerLimit)
|
||||
|
@ -1647,6 +1704,35 @@ func (b *Builder) serviceConnectVal(v *ServiceConnect) *structs.ServiceConnect {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *Builder) uiConfigVal(v RawUIConfig) UIConfig {
|
||||
return UIConfig{
|
||||
Enabled: b.boolVal(v.Enabled),
|
||||
Dir: b.stringVal(v.Dir),
|
||||
ContentPath: UIPathBuilder(b.stringVal(v.ContentPath)),
|
||||
MetricsProvider: b.stringVal(v.MetricsProvider),
|
||||
MetricsProviderFiles: v.MetricsProviderFiles,
|
||||
MetricsProviderOptionsJSON: b.stringVal(v.MetricsProviderOptionsJSON),
|
||||
MetricsProxy: b.uiMetricsProxyVal(v.MetricsProxy),
|
||||
DashboardURLTemplates: v.DashboardURLTemplates,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Builder) uiMetricsProxyVal(v RawUIMetricsProxy) UIMetricsProxy {
|
||||
var hdrs []UIMetricsProxyAddHeader
|
||||
|
||||
for _, hdr := range v.AddHeaders {
|
||||
hdrs = append(hdrs, UIMetricsProxyAddHeader{
|
||||
Name: b.stringVal(hdr.Name),
|
||||
Value: b.stringVal(hdr.Value),
|
||||
})
|
||||
}
|
||||
|
||||
return UIMetricsProxy{
|
||||
BaseURL: b.stringVal(v.BaseURL),
|
||||
AddHeaders: hdrs,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Builder) boolValWithDefault(v *bool, defaultVal bool) bool {
|
||||
if v == nil {
|
||||
return defaultVal
|
||||
|
|
|
@ -133,123 +133,129 @@ type Config struct {
|
|||
// DEPRECATED (ACL-Legacy-Compat) - moved into the "acl.tokens" stanza
|
||||
ACLTTL *string `json:"acl_ttl,omitempty" hcl:"acl_ttl" mapstructure:"acl_ttl"`
|
||||
// DEPRECATED (ACL-Legacy-Compat) - moved into the "acl.tokens" stanza
|
||||
ACLToken *string `json:"acl_token,omitempty" hcl:"acl_token" mapstructure:"acl_token"`
|
||||
ACL ACL `json:"acl,omitempty" hcl:"acl" mapstructure:"acl"`
|
||||
Addresses Addresses `json:"addresses,omitempty" hcl:"addresses" mapstructure:"addresses"`
|
||||
AdvertiseAddrLAN *string `json:"advertise_addr,omitempty" hcl:"advertise_addr" mapstructure:"advertise_addr"`
|
||||
AdvertiseAddrLANIPv4 *string `json:"advertise_addr_ipv4,omitempty" hcl:"advertise_addr_ipv4" mapstructure:"advertise_addr_ipv4"`
|
||||
AdvertiseAddrLANIPv6 *string `json:"advertise_addr_ipv6,omitempty" hcl:"advertise_addr_ipv6" mapstructure:"advertise_addr_ipv6"`
|
||||
AdvertiseAddrWAN *string `json:"advertise_addr_wan,omitempty" hcl:"advertise_addr_wan" mapstructure:"advertise_addr_wan"`
|
||||
AdvertiseAddrWANIPv4 *string `json:"advertise_addr_wan_ipv4,omitempty" hcl:"advertise_addr_wan_ipv4" mapstructure:"advertise_addr_wan_ipv4"`
|
||||
AdvertiseAddrWANIPv6 *string `json:"advertise_addr_wan_ipv6,omitempty" hcl:"advertise_addr_wan_ipv6" mapstructure:"advertise_addr_ipv6"`
|
||||
AutoConfig AutoConfigRaw `json:"auto_config,omitempty" hcl:"auto_config" mapstructure:"auto_config"`
|
||||
Autopilot Autopilot `json:"autopilot,omitempty" hcl:"autopilot" mapstructure:"autopilot"`
|
||||
BindAddr *string `json:"bind_addr,omitempty" hcl:"bind_addr" mapstructure:"bind_addr"`
|
||||
Bootstrap *bool `json:"bootstrap,omitempty" hcl:"bootstrap" mapstructure:"bootstrap"`
|
||||
BootstrapExpect *int `json:"bootstrap_expect,omitempty" hcl:"bootstrap_expect" mapstructure:"bootstrap_expect"`
|
||||
Cache Cache `json:"cache,omitempty" hcl:"cache" mapstructure:"cache"`
|
||||
CAFile *string `json:"ca_file,omitempty" hcl:"ca_file" mapstructure:"ca_file"`
|
||||
CAPath *string `json:"ca_path,omitempty" hcl:"ca_path" mapstructure:"ca_path"`
|
||||
CertFile *string `json:"cert_file,omitempty" hcl:"cert_file" mapstructure:"cert_file"`
|
||||
Check *CheckDefinition `json:"check,omitempty" hcl:"check" mapstructure:"check"` // needs to be a pointer to avoid partial merges
|
||||
CheckOutputMaxSize *int `json:"check_output_max_size,omitempty" hcl:"check_output_max_size" mapstructure:"check_output_max_size"`
|
||||
CheckUpdateInterval *string `json:"check_update_interval,omitempty" hcl:"check_update_interval" mapstructure:"check_update_interval"`
|
||||
Checks []CheckDefinition `json:"checks,omitempty" hcl:"checks" mapstructure:"checks"`
|
||||
ClientAddr *string `json:"client_addr,omitempty" hcl:"client_addr" mapstructure:"client_addr"`
|
||||
ConfigEntries ConfigEntries `json:"config_entries,omitempty" hcl:"config_entries" mapstructure:"config_entries"`
|
||||
AutoEncrypt AutoEncrypt `json:"auto_encrypt,omitempty" hcl:"auto_encrypt" mapstructure:"auto_encrypt"`
|
||||
Connect Connect `json:"connect,omitempty" hcl:"connect" mapstructure:"connect"`
|
||||
DNS DNS `json:"dns_config,omitempty" hcl:"dns_config" mapstructure:"dns_config"`
|
||||
DNSDomain *string `json:"domain,omitempty" hcl:"domain" mapstructure:"domain"`
|
||||
DNSAltDomain *string `json:"alt_domain,omitempty" hcl:"alt_domain" mapstructure:"alt_domain"`
|
||||
DNSRecursors []string `json:"recursors,omitempty" hcl:"recursors" mapstructure:"recursors"`
|
||||
DataDir *string `json:"data_dir,omitempty" hcl:"data_dir" mapstructure:"data_dir"`
|
||||
Datacenter *string `json:"datacenter,omitempty" hcl:"datacenter" mapstructure:"datacenter"`
|
||||
DefaultQueryTime *string `json:"default_query_time,omitempty" hcl:"default_query_time" mapstructure:"default_query_time"`
|
||||
DisableAnonymousSignature *bool `json:"disable_anonymous_signature,omitempty" hcl:"disable_anonymous_signature" mapstructure:"disable_anonymous_signature"`
|
||||
DisableCoordinates *bool `json:"disable_coordinates,omitempty" hcl:"disable_coordinates" mapstructure:"disable_coordinates"`
|
||||
DisableHostNodeID *bool `json:"disable_host_node_id,omitempty" hcl:"disable_host_node_id" mapstructure:"disable_host_node_id"`
|
||||
DisableHTTPUnprintableCharFilter *bool `json:"disable_http_unprintable_char_filter,omitempty" hcl:"disable_http_unprintable_char_filter" mapstructure:"disable_http_unprintable_char_filter"`
|
||||
DisableKeyringFile *bool `json:"disable_keyring_file,omitempty" hcl:"disable_keyring_file" mapstructure:"disable_keyring_file"`
|
||||
DisableRemoteExec *bool `json:"disable_remote_exec,omitempty" hcl:"disable_remote_exec" mapstructure:"disable_remote_exec"`
|
||||
DisableUpdateCheck *bool `json:"disable_update_check,omitempty" hcl:"disable_update_check" mapstructure:"disable_update_check"`
|
||||
DiscardCheckOutput *bool `json:"discard_check_output" hcl:"discard_check_output" mapstructure:"discard_check_output"`
|
||||
DiscoveryMaxStale *string `json:"discovery_max_stale" hcl:"discovery_max_stale" mapstructure:"discovery_max_stale"`
|
||||
EnableACLReplication *bool `json:"enable_acl_replication,omitempty" hcl:"enable_acl_replication" mapstructure:"enable_acl_replication"`
|
||||
EnableAgentTLSForChecks *bool `json:"enable_agent_tls_for_checks,omitempty" hcl:"enable_agent_tls_for_checks" mapstructure:"enable_agent_tls_for_checks"`
|
||||
EnableCentralServiceConfig *bool `json:"enable_central_service_config,omitempty" hcl:"enable_central_service_config" mapstructure:"enable_central_service_config"`
|
||||
EnableDebug *bool `json:"enable_debug,omitempty" hcl:"enable_debug" mapstructure:"enable_debug"`
|
||||
EnableScriptChecks *bool `json:"enable_script_checks,omitempty" hcl:"enable_script_checks" mapstructure:"enable_script_checks"`
|
||||
EnableLocalScriptChecks *bool `json:"enable_local_script_checks,omitempty" hcl:"enable_local_script_checks" mapstructure:"enable_local_script_checks"`
|
||||
EnableSyslog *bool `json:"enable_syslog,omitempty" hcl:"enable_syslog" mapstructure:"enable_syslog"`
|
||||
EncryptKey *string `json:"encrypt,omitempty" hcl:"encrypt" mapstructure:"encrypt"`
|
||||
EncryptVerifyIncoming *bool `json:"encrypt_verify_incoming,omitempty" hcl:"encrypt_verify_incoming" mapstructure:"encrypt_verify_incoming"`
|
||||
EncryptVerifyOutgoing *bool `json:"encrypt_verify_outgoing,omitempty" hcl:"encrypt_verify_outgoing" mapstructure:"encrypt_verify_outgoing"`
|
||||
GossipLAN GossipLANConfig `json:"gossip_lan,omitempty" hcl:"gossip_lan" mapstructure:"gossip_lan"`
|
||||
GossipWAN GossipWANConfig `json:"gossip_wan,omitempty" hcl:"gossip_wan" mapstructure:"gossip_wan"`
|
||||
HTTPConfig HTTPConfig `json:"http_config,omitempty" hcl:"http_config" mapstructure:"http_config"`
|
||||
KeyFile *string `json:"key_file,omitempty" hcl:"key_file" mapstructure:"key_file"`
|
||||
LeaveOnTerm *bool `json:"leave_on_terminate,omitempty" hcl:"leave_on_terminate" mapstructure:"leave_on_terminate"`
|
||||
Limits Limits `json:"limits,omitempty" hcl:"limits" mapstructure:"limits"`
|
||||
LogLevel *string `json:"log_level,omitempty" hcl:"log_level" mapstructure:"log_level"`
|
||||
LogJSON *bool `json:"log_json,omitempty" hcl:"log_json" mapstructure:"log_json"`
|
||||
LogFile *string `json:"log_file,omitempty" hcl:"log_file" mapstructure:"log_file"`
|
||||
LogRotateDuration *string `json:"log_rotate_duration,omitempty" hcl:"log_rotate_duration" mapstructure:"log_rotate_duration"`
|
||||
LogRotateBytes *int `json:"log_rotate_bytes,omitempty" hcl:"log_rotate_bytes" mapstructure:"log_rotate_bytes"`
|
||||
LogRotateMaxFiles *int `json:"log_rotate_max_files,omitempty" hcl:"log_rotate_max_files" mapstructure:"log_rotate_max_files"`
|
||||
MaxQueryTime *string `json:"max_query_time,omitempty" hcl:"max_query_time" mapstructure:"max_query_time"`
|
||||
NodeID *string `json:"node_id,omitempty" hcl:"node_id" mapstructure:"node_id"`
|
||||
NodeMeta map[string]string `json:"node_meta,omitempty" hcl:"node_meta" mapstructure:"node_meta"`
|
||||
NodeName *string `json:"node_name,omitempty" hcl:"node_name" mapstructure:"node_name"`
|
||||
Performance Performance `json:"performance,omitempty" hcl:"performance" mapstructure:"performance"`
|
||||
PidFile *string `json:"pid_file,omitempty" hcl:"pid_file" mapstructure:"pid_file"`
|
||||
Ports Ports `json:"ports,omitempty" hcl:"ports" mapstructure:"ports"`
|
||||
PrimaryDatacenter *string `json:"primary_datacenter,omitempty" hcl:"primary_datacenter" mapstructure:"primary_datacenter"`
|
||||
PrimaryGateways []string `json:"primary_gateways" hcl:"primary_gateways" mapstructure:"primary_gateways"`
|
||||
PrimaryGatewaysInterval *string `json:"primary_gateways_interval,omitempty" hcl:"primary_gateways_interval" mapstructure:"primary_gateways_interval"`
|
||||
RPCProtocol *int `json:"protocol,omitempty" hcl:"protocol" mapstructure:"protocol"`
|
||||
RaftProtocol *int `json:"raft_protocol,omitempty" hcl:"raft_protocol" mapstructure:"raft_protocol"`
|
||||
RaftSnapshotThreshold *int `json:"raft_snapshot_threshold,omitempty" hcl:"raft_snapshot_threshold" mapstructure:"raft_snapshot_threshold"`
|
||||
RaftSnapshotInterval *string `json:"raft_snapshot_interval,omitempty" hcl:"raft_snapshot_interval" mapstructure:"raft_snapshot_interval"`
|
||||
RaftTrailingLogs *int `json:"raft_trailing_logs,omitempty" hcl:"raft_trailing_logs" mapstructure:"raft_trailing_logs"`
|
||||
ReconnectTimeoutLAN *string `json:"reconnect_timeout,omitempty" hcl:"reconnect_timeout" mapstructure:"reconnect_timeout"`
|
||||
ReconnectTimeoutWAN *string `json:"reconnect_timeout_wan,omitempty" hcl:"reconnect_timeout_wan" mapstructure:"reconnect_timeout_wan"`
|
||||
RejoinAfterLeave *bool `json:"rejoin_after_leave,omitempty" hcl:"rejoin_after_leave" mapstructure:"rejoin_after_leave"`
|
||||
RetryJoinIntervalLAN *string `json:"retry_interval,omitempty" hcl:"retry_interval" mapstructure:"retry_interval"`
|
||||
RetryJoinIntervalWAN *string `json:"retry_interval_wan,omitempty" hcl:"retry_interval_wan" mapstructure:"retry_interval_wan"`
|
||||
RetryJoinLAN []string `json:"retry_join,omitempty" hcl:"retry_join" mapstructure:"retry_join"`
|
||||
RetryJoinMaxAttemptsLAN *int `json:"retry_max,omitempty" hcl:"retry_max" mapstructure:"retry_max"`
|
||||
RetryJoinMaxAttemptsWAN *int `json:"retry_max_wan,omitempty" hcl:"retry_max_wan" mapstructure:"retry_max_wan"`
|
||||
RetryJoinWAN []string `json:"retry_join_wan,omitempty" hcl:"retry_join_wan" mapstructure:"retry_join_wan"`
|
||||
SerfAllowedCIDRsLAN []string `json:"serf_lan_allowed_cidrs,omitempty" hcl:"serf_lan_allowed_cidrs" mapstructure:"serf_lan_allowed_cidrs"`
|
||||
SerfAllowedCIDRsWAN []string `json:"serf_wan_allowed_cidrs,omitempty" hcl:"serf_wan_allowed_cidrs" mapstructure:"serf_wan_allowed_cidrs"`
|
||||
SerfBindAddrLAN *string `json:"serf_lan,omitempty" hcl:"serf_lan" mapstructure:"serf_lan"`
|
||||
SerfBindAddrWAN *string `json:"serf_wan,omitempty" hcl:"serf_wan" mapstructure:"serf_wan"`
|
||||
ServerMode *bool `json:"server,omitempty" hcl:"server" mapstructure:"server"`
|
||||
ServerName *string `json:"server_name,omitempty" hcl:"server_name" mapstructure:"server_name"`
|
||||
Service *ServiceDefinition `json:"service,omitempty" hcl:"service" mapstructure:"service"`
|
||||
Services []ServiceDefinition `json:"services,omitempty" hcl:"services" mapstructure:"services"`
|
||||
SessionTTLMin *string `json:"session_ttl_min,omitempty" hcl:"session_ttl_min" mapstructure:"session_ttl_min"`
|
||||
SkipLeaveOnInt *bool `json:"skip_leave_on_interrupt,omitempty" hcl:"skip_leave_on_interrupt" mapstructure:"skip_leave_on_interrupt"`
|
||||
StartJoinAddrsLAN []string `json:"start_join,omitempty" hcl:"start_join" mapstructure:"start_join"`
|
||||
StartJoinAddrsWAN []string `json:"start_join_wan,omitempty" hcl:"start_join_wan" mapstructure:"start_join_wan"`
|
||||
SyslogFacility *string `json:"syslog_facility,omitempty" hcl:"syslog_facility" mapstructure:"syslog_facility"`
|
||||
TLSCipherSuites *string `json:"tls_cipher_suites,omitempty" hcl:"tls_cipher_suites" mapstructure:"tls_cipher_suites"`
|
||||
TLSMinVersion *string `json:"tls_min_version,omitempty" hcl:"tls_min_version" mapstructure:"tls_min_version"`
|
||||
TLSPreferServerCipherSuites *bool `json:"tls_prefer_server_cipher_suites,omitempty" hcl:"tls_prefer_server_cipher_suites" mapstructure:"tls_prefer_server_cipher_suites"`
|
||||
TaggedAddresses map[string]string `json:"tagged_addresses,omitempty" hcl:"tagged_addresses" mapstructure:"tagged_addresses"`
|
||||
Telemetry Telemetry `json:"telemetry,omitempty" hcl:"telemetry" mapstructure:"telemetry"`
|
||||
TranslateWANAddrs *bool `json:"translate_wan_addrs,omitempty" hcl:"translate_wan_addrs" mapstructure:"translate_wan_addrs"`
|
||||
UI *bool `json:"ui,omitempty" hcl:"ui" mapstructure:"ui"`
|
||||
UIContentPath *string `json:"ui_content_path,omitempty" hcl:"ui_content_path" mapstructure:"ui_content_path"`
|
||||
UIDir *string `json:"ui_dir,omitempty" hcl:"ui_dir" mapstructure:"ui_dir"`
|
||||
UnixSocket UnixSocket `json:"unix_sockets,omitempty" hcl:"unix_sockets" mapstructure:"unix_sockets"`
|
||||
VerifyIncoming *bool `json:"verify_incoming,omitempty" hcl:"verify_incoming" mapstructure:"verify_incoming"`
|
||||
VerifyIncomingHTTPS *bool `json:"verify_incoming_https,omitempty" hcl:"verify_incoming_https" mapstructure:"verify_incoming_https"`
|
||||
VerifyIncomingRPC *bool `json:"verify_incoming_rpc,omitempty" hcl:"verify_incoming_rpc" mapstructure:"verify_incoming_rpc"`
|
||||
VerifyOutgoing *bool `json:"verify_outgoing,omitempty" hcl:"verify_outgoing" mapstructure:"verify_outgoing"`
|
||||
VerifyServerHostname *bool `json:"verify_server_hostname,omitempty" hcl:"verify_server_hostname" mapstructure:"verify_server_hostname"`
|
||||
Watches []map[string]interface{} `json:"watches,omitempty" hcl:"watches" mapstructure:"watches"`
|
||||
ACLToken *string `json:"acl_token,omitempty" hcl:"acl_token" mapstructure:"acl_token"`
|
||||
ACL ACL `json:"acl,omitempty" hcl:"acl" mapstructure:"acl"`
|
||||
Addresses Addresses `json:"addresses,omitempty" hcl:"addresses" mapstructure:"addresses"`
|
||||
AdvertiseAddrLAN *string `json:"advertise_addr,omitempty" hcl:"advertise_addr" mapstructure:"advertise_addr"`
|
||||
AdvertiseAddrLANIPv4 *string `json:"advertise_addr_ipv4,omitempty" hcl:"advertise_addr_ipv4" mapstructure:"advertise_addr_ipv4"`
|
||||
AdvertiseAddrLANIPv6 *string `json:"advertise_addr_ipv6,omitempty" hcl:"advertise_addr_ipv6" mapstructure:"advertise_addr_ipv6"`
|
||||
AdvertiseAddrWAN *string `json:"advertise_addr_wan,omitempty" hcl:"advertise_addr_wan" mapstructure:"advertise_addr_wan"`
|
||||
AdvertiseAddrWANIPv4 *string `json:"advertise_addr_wan_ipv4,omitempty" hcl:"advertise_addr_wan_ipv4" mapstructure:"advertise_addr_wan_ipv4"`
|
||||
AdvertiseAddrWANIPv6 *string `json:"advertise_addr_wan_ipv6,omitempty" hcl:"advertise_addr_wan_ipv6" mapstructure:"advertise_addr_ipv6"`
|
||||
AutoConfig AutoConfigRaw `json:"auto_config,omitempty" hcl:"auto_config" mapstructure:"auto_config"`
|
||||
Autopilot Autopilot `json:"autopilot,omitempty" hcl:"autopilot" mapstructure:"autopilot"`
|
||||
BindAddr *string `json:"bind_addr,omitempty" hcl:"bind_addr" mapstructure:"bind_addr"`
|
||||
Bootstrap *bool `json:"bootstrap,omitempty" hcl:"bootstrap" mapstructure:"bootstrap"`
|
||||
BootstrapExpect *int `json:"bootstrap_expect,omitempty" hcl:"bootstrap_expect" mapstructure:"bootstrap_expect"`
|
||||
Cache Cache `json:"cache,omitempty" hcl:"cache" mapstructure:"cache"`
|
||||
CAFile *string `json:"ca_file,omitempty" hcl:"ca_file" mapstructure:"ca_file"`
|
||||
CAPath *string `json:"ca_path,omitempty" hcl:"ca_path" mapstructure:"ca_path"`
|
||||
CertFile *string `json:"cert_file,omitempty" hcl:"cert_file" mapstructure:"cert_file"`
|
||||
Check *CheckDefinition `json:"check,omitempty" hcl:"check" mapstructure:"check"` // needs to be a pointer to avoid partial merges
|
||||
CheckOutputMaxSize *int `json:"check_output_max_size,omitempty" hcl:"check_output_max_size" mapstructure:"check_output_max_size"`
|
||||
CheckUpdateInterval *string `json:"check_update_interval,omitempty" hcl:"check_update_interval" mapstructure:"check_update_interval"`
|
||||
Checks []CheckDefinition `json:"checks,omitempty" hcl:"checks" mapstructure:"checks"`
|
||||
ClientAddr *string `json:"client_addr,omitempty" hcl:"client_addr" mapstructure:"client_addr"`
|
||||
ConfigEntries ConfigEntries `json:"config_entries,omitempty" hcl:"config_entries" mapstructure:"config_entries"`
|
||||
AutoEncrypt AutoEncrypt `json:"auto_encrypt,omitempty" hcl:"auto_encrypt" mapstructure:"auto_encrypt"`
|
||||
Connect Connect `json:"connect,omitempty" hcl:"connect" mapstructure:"connect"`
|
||||
DNS DNS `json:"dns_config,omitempty" hcl:"dns_config" mapstructure:"dns_config"`
|
||||
DNSDomain *string `json:"domain,omitempty" hcl:"domain" mapstructure:"domain"`
|
||||
DNSAltDomain *string `json:"alt_domain,omitempty" hcl:"alt_domain" mapstructure:"alt_domain"`
|
||||
DNSRecursors []string `json:"recursors,omitempty" hcl:"recursors" mapstructure:"recursors"`
|
||||
DataDir *string `json:"data_dir,omitempty" hcl:"data_dir" mapstructure:"data_dir"`
|
||||
Datacenter *string `json:"datacenter,omitempty" hcl:"datacenter" mapstructure:"datacenter"`
|
||||
DefaultQueryTime *string `json:"default_query_time,omitempty" hcl:"default_query_time" mapstructure:"default_query_time"`
|
||||
DisableAnonymousSignature *bool `json:"disable_anonymous_signature,omitempty" hcl:"disable_anonymous_signature" mapstructure:"disable_anonymous_signature"`
|
||||
DisableCoordinates *bool `json:"disable_coordinates,omitempty" hcl:"disable_coordinates" mapstructure:"disable_coordinates"`
|
||||
DisableHostNodeID *bool `json:"disable_host_node_id,omitempty" hcl:"disable_host_node_id" mapstructure:"disable_host_node_id"`
|
||||
DisableHTTPUnprintableCharFilter *bool `json:"disable_http_unprintable_char_filter,omitempty" hcl:"disable_http_unprintable_char_filter" mapstructure:"disable_http_unprintable_char_filter"`
|
||||
DisableKeyringFile *bool `json:"disable_keyring_file,omitempty" hcl:"disable_keyring_file" mapstructure:"disable_keyring_file"`
|
||||
DisableRemoteExec *bool `json:"disable_remote_exec,omitempty" hcl:"disable_remote_exec" mapstructure:"disable_remote_exec"`
|
||||
DisableUpdateCheck *bool `json:"disable_update_check,omitempty" hcl:"disable_update_check" mapstructure:"disable_update_check"`
|
||||
DiscardCheckOutput *bool `json:"discard_check_output" hcl:"discard_check_output" mapstructure:"discard_check_output"`
|
||||
DiscoveryMaxStale *string `json:"discovery_max_stale" hcl:"discovery_max_stale" mapstructure:"discovery_max_stale"`
|
||||
EnableACLReplication *bool `json:"enable_acl_replication,omitempty" hcl:"enable_acl_replication" mapstructure:"enable_acl_replication"`
|
||||
EnableAgentTLSForChecks *bool `json:"enable_agent_tls_for_checks,omitempty" hcl:"enable_agent_tls_for_checks" mapstructure:"enable_agent_tls_for_checks"`
|
||||
EnableCentralServiceConfig *bool `json:"enable_central_service_config,omitempty" hcl:"enable_central_service_config" mapstructure:"enable_central_service_config"`
|
||||
EnableDebug *bool `json:"enable_debug,omitempty" hcl:"enable_debug" mapstructure:"enable_debug"`
|
||||
EnableScriptChecks *bool `json:"enable_script_checks,omitempty" hcl:"enable_script_checks" mapstructure:"enable_script_checks"`
|
||||
EnableLocalScriptChecks *bool `json:"enable_local_script_checks,omitempty" hcl:"enable_local_script_checks" mapstructure:"enable_local_script_checks"`
|
||||
EnableSyslog *bool `json:"enable_syslog,omitempty" hcl:"enable_syslog" mapstructure:"enable_syslog"`
|
||||
EncryptKey *string `json:"encrypt,omitempty" hcl:"encrypt" mapstructure:"encrypt"`
|
||||
EncryptVerifyIncoming *bool `json:"encrypt_verify_incoming,omitempty" hcl:"encrypt_verify_incoming" mapstructure:"encrypt_verify_incoming"`
|
||||
EncryptVerifyOutgoing *bool `json:"encrypt_verify_outgoing,omitempty" hcl:"encrypt_verify_outgoing" mapstructure:"encrypt_verify_outgoing"`
|
||||
GossipLAN GossipLANConfig `json:"gossip_lan,omitempty" hcl:"gossip_lan" mapstructure:"gossip_lan"`
|
||||
GossipWAN GossipWANConfig `json:"gossip_wan,omitempty" hcl:"gossip_wan" mapstructure:"gossip_wan"`
|
||||
HTTPConfig HTTPConfig `json:"http_config,omitempty" hcl:"http_config" mapstructure:"http_config"`
|
||||
KeyFile *string `json:"key_file,omitempty" hcl:"key_file" mapstructure:"key_file"`
|
||||
LeaveOnTerm *bool `json:"leave_on_terminate,omitempty" hcl:"leave_on_terminate" mapstructure:"leave_on_terminate"`
|
||||
Limits Limits `json:"limits,omitempty" hcl:"limits" mapstructure:"limits"`
|
||||
LogLevel *string `json:"log_level,omitempty" hcl:"log_level" mapstructure:"log_level"`
|
||||
LogJSON *bool `json:"log_json,omitempty" hcl:"log_json" mapstructure:"log_json"`
|
||||
LogFile *string `json:"log_file,omitempty" hcl:"log_file" mapstructure:"log_file"`
|
||||
LogRotateDuration *string `json:"log_rotate_duration,omitempty" hcl:"log_rotate_duration" mapstructure:"log_rotate_duration"`
|
||||
LogRotateBytes *int `json:"log_rotate_bytes,omitempty" hcl:"log_rotate_bytes" mapstructure:"log_rotate_bytes"`
|
||||
LogRotateMaxFiles *int `json:"log_rotate_max_files,omitempty" hcl:"log_rotate_max_files" mapstructure:"log_rotate_max_files"`
|
||||
MaxQueryTime *string `json:"max_query_time,omitempty" hcl:"max_query_time" mapstructure:"max_query_time"`
|
||||
NodeID *string `json:"node_id,omitempty" hcl:"node_id" mapstructure:"node_id"`
|
||||
NodeMeta map[string]string `json:"node_meta,omitempty" hcl:"node_meta" mapstructure:"node_meta"`
|
||||
NodeName *string `json:"node_name,omitempty" hcl:"node_name" mapstructure:"node_name"`
|
||||
Performance Performance `json:"performance,omitempty" hcl:"performance" mapstructure:"performance"`
|
||||
PidFile *string `json:"pid_file,omitempty" hcl:"pid_file" mapstructure:"pid_file"`
|
||||
Ports Ports `json:"ports,omitempty" hcl:"ports" mapstructure:"ports"`
|
||||
PrimaryDatacenter *string `json:"primary_datacenter,omitempty" hcl:"primary_datacenter" mapstructure:"primary_datacenter"`
|
||||
PrimaryGateways []string `json:"primary_gateways" hcl:"primary_gateways" mapstructure:"primary_gateways"`
|
||||
PrimaryGatewaysInterval *string `json:"primary_gateways_interval,omitempty" hcl:"primary_gateways_interval" mapstructure:"primary_gateways_interval"`
|
||||
RPCProtocol *int `json:"protocol,omitempty" hcl:"protocol" mapstructure:"protocol"`
|
||||
RaftProtocol *int `json:"raft_protocol,omitempty" hcl:"raft_protocol" mapstructure:"raft_protocol"`
|
||||
RaftSnapshotThreshold *int `json:"raft_snapshot_threshold,omitempty" hcl:"raft_snapshot_threshold" mapstructure:"raft_snapshot_threshold"`
|
||||
RaftSnapshotInterval *string `json:"raft_snapshot_interval,omitempty" hcl:"raft_snapshot_interval" mapstructure:"raft_snapshot_interval"`
|
||||
RaftTrailingLogs *int `json:"raft_trailing_logs,omitempty" hcl:"raft_trailing_logs" mapstructure:"raft_trailing_logs"`
|
||||
ReconnectTimeoutLAN *string `json:"reconnect_timeout,omitempty" hcl:"reconnect_timeout" mapstructure:"reconnect_timeout"`
|
||||
ReconnectTimeoutWAN *string `json:"reconnect_timeout_wan,omitempty" hcl:"reconnect_timeout_wan" mapstructure:"reconnect_timeout_wan"`
|
||||
RejoinAfterLeave *bool `json:"rejoin_after_leave,omitempty" hcl:"rejoin_after_leave" mapstructure:"rejoin_after_leave"`
|
||||
RetryJoinIntervalLAN *string `json:"retry_interval,omitempty" hcl:"retry_interval" mapstructure:"retry_interval"`
|
||||
RetryJoinIntervalWAN *string `json:"retry_interval_wan,omitempty" hcl:"retry_interval_wan" mapstructure:"retry_interval_wan"`
|
||||
RetryJoinLAN []string `json:"retry_join,omitempty" hcl:"retry_join" mapstructure:"retry_join"`
|
||||
RetryJoinMaxAttemptsLAN *int `json:"retry_max,omitempty" hcl:"retry_max" mapstructure:"retry_max"`
|
||||
RetryJoinMaxAttemptsWAN *int `json:"retry_max_wan,omitempty" hcl:"retry_max_wan" mapstructure:"retry_max_wan"`
|
||||
RetryJoinWAN []string `json:"retry_join_wan,omitempty" hcl:"retry_join_wan" mapstructure:"retry_join_wan"`
|
||||
SerfAllowedCIDRsLAN []string `json:"serf_lan_allowed_cidrs,omitempty" hcl:"serf_lan_allowed_cidrs" mapstructure:"serf_lan_allowed_cidrs"`
|
||||
SerfAllowedCIDRsWAN []string `json:"serf_wan_allowed_cidrs,omitempty" hcl:"serf_wan_allowed_cidrs" mapstructure:"serf_wan_allowed_cidrs"`
|
||||
SerfBindAddrLAN *string `json:"serf_lan,omitempty" hcl:"serf_lan" mapstructure:"serf_lan"`
|
||||
SerfBindAddrWAN *string `json:"serf_wan,omitempty" hcl:"serf_wan" mapstructure:"serf_wan"`
|
||||
ServerMode *bool `json:"server,omitempty" hcl:"server" mapstructure:"server"`
|
||||
ServerName *string `json:"server_name,omitempty" hcl:"server_name" mapstructure:"server_name"`
|
||||
Service *ServiceDefinition `json:"service,omitempty" hcl:"service" mapstructure:"service"`
|
||||
Services []ServiceDefinition `json:"services,omitempty" hcl:"services" mapstructure:"services"`
|
||||
SessionTTLMin *string `json:"session_ttl_min,omitempty" hcl:"session_ttl_min" mapstructure:"session_ttl_min"`
|
||||
SkipLeaveOnInt *bool `json:"skip_leave_on_interrupt,omitempty" hcl:"skip_leave_on_interrupt" mapstructure:"skip_leave_on_interrupt"`
|
||||
StartJoinAddrsLAN []string `json:"start_join,omitempty" hcl:"start_join" mapstructure:"start_join"`
|
||||
StartJoinAddrsWAN []string `json:"start_join_wan,omitempty" hcl:"start_join_wan" mapstructure:"start_join_wan"`
|
||||
SyslogFacility *string `json:"syslog_facility,omitempty" hcl:"syslog_facility" mapstructure:"syslog_facility"`
|
||||
TLSCipherSuites *string `json:"tls_cipher_suites,omitempty" hcl:"tls_cipher_suites" mapstructure:"tls_cipher_suites"`
|
||||
TLSMinVersion *string `json:"tls_min_version,omitempty" hcl:"tls_min_version" mapstructure:"tls_min_version"`
|
||||
TLSPreferServerCipherSuites *bool `json:"tls_prefer_server_cipher_suites,omitempty" hcl:"tls_prefer_server_cipher_suites" mapstructure:"tls_prefer_server_cipher_suites"`
|
||||
TaggedAddresses map[string]string `json:"tagged_addresses,omitempty" hcl:"tagged_addresses" mapstructure:"tagged_addresses"`
|
||||
Telemetry Telemetry `json:"telemetry,omitempty" hcl:"telemetry" mapstructure:"telemetry"`
|
||||
TranslateWANAddrs *bool `json:"translate_wan_addrs,omitempty" hcl:"translate_wan_addrs" mapstructure:"translate_wan_addrs"`
|
||||
|
||||
// DEPRECATED (ui-config) - moved to the ui_config stanza
|
||||
UI *bool `json:"ui,omitempty" hcl:"ui" mapstructure:"ui"`
|
||||
// DEPRECATED (ui-config) - moved to the ui_config stanza
|
||||
UIContentPath *string `json:"ui_content_path,omitempty" hcl:"ui_content_path" mapstructure:"ui_content_path"`
|
||||
// DEPRECATED (ui-config) - moved to the ui_config stanza
|
||||
UIDir *string `json:"ui_dir,omitempty" hcl:"ui_dir" mapstructure:"ui_dir"`
|
||||
UIConfig RawUIConfig `json:"ui_config,omitempty" hcl:"ui_config" mapstructure:"ui_config"`
|
||||
|
||||
UnixSocket UnixSocket `json:"unix_sockets,omitempty" hcl:"unix_sockets" mapstructure:"unix_sockets"`
|
||||
VerifyIncoming *bool `json:"verify_incoming,omitempty" hcl:"verify_incoming" mapstructure:"verify_incoming"`
|
||||
VerifyIncomingHTTPS *bool `json:"verify_incoming_https,omitempty" hcl:"verify_incoming_https" mapstructure:"verify_incoming_https"`
|
||||
VerifyIncomingRPC *bool `json:"verify_incoming_rpc,omitempty" hcl:"verify_incoming_rpc" mapstructure:"verify_incoming_rpc"`
|
||||
VerifyOutgoing *bool `json:"verify_outgoing,omitempty" hcl:"verify_outgoing" mapstructure:"verify_outgoing"`
|
||||
VerifyServerHostname *bool `json:"verify_server_hostname,omitempty" hcl:"verify_server_hostname" mapstructure:"verify_server_hostname"`
|
||||
Watches []map[string]interface{} `json:"watches,omitempty" hcl:"watches" mapstructure:"watches"`
|
||||
|
||||
// This isn't used by Consul but we've documented a feature where users
|
||||
// can deploy their snapshot agent configs alongside their Consul configs
|
||||
|
@ -769,3 +775,24 @@ type AutoConfigAuthorizerRaw struct {
|
|||
NotBeforeLeeway *string `json:"not_before_leeway,omitempty" hcl:"not_before_leeway" mapstructure:"not_before_leeway"`
|
||||
ClockSkewLeeway *string `json:"clock_skew_leeway,omitempty" hcl:"clock_skew_leeway" mapstructure:"clock_skew_leeway"`
|
||||
}
|
||||
|
||||
type RawUIConfig struct {
|
||||
Enabled *bool `json:"enabled,omitempty" hcl:"enabled" mapstructure:"enabled"`
|
||||
Dir *string `json:"dir,omitempty" hcl:"dir" mapstructure:"dir"`
|
||||
ContentPath *string `json:"content_path,omitempty" hcl:"content_path" mapstructure:"content_path"`
|
||||
MetricsProvider *string `json:"metrics_provider,omitempty" hcl:"metrics_provider" mapstructure:"metrics_provider"`
|
||||
MetricsProviderFiles []string `json:"metrics_provider_files,omitempty" hcl:"metrics_provider_files" mapstructure:"metrics_provider_files"`
|
||||
MetricsProviderOptionsJSON *string `json:"metrics_provider_options_json,omitempty" hcl:"metrics_provider_options_json" mapstructure:"metrics_provider_options_json"`
|
||||
MetricsProxy RawUIMetricsProxy `json:"metrics_proxy,omitempty" hcl:"metrics_proxy" mapstructure:"metrics_proxy"`
|
||||
DashboardURLTemplates map[string]string `json:"dashboard_url_templates" hcl:"dashboard_url_templates" mapstructure:"dashboard_url_templates"`
|
||||
}
|
||||
|
||||
type RawUIMetricsProxy struct {
|
||||
BaseURL *string `json:"base_url,omitempty" hcl:"base_url" mapstructure:"base_url"`
|
||||
AddHeaders []RawUIMetricsProxyAddHeader `json:"add_headers,omitempty" hcl:"add_headers" mapstructure:"add_headers"`
|
||||
}
|
||||
|
||||
type RawUIMetricsProxyAddHeader struct {
|
||||
Name *string `json:"name,omitempty" hcl:"name" mapstructure:"name"`
|
||||
Value *string `json:"value,omitempty" hcl:"value" mapstructure:"value"`
|
||||
}
|
||||
|
|
|
@ -139,7 +139,9 @@ func DevSource() Source {
|
|||
disable_anonymous_signature = true
|
||||
disable_keyring_file = true
|
||||
enable_debug = true
|
||||
ui = true
|
||||
ui_config {
|
||||
enabled = true
|
||||
}
|
||||
log_level = "DEBUG"
|
||||
server = true
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ func AddFlags(fs *flag.FlagSet, f *BuilderOpts) {
|
|||
add(&f.Config.Ports.SerfWAN, "serf-wan-port", "Sets the Serf WAN port to listen on.")
|
||||
add(&f.Config.ServerMode, "server", "Switches agent to server mode.")
|
||||
add(&f.Config.EnableSyslog, "syslog", "Enables logging to syslog.")
|
||||
add(&f.Config.UI, "ui", "Enables the built-in static web UI server.")
|
||||
add(&f.Config.UIContentPath, "ui-content-path", "Sets the external UI path to a string. Defaults to: /ui/ ")
|
||||
add(&f.Config.UIDir, "ui-dir", "Path to directory containing the web UI resources.")
|
||||
add(&f.Config.UIConfig.Enabled, "ui", "Enables the built-in static web UI server.")
|
||||
add(&f.Config.UIConfig.ContentPath, "ui-content-path", "Sets the external UI path to a string. Defaults to: /ui/ ")
|
||||
add(&f.Config.UIConfig.Dir, "ui-dir", "Path to directory containing the web UI resources.")
|
||||
add(&f.HCL, "hcl", "hcl config fragment. Can be specified multiple times.")
|
||||
}
|
||||
|
|
|
@ -694,13 +694,6 @@ type RuntimeConfig struct {
|
|||
// flag: -enable-script-checks
|
||||
EnableRemoteScriptChecks bool
|
||||
|
||||
// EnableUI enables the statically-compiled assets for the Consul web UI and
|
||||
// serves them at the default /ui/ endpoint automatically.
|
||||
//
|
||||
// hcl: enable_ui = (true|false)
|
||||
// flag: -ui
|
||||
EnableUI bool
|
||||
|
||||
// EncryptKey contains the encryption key to use for the Serf communication.
|
||||
//
|
||||
// hcl: encrypt = string
|
||||
|
@ -1411,16 +1404,18 @@ type RuntimeConfig struct {
|
|||
// hcl: limits { txn_max_req_len = uint64 }
|
||||
TxnMaxReqLen uint64
|
||||
|
||||
// UIDir is the directory containing the Web UI resources.
|
||||
// If provided, the UI endpoints will be enabled.
|
||||
// UIConfig holds various runtime options that control both the agent's
|
||||
// behavior while serving the UI (e.g. whether it's enabled, what path it's
|
||||
// mounted on) as well as options that enable or disable features within the
|
||||
// UI.
|
||||
//
|
||||
// hcl: ui_dir = string
|
||||
// flag: -ui-dir string
|
||||
UIDir string
|
||||
|
||||
//UIContentPath is a string that sets the external
|
||||
// path to a string. Default: /ui/
|
||||
UIContentPath string
|
||||
// NOTE: Never read from this field directly once the agent has started up
|
||||
// since the UI config is reloadable. The on in the agent's config field may
|
||||
// be out of date. Use the agent.getUIConfig() method to get the latest config
|
||||
// in a thread-safe way.
|
||||
//
|
||||
// hcl: ui_config { ... }
|
||||
UIConfig UIConfig
|
||||
|
||||
// UnixSocketGroup contains the group of the file permissions when
|
||||
// Consul binds to UNIX sockets.
|
||||
|
@ -1518,6 +1513,27 @@ type AutoConfigAuthorizer struct {
|
|||
AllowReuse bool
|
||||
}
|
||||
|
||||
type UIConfig struct {
|
||||
Enabled bool
|
||||
Dir string
|
||||
ContentPath string
|
||||
MetricsProvider string
|
||||
MetricsProviderFiles []string
|
||||
MetricsProviderOptionsJSON string
|
||||
MetricsProxy UIMetricsProxy
|
||||
DashboardURLTemplates map[string]string
|
||||
}
|
||||
|
||||
type UIMetricsProxy struct {
|
||||
BaseURL string
|
||||
AddHeaders []UIMetricsProxyAddHeader
|
||||
}
|
||||
|
||||
type UIMetricsProxyAddHeader struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (c *RuntimeConfig) apiAddresses(maxPerType int) (unixAddrs, httpAddrs, httpsAddrs []string) {
|
||||
if len(c.HTTPSAddrs) > 0 {
|
||||
for i, addr := range c.HTTPSAddrs {
|
||||
|
|
|
@ -290,7 +290,7 @@ func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|||
rt.DisableAnonymousSignature = true
|
||||
rt.DisableKeyringFile = true
|
||||
rt.EnableDebug = true
|
||||
rt.EnableUI = true
|
||||
rt.UIConfig.Enabled = true
|
||||
rt.LeaveOnTerm = false
|
||||
rt.Logging.LogLevel = "DEBUG"
|
||||
rt.RPCAdvertiseAddr = tcpAddr("127.0.0.1:8300")
|
||||
|
@ -850,7 +850,7 @@ func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|||
`-data-dir=` + dataDir,
|
||||
},
|
||||
patch: func(rt *RuntimeConfig) {
|
||||
rt.EnableUI = true
|
||||
rt.UIConfig.Enabled = true
|
||||
rt.DataDir = dataDir
|
||||
},
|
||||
},
|
||||
|
@ -861,7 +861,7 @@ func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|||
`-data-dir=` + dataDir,
|
||||
},
|
||||
patch: func(rt *RuntimeConfig) {
|
||||
rt.UIDir = "a"
|
||||
rt.UIConfig.Dir = "a"
|
||||
rt.DataDir = dataDir
|
||||
},
|
||||
},
|
||||
|
@ -873,7 +873,7 @@ func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|||
},
|
||||
|
||||
patch: func(rt *RuntimeConfig) {
|
||||
rt.UIContentPath = "/a/b/"
|
||||
rt.UIConfig.ContentPath = "/a/b/"
|
||||
rt.DataDir = dataDir
|
||||
},
|
||||
},
|
||||
|
@ -1894,16 +1894,16 @@ func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|||
err: "DNS address cannot be a unix socket",
|
||||
},
|
||||
{
|
||||
desc: "ui and ui_dir",
|
||||
desc: "ui enabled and dir specified",
|
||||
args: []string{
|
||||
`-datacenter=a`,
|
||||
`-data-dir=` + dataDir,
|
||||
},
|
||||
json: []string{`{ "ui": true, "ui_dir": "a" }`},
|
||||
hcl: []string{`ui = true ui_dir = "a"`},
|
||||
err: "Both the ui and ui-dir flags were specified, please provide only one.\n" +
|
||||
"If trying to use your own web UI resources, use the ui-dir flag.\n" +
|
||||
"The web UI is included in the binary so use ui to enable it",
|
||||
json: []string{`{ "ui_config": { "enabled": true, "dir": "a" } }`},
|
||||
hcl: []string{`ui_config { enabled = true dir = "a"}`},
|
||||
err: "Both the ui_config.enabled and ui_config.dir (or -ui and -ui-dir) were specified, please provide only one.\n" +
|
||||
"If trying to use your own web UI resources, use ui_config.dir or the -ui-dir flag.\n" +
|
||||
"The web UI is included in the binary so use ui_config.enabled or the -ui flag to enable it",
|
||||
},
|
||||
|
||||
// test ANY address failures
|
||||
|
@ -4251,6 +4251,169 @@ func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|||
rt.CertFile = "foo"
|
||||
},
|
||||
},
|
||||
|
||||
// UI Config tests
|
||||
{
|
||||
desc: "ui config deprecated",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui": true,
|
||||
"ui_content_path": "/bar"
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui = true
|
||||
ui_content_path = "/bar"
|
||||
`},
|
||||
warns: []string{
|
||||
`The 'ui' field is deprecated. Use the 'ui_config.enabled' field instead.`,
|
||||
`The 'ui_content_path' field is deprecated. Use the 'ui_config.content_path' field instead.`,
|
||||
},
|
||||
patch: func(rt *RuntimeConfig) {
|
||||
// Should still work!
|
||||
rt.UIConfig.Enabled = true
|
||||
rt.UIConfig.ContentPath = "/bar/"
|
||||
rt.DataDir = dataDir
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "ui-dir config deprecated",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_dir": "/bar"
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_dir = "/bar"
|
||||
`},
|
||||
warns: []string{
|
||||
`The 'ui_dir' field is deprecated. Use the 'ui_config.dir' field instead.`,
|
||||
},
|
||||
patch: func(rt *RuntimeConfig) {
|
||||
// Should still work!
|
||||
rt.UIConfig.Dir = "/bar"
|
||||
rt.DataDir = dataDir
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "metrics_provider constraint",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"metrics_provider": "((((lisp 4 life))))"
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
metrics_provider = "((((lisp 4 life))))"
|
||||
}
|
||||
`},
|
||||
err: `ui_config.metrics_provider can only contain lowercase alphanumeric or _ characters.`,
|
||||
},
|
||||
{
|
||||
desc: "metrics_provider_options_json invalid JSON",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"metrics_provider_options_json": "not valid JSON"
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
metrics_provider_options_json = "not valid JSON"
|
||||
}
|
||||
`},
|
||||
err: `ui_config.metrics_provider_options_json must be empty or a string containing a valid JSON object.`,
|
||||
},
|
||||
{
|
||||
desc: "metrics_provider_options_json not an object",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"metrics_provider_options_json": "1.0"
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
metrics_provider_options_json = "1.0"
|
||||
}
|
||||
`},
|
||||
err: `ui_config.metrics_provider_options_json must be empty or a string containing a valid JSON object.`,
|
||||
},
|
||||
{
|
||||
desc: "metrics_proxy.base_url valid",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"metrics_proxy": {
|
||||
"base_url": "___"
|
||||
}
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
metrics_proxy {
|
||||
base_url = "___"
|
||||
}
|
||||
}
|
||||
`},
|
||||
err: `ui_config.metrics_proxy.base_url must be a valid http or https URL.`,
|
||||
},
|
||||
{
|
||||
desc: "metrics_proxy.base_url http(s)",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"metrics_proxy": {
|
||||
"base_url": "localhost:1234"
|
||||
}
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
metrics_proxy {
|
||||
base_url = "localhost:1234"
|
||||
}
|
||||
}
|
||||
`},
|
||||
err: `ui_config.metrics_proxy.base_url must be a valid http or https URL.`,
|
||||
},
|
||||
{
|
||||
desc: "dashboard_url_templates key format",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"dashboard_url_templates": {
|
||||
"(*&ASDOUISD)": "localhost:1234"
|
||||
}
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
dashboard_url_templates {
|
||||
"(*&ASDOUISD)" = "localhost:1234"
|
||||
}
|
||||
}
|
||||
`},
|
||||
err: `ui_config.dashboard_url_templates key names can only contain lowercase alphanumeric or _ characters.`,
|
||||
},
|
||||
{
|
||||
desc: "dashboard_url_templates value format",
|
||||
args: []string{`-data-dir=` + dataDir},
|
||||
json: []string{`{
|
||||
"ui_config": {
|
||||
"dashboard_url_templates": {
|
||||
"services": "localhost:1234"
|
||||
}
|
||||
}
|
||||
}`},
|
||||
hcl: []string{`
|
||||
ui_config {
|
||||
dashboard_url_templates {
|
||||
services = "localhost:1234"
|
||||
}
|
||||
}
|
||||
`},
|
||||
err: `ui_config.dashboard_url_templates values must be a valid http or https URL.`,
|
||||
},
|
||||
}
|
||||
|
||||
testConfig(t, tests, dataDir)
|
||||
|
@ -5070,9 +5233,26 @@ func TestFullConfig(t *testing.T) {
|
|||
"tls_min_version": "pAOWafkR",
|
||||
"tls_prefer_server_cipher_suites": true,
|
||||
"translate_wan_addrs": true,
|
||||
"ui": true,
|
||||
"ui_dir": "11IFzAUn",
|
||||
"ui_content_path": "consul",
|
||||
"ui_config": {
|
||||
"enabled": true,
|
||||
"dir": "pVncV4Ey",
|
||||
"content_path": "qp1WRhYH",
|
||||
"metrics_provider": "sgnaoa_lower_case",
|
||||
"metrics_provider_files": ["sgnaMFoa", "dicnwkTH"],
|
||||
"metrics_provider_options_json": "{\"DIbVQadX\": 1}",
|
||||
"metrics_proxy": {
|
||||
"base_url": "http://foo.bar",
|
||||
"add_headers": [
|
||||
{
|
||||
"name": "p3nynwc9",
|
||||
"value": "TYBgnN2F"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dashboard_url_templates": {
|
||||
"u2eziu2n_lower_case": "http://lkjasd.otr"
|
||||
}
|
||||
},
|
||||
"unix_sockets": {
|
||||
"group": "8pFodrV8",
|
||||
"mode": "E8sAwOv4",
|
||||
|
@ -5736,9 +5916,26 @@ func TestFullConfig(t *testing.T) {
|
|||
tls_min_version = "pAOWafkR"
|
||||
tls_prefer_server_cipher_suites = true
|
||||
translate_wan_addrs = true
|
||||
ui = true
|
||||
ui_dir = "11IFzAUn"
|
||||
ui_content_path = "consul"
|
||||
ui_config {
|
||||
enabled = true
|
||||
dir = "pVncV4Ey"
|
||||
content_path = "qp1WRhYH"
|
||||
metrics_provider = "sgnaoa_lower_case"
|
||||
metrics_provider_files = ["sgnaMFoa", "dicnwkTH"]
|
||||
metrics_provider_options_json = "{\"DIbVQadX\": 1}"
|
||||
metrics_proxy {
|
||||
base_url = "http://foo.bar"
|
||||
add_headers = [
|
||||
{
|
||||
name = "p3nynwc9"
|
||||
value = "TYBgnN2F"
|
||||
}
|
||||
]
|
||||
}
|
||||
dashboard_url_templates {
|
||||
u2eziu2n_lower_case = "http://lkjasd.otr"
|
||||
}
|
||||
}
|
||||
unix_sockets = {
|
||||
group = "8pFodrV8"
|
||||
mode = "E8sAwOv4"
|
||||
|
@ -6110,7 +6307,6 @@ func TestFullConfig(t *testing.T) {
|
|||
EnableDebug: true,
|
||||
EnableRemoteScriptChecks: true,
|
||||
EnableLocalScriptChecks: true,
|
||||
EnableUI: true,
|
||||
EncryptKey: "A4wELWqH",
|
||||
EncryptVerifyIncoming: true,
|
||||
EncryptVerifyOutgoing: true,
|
||||
|
@ -6507,10 +6703,26 @@ func TestFullConfig(t *testing.T) {
|
|||
"wan": "78.63.37.19",
|
||||
"wan_ipv4": "78.63.37.19",
|
||||
},
|
||||
TranslateWANAddrs: true,
|
||||
TxnMaxReqLen: 5678000000000000,
|
||||
UIContentPath: "/consul/",
|
||||
UIDir: "11IFzAUn",
|
||||
TranslateWANAddrs: true,
|
||||
TxnMaxReqLen: 5678000000000000,
|
||||
UIConfig: UIConfig{
|
||||
Enabled: true,
|
||||
Dir: "pVncV4Ey",
|
||||
ContentPath: "/qp1WRhYH/", // slashes are added in parsing
|
||||
MetricsProvider: "sgnaoa_lower_case",
|
||||
MetricsProviderFiles: []string{"sgnaMFoa", "dicnwkTH"},
|
||||
MetricsProviderOptionsJSON: "{\"DIbVQadX\": 1}",
|
||||
MetricsProxy: UIMetricsProxy{
|
||||
BaseURL: "http://foo.bar",
|
||||
AddHeaders: []UIMetricsProxyAddHeader{
|
||||
{
|
||||
Name: "p3nynwc9",
|
||||
Value: "TYBgnN2F",
|
||||
},
|
||||
},
|
||||
},
|
||||
DashboardURLTemplates: map[string]string{"u2eziu2n_lower_case": "http://lkjasd.otr"},
|
||||
},
|
||||
UnixSocketUser: "E0nB1DwA",
|
||||
UnixSocketGroup: "8pFodrV8",
|
||||
UnixSocketMode: "E8sAwOv4",
|
||||
|
@ -6589,7 +6801,7 @@ func TestFullConfig(t *testing.T) {
|
|||
// we are patching a handful of safe fields to make validation pass.
|
||||
rt.Bootstrap = false
|
||||
rt.DevMode = false
|
||||
rt.EnableUI = false
|
||||
rt.UIConfig.Enabled = false
|
||||
rt.SegmentName = ""
|
||||
rt.Segments = nil
|
||||
|
||||
|
@ -6599,7 +6811,7 @@ func TestFullConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
// check the warnings
|
||||
require.ElementsMatch(t, warns, b.Warnings, "Warnings: %v", b.Warnings)
|
||||
require.ElementsMatch(t, warns, b.Warnings, "Warnings: %#v", b.Warnings)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -7005,7 +7217,6 @@ func TestSanitize(t *testing.T) {
|
|||
"EnableCentralServiceConfig": false,
|
||||
"EnableLocalScriptChecks": false,
|
||||
"EnableRemoteScriptChecks": false,
|
||||
"EnableUI": false,
|
||||
"EncryptKey": "hidden",
|
||||
"EncryptVerifyIncoming": false,
|
||||
"EncryptVerifyOutgoing": false,
|
||||
|
@ -7179,8 +7390,19 @@ func TestSanitize(t *testing.T) {
|
|||
},
|
||||
"TranslateWANAddrs": false,
|
||||
"TxnMaxReqLen": 5678000000000000,
|
||||
"UIDir": "",
|
||||
"UIContentPath": "",
|
||||
"UIConfig": {
|
||||
"ContentPath": "",
|
||||
"Dir": "",
|
||||
"Enabled": false,
|
||||
"MetricsProvider": "",
|
||||
"MetricsProviderFiles": [],
|
||||
"MetricsProviderOptionsJSON": "",
|
||||
"MetricsProxy": {
|
||||
"AddHeaders": [],
|
||||
"BaseURL": ""
|
||||
},
|
||||
"DashboardURLTemplates": {}
|
||||
},
|
||||
"UnixSocketGroup": "",
|
||||
"UnixSocketMode": "",
|
||||
"UnixSocketUser": "",
|
||||
|
|
|
@ -347,16 +347,23 @@ func (s *HTTPHandlers) handler(enableDebug bool) http.Handler {
|
|||
handlePProf("/debug/pprof/trace", pprof.Trace)
|
||||
|
||||
if s.IsUIEnabled() {
|
||||
// Note that we _don't_ support reloading ui_config.{enabled,content_dir}
|
||||
// since this only runs at initial startup.
|
||||
|
||||
var uifs http.FileSystem
|
||||
// Use the custom UI dir if provided.
|
||||
if s.agent.config.UIDir != "" {
|
||||
uifs = http.Dir(s.agent.config.UIDir)
|
||||
uiConfig := s.agent.getUIConfig()
|
||||
if uiConfig.Dir != "" {
|
||||
uifs = http.Dir(uiConfig.Dir)
|
||||
} else {
|
||||
fs := assetFS()
|
||||
uifs = fs
|
||||
}
|
||||
|
||||
uifs = &redirectFS{fs: &settingsInjectedIndexFS{fs: uifs, UISettings: s.GetUIENVFromConfig()}}
|
||||
uifs = &redirectFS{fs: &settingsInjectedIndexFS{
|
||||
fs: uifs,
|
||||
UISettings: s.GetUIENVFromConfig(),
|
||||
}}
|
||||
// create a http handler using the ui file system
|
||||
// and the headers specified by the http_config.response_headers user config
|
||||
uifsWithHeaders := serveHandlerWithHeaders(
|
||||
|
@ -368,9 +375,9 @@ func (s *HTTPHandlers) handler(enableDebug bool) http.Handler {
|
|||
uifsWithHeaders,
|
||||
)
|
||||
mux.Handle(
|
||||
s.agent.config.UIContentPath,
|
||||
uiConfig.ContentPath,
|
||||
http.StripPrefix(
|
||||
s.agent.config.UIContentPath,
|
||||
uiConfig.ContentPath,
|
||||
uifsWithHeaders,
|
||||
),
|
||||
)
|
||||
|
@ -391,9 +398,20 @@ func (s *HTTPHandlers) handler(enableDebug bool) http.Handler {
|
|||
}
|
||||
|
||||
func (s *HTTPHandlers) GetUIENVFromConfig() map[string]interface{} {
|
||||
uiCfg := s.agent.getUIConfig()
|
||||
|
||||
vars := map[string]interface{}{
|
||||
"CONSUL_CONTENT_PATH": s.agent.config.UIContentPath,
|
||||
"CONSUL_ACLS_ENABLED": s.agent.config.ACLsEnabled,
|
||||
"CONSUL_CONTENT_PATH": uiCfg.ContentPath,
|
||||
"CONSUL_ACLS_ENABLED": s.agent.config.ACLsEnabled,
|
||||
"CONSUL_METRICS_PROVIDER": uiCfg.MetricsProvider,
|
||||
"CONSUL_METRICS_PROVIDER_OPTIONS": json.RawMessage(uiCfg.MetricsProviderOptionsJSON),
|
||||
// We explicitly MUST NOT pass the metrics_proxy object since it might
|
||||
// contain add_headers with secrets that the UI shouldn't know e.g. API
|
||||
// tokens for the backend. The provider should either require the proxy to
|
||||
// be configured and then use that or hit the backend directly from the
|
||||
// browser.
|
||||
"CONSUL_METRICS_PROXY_ENABLED": uiCfg.MetricsProxy.BaseURL != "",
|
||||
"CONSUL_DASHBOARD_URL_TEMPLATES": uiCfg.DashboardURLTemplates,
|
||||
}
|
||||
|
||||
s.addEnterpriseUIENVVars(vars)
|
||||
|
@ -655,7 +673,8 @@ func (s *HTTPHandlers) Index(resp http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
// Redirect to the UI endpoint
|
||||
http.Redirect(resp, req, s.agent.config.UIContentPath, http.StatusMovedPermanently) // 301
|
||||
uiCfg := s.agent.getUIConfig()
|
||||
http.Redirect(resp, req, uiCfg.ContentPath, http.StatusMovedPermanently) // 301
|
||||
}
|
||||
|
||||
func decodeBody(body io.Reader, out interface{}) error {
|
||||
|
|
|
@ -34,7 +34,7 @@ func TestUiIndex(t *testing.T) {
|
|||
testrpc.WaitForLeader(t, a.RPC, "dc1")
|
||||
|
||||
// Create file
|
||||
path := filepath.Join(a.Config.UIDir, "my-file")
|
||||
path := filepath.Join(a.Config.UIConfig.Dir, "my-file")
|
||||
if err := ioutil.WriteFile(path, []byte("test"), 0777); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue