mirror of https://github.com/hashicorp/consul
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7945 lines
211 KiB
7945 lines
211 KiB
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/consul/agent/cache"
|
|
"github.com/hashicorp/consul/agent/checks"
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
"github.com/hashicorp/consul/agent/token"
|
|
"github.com/hashicorp/consul/lib"
|
|
"github.com/hashicorp/consul/logging"
|
|
"github.com/hashicorp/consul/sdk/testutil"
|
|
"github.com/hashicorp/consul/types"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type configTest struct {
|
|
desc string
|
|
args []string
|
|
pre, post func()
|
|
json, jsontail []string
|
|
hcl, hcltail []string
|
|
skipformat bool
|
|
privatev4 func() ([]*net.IPAddr, error)
|
|
publicv6 func() ([]*net.IPAddr, error)
|
|
patch func(rt *RuntimeConfig)
|
|
err string
|
|
warns []string
|
|
hostname func() (string, error)
|
|
}
|
|
|
|
// TestConfigFlagsAndEdgecases tests the command line flags and
|
|
// edgecases for the config parsing. It provides a test structure which
|
|
// checks for warnings on deprecated fields and flags. These tests
|
|
// should check one option at a time if possible and should use generic
|
|
// values, e.g. 'a' or 1 instead of 'servicex' or 3306.
|
|
|
|
func TestBuilder_BuildAndValide_ConfigFlagsAndEdgecases(t *testing.T) {
|
|
dataDir := testutil.TempDir(t, "consul")
|
|
|
|
defaultEntMeta := structs.DefaultEnterpriseMeta()
|
|
|
|
tests := []configTest{
|
|
// ------------------------------------------------------------
|
|
// cmd line flags
|
|
//
|
|
|
|
{
|
|
desc: "-advertise",
|
|
args: []string{
|
|
`-advertise=1.2.3.4`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.2.3.4",
|
|
"lan_ipv4": "1.2.3.4",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-advertise-wan",
|
|
args: []string{
|
|
`-advertise-wan=1.2.3.4`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "10.0.0.1",
|
|
"lan_ipv4": "10.0.0.1",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-advertise and -advertise-wan",
|
|
args: []string{
|
|
`-advertise=1.2.3.4`,
|
|
`-advertise-wan=5.6.7.8`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrWAN = ipAddr("5.6.7.8")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("5.6.7.8:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.2.3.4",
|
|
"lan_ipv4": "1.2.3.4",
|
|
"wan": "5.6.7.8",
|
|
"wan_ipv4": "5.6.7.8",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-bind",
|
|
args: []string{
|
|
`-bind=1.2.3.4`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.BindAddr = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
|
|
rt.RPCBindAddr = tcpAddr("1.2.3.4:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.SerfBindAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.SerfBindAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.2.3.4",
|
|
"lan_ipv4": "1.2.3.4",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-bootstrap",
|
|
args: []string{
|
|
`-bootstrap`,
|
|
`-server`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Bootstrap = true
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{"bootstrap = true: do not enable unless necessary"},
|
|
},
|
|
{
|
|
desc: "-bootstrap-expect",
|
|
args: []string{
|
|
`-bootstrap-expect=3`,
|
|
`-server`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.BootstrapExpect = 3
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{"bootstrap_expect > 0: expecting 3 servers"},
|
|
},
|
|
{
|
|
desc: "-client",
|
|
args: []string{
|
|
`-client=1.2.3.4`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("1.2.3.4")}
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("1.2.3.4:8600"), udpAddr("1.2.3.4:8600")}
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("1.2.3.4:8500")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-config-dir",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-config-dir`, filepath.Join(dataDir, "conf.d"),
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
pre: func() {
|
|
writeFile(filepath.Join(dataDir, "conf.d/conf.json"), []byte(`{"datacenter":"a"}`))
|
|
},
|
|
},
|
|
{
|
|
desc: "-config-file json",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-config-file`, filepath.Join(dataDir, "conf.json"),
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
pre: func() {
|
|
writeFile(filepath.Join(dataDir, "conf.json"), []byte(`{"datacenter":"a"}`))
|
|
},
|
|
},
|
|
{
|
|
desc: "-config-file hcl and json",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-config-file`, filepath.Join(dataDir, "conf.hcl"),
|
|
`-config-file`, filepath.Join(dataDir, "conf.json"),
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "b"
|
|
rt.ACLDatacenter = "b"
|
|
rt.PrimaryDatacenter = "b"
|
|
rt.DataDir = dataDir
|
|
},
|
|
pre: func() {
|
|
writeFile(filepath.Join(dataDir, "conf.hcl"), []byte(`datacenter = "a"`))
|
|
writeFile(filepath.Join(dataDir, "conf.json"), []byte(`{"datacenter":"b"}`))
|
|
},
|
|
},
|
|
{
|
|
desc: "-data-dir empty",
|
|
args: []string{
|
|
`-data-dir=`,
|
|
},
|
|
err: "data_dir cannot be empty",
|
|
},
|
|
{
|
|
desc: "-data-dir non-directory",
|
|
args: []string{
|
|
`-data-dir=runtime_test.go`,
|
|
},
|
|
err: `data_dir "runtime_test.go" is not a directory`,
|
|
},
|
|
{
|
|
desc: "-datacenter",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-datacenter empty",
|
|
args: []string{
|
|
`-datacenter=`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
err: "datacenter cannot be empty",
|
|
},
|
|
{
|
|
desc: "-dev",
|
|
args: []string{
|
|
`-dev`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("127.0.0.1")
|
|
rt.AdvertiseAddrWAN = ipAddr("127.0.0.1")
|
|
rt.BindAddr = ipAddr("127.0.0.1")
|
|
rt.ConnectEnabled = true
|
|
rt.DevMode = true
|
|
rt.DisableAnonymousSignature = true
|
|
rt.DisableKeyringFile = true
|
|
rt.EnableDebug = true
|
|
rt.UIConfig.Enabled = true
|
|
rt.LeaveOnTerm = false
|
|
rt.Logging.LogLevel = "DEBUG"
|
|
rt.RPCAdvertiseAddr = tcpAddr("127.0.0.1:8300")
|
|
rt.RPCBindAddr = tcpAddr("127.0.0.1:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("127.0.0.1:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("127.0.0.1:8302")
|
|
rt.SerfBindAddrLAN = tcpAddr("127.0.0.1:8301")
|
|
rt.SerfBindAddrWAN = tcpAddr("127.0.0.1:8302")
|
|
rt.ServerMode = true
|
|
rt.SkipLeaveOnInt = true
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "127.0.0.1",
|
|
"lan_ipv4": "127.0.0.1",
|
|
"wan": "127.0.0.1",
|
|
"wan_ipv4": "127.0.0.1",
|
|
}
|
|
rt.ConsulCoordinateUpdatePeriod = 100 * time.Millisecond
|
|
rt.ConsulRaftElectionTimeout = 52 * time.Millisecond
|
|
rt.ConsulRaftHeartbeatTimeout = 35 * time.Millisecond
|
|
rt.ConsulRaftLeaderLeaseTimeout = 20 * time.Millisecond
|
|
rt.GossipLANGossipInterval = 100 * time.Millisecond
|
|
rt.GossipLANProbeInterval = 100 * time.Millisecond
|
|
rt.GossipLANProbeTimeout = 100 * time.Millisecond
|
|
rt.GossipLANSuspicionMult = 3
|
|
rt.GossipWANGossipInterval = 100 * time.Millisecond
|
|
rt.GossipWANProbeInterval = 100 * time.Millisecond
|
|
rt.GossipWANProbeTimeout = 100 * time.Millisecond
|
|
rt.GossipWANSuspicionMult = 3
|
|
rt.ConsulServerHealthInterval = 10 * time.Millisecond
|
|
rt.GRPCPort = 8502
|
|
rt.GRPCAddrs = []net.Addr{tcpAddr("127.0.0.1:8502")}
|
|
},
|
|
},
|
|
{
|
|
desc: "-disable-host-node-id",
|
|
args: []string{
|
|
`-disable-host-node-id`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DisableHostNodeID = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-disable-keyring-file",
|
|
args: []string{
|
|
`-disable-keyring-file`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DisableKeyringFile = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-dns-port",
|
|
args: []string{
|
|
`-dns-port=123`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DNSPort = 123
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("127.0.0.1:123"), udpAddr("127.0.0.1:123")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-domain",
|
|
args: []string{
|
|
`-domain=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DNSDomain = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-alt-domain",
|
|
args: []string{
|
|
`-alt-domain=alt`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DNSAltDomain = "alt"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-alt-domain can't be prefixed by DC",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-alt-domain=a.alt`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
err: "alt_domain cannot start with {service,connect,node,query,addr,a}",
|
|
},
|
|
{
|
|
desc: "-alt-domain can't be prefixed by service",
|
|
args: []string{
|
|
`-alt-domain=service.alt`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
err: "alt_domain cannot start with {service,connect,node,query,addr,dc1}",
|
|
},
|
|
{
|
|
desc: "-alt-domain can be prefixed by non-keywords",
|
|
args: []string{
|
|
`-alt-domain=mydomain.alt`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DNSAltDomain = "mydomain.alt"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-alt-domain can't be prefixed by DC",
|
|
args: []string{
|
|
`-alt-domain=dc1.alt`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
err: "alt_domain cannot start with {service,connect,node,query,addr,dc1}",
|
|
},
|
|
{
|
|
desc: "-enable-script-checks",
|
|
args: []string{
|
|
`-enable-script-checks`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.EnableLocalScriptChecks = true
|
|
rt.EnableRemoteScriptChecks = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{remoteScriptCheckSecurityWarning},
|
|
},
|
|
{
|
|
desc: "-encrypt",
|
|
args: []string{
|
|
`-encrypt=pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s=`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.EncryptKey = "pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s="
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-config-format disabled, skip unknown files",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-config-dir`, filepath.Join(dataDir, "conf"),
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
pre: func() {
|
|
writeFile(filepath.Join(dataDir, "conf", "valid.json"), []byte(`{"datacenter":"a"}`))
|
|
writeFile(filepath.Join(dataDir, "conf", "invalid.skip"), []byte(`NOPE`))
|
|
},
|
|
warns: []string{
|
|
"skipping file " + filepath.Join(dataDir, "conf", "invalid.skip") + ", extension must be .hcl or .json, or config format must be set",
|
|
},
|
|
},
|
|
{
|
|
desc: "-config-format=json",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-config-format=json`,
|
|
`-config-file`, filepath.Join(dataDir, "conf"),
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
pre: func() {
|
|
writeFile(filepath.Join(dataDir, "conf"), []byte(`{"datacenter":"a"}`))
|
|
},
|
|
},
|
|
{
|
|
desc: "-config-format=hcl",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-config-format=hcl`,
|
|
`-config-file`, filepath.Join(dataDir, "conf"),
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
pre: func() {
|
|
writeFile(filepath.Join(dataDir, "conf"), []byte(`datacenter = "a"`))
|
|
},
|
|
},
|
|
{
|
|
desc: "-http-port",
|
|
args: []string{
|
|
`-http-port=123`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.HTTPPort = 123
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("127.0.0.1:123")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-join",
|
|
args: []string{
|
|
`-join=a`,
|
|
`-join=b`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.StartJoinAddrsLAN = []string{"a", "b"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-join-wan",
|
|
args: []string{
|
|
`-join-wan=a`,
|
|
`-join-wan=b`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.StartJoinAddrsWAN = []string{"a", "b"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-log-level",
|
|
args: []string{
|
|
`-log-level=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Logging.LogLevel = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-log-json",
|
|
args: []string{
|
|
`-log-json`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Logging.LogJSON = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-log-rotate-max-files",
|
|
args: []string{
|
|
`-log-rotate-max-files=2`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "log_rotate_max_files": 2 }`},
|
|
hcl: []string{`log_rotate_max_files = 2`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Logging.LogRotateMaxFiles = 2
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-node",
|
|
args: []string{
|
|
`-node=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.NodeName = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-node-id",
|
|
args: []string{
|
|
`-node-id=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.NodeID = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-node-meta",
|
|
args: []string{
|
|
`-node-meta=a:b`,
|
|
`-node-meta=c:d`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.NodeMeta = map[string]string{"a": "b", "c": "d"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-non-voting-server",
|
|
args: []string{
|
|
`-non-voting-server`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.NonVotingServer = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: enterpriseNonVotingServerWarnings,
|
|
},
|
|
{
|
|
desc: "-pid-file",
|
|
args: []string{
|
|
`-pid-file=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.PidFile = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-primary-gateway",
|
|
args: []string{
|
|
`-server`,
|
|
`-datacenter=dc2`,
|
|
`-primary-gateway=a`,
|
|
`-primary-gateway=b`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "primary_datacenter": "dc1" }`},
|
|
hcl: []string{`primary_datacenter = "dc1"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "dc2"
|
|
rt.PrimaryDatacenter = "dc1"
|
|
rt.ACLDatacenter = "dc1"
|
|
rt.PrimaryGateways = []string{"a", "b"}
|
|
rt.DataDir = dataDir
|
|
// server things
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
},
|
|
},
|
|
{
|
|
desc: "-protocol",
|
|
args: []string{
|
|
`-protocol=1`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RPCProtocol = 1
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-raft-protocol",
|
|
args: []string{
|
|
`-raft-protocol=1`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RaftProtocol = 1
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-recursor",
|
|
args: []string{
|
|
`-recursor=1.2.3.4`,
|
|
`-recursor=5.6.7.8`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DNSRecursors = []string{"1.2.3.4", "5.6.7.8"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-rejoin",
|
|
args: []string{
|
|
`-rejoin`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RejoinAfterLeave = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-retry-interval",
|
|
args: []string{
|
|
`-retry-interval=5s`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinIntervalLAN = 5 * time.Second
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-retry-interval-wan",
|
|
args: []string{
|
|
`-retry-interval-wan=5s`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinIntervalWAN = 5 * time.Second
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-retry-join",
|
|
args: []string{
|
|
`-retry-join=a`,
|
|
`-retry-join=b`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinLAN = []string{"a", "b"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-retry-join-wan",
|
|
args: []string{
|
|
`-retry-join-wan=a`,
|
|
`-retry-join-wan=b`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinWAN = []string{"a", "b"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-retry-max",
|
|
args: []string{
|
|
`-retry-max=1`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinMaxAttemptsLAN = 1
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-retry-max-wan",
|
|
args: []string{
|
|
`-retry-max-wan=1`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinMaxAttemptsWAN = 1
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-serf-lan-bind",
|
|
args: []string{
|
|
`-serf-lan-bind=1.2.3.4`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.SerfBindAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-serf-lan-port",
|
|
args: []string{
|
|
`-serf-lan-port=123`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.SerfPortLAN = 123
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("10.0.0.1:123")
|
|
rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:123")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-serf-wan-bind",
|
|
args: []string{
|
|
`-serf-wan-bind=1.2.3.4`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.SerfBindAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-serf-wan-port",
|
|
args: []string{
|
|
`-serf-wan-port=123`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.SerfPortWAN = 123
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("10.0.0.1:123")
|
|
rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:123")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-server",
|
|
args: []string{
|
|
`-server`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-server-port",
|
|
args: []string{
|
|
`-server-port=123`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ServerPort = 123
|
|
rt.RPCAdvertiseAddr = tcpAddr("10.0.0.1:123")
|
|
rt.RPCBindAddr = tcpAddr("0.0.0.0:123")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-syslog",
|
|
args: []string{
|
|
`-syslog`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Logging.EnableSyslog = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-ui",
|
|
args: []string{
|
|
`-ui`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.UIConfig.Enabled = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-ui-dir",
|
|
args: []string{
|
|
`-ui-dir=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.UIConfig.Dir = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "-ui-content-path",
|
|
args: []string{
|
|
`-ui-content-path=/a/b`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.UIConfig.ContentPath = "/a/b/"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
|
|
// ------------------------------------------------------------
|
|
// ports and addresses
|
|
//
|
|
|
|
{
|
|
desc: "bind addr any v4",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr":"0.0.0.0" }`},
|
|
hcl: []string{`bind_addr = "0.0.0.0"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("10.0.0.1")
|
|
rt.AdvertiseAddrWAN = ipAddr("10.0.0.1")
|
|
rt.BindAddr = ipAddr("0.0.0.0")
|
|
rt.RPCAdvertiseAddr = tcpAddr("10.0.0.1:8300")
|
|
rt.RPCBindAddr = tcpAddr("0.0.0.0:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("10.0.0.1:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("10.0.0.1:8302")
|
|
rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:8301")
|
|
rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "10.0.0.1",
|
|
"lan_ipv4": "10.0.0.1",
|
|
"wan": "10.0.0.1",
|
|
"wan_ipv4": "10.0.0.1",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "bind addr any v6",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr":"::" }`},
|
|
hcl: []string{`bind_addr = "::"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("dead:beef::1")
|
|
rt.AdvertiseAddrWAN = ipAddr("dead:beef::1")
|
|
rt.BindAddr = ipAddr("::")
|
|
rt.RPCAdvertiseAddr = tcpAddr("[dead:beef::1]:8300")
|
|
rt.RPCBindAddr = tcpAddr("[::]:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("[dead:beef::1]:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("[dead:beef::1]:8302")
|
|
rt.SerfBindAddrLAN = tcpAddr("[::]:8301")
|
|
rt.SerfBindAddrWAN = tcpAddr("[::]:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "dead:beef::1",
|
|
"lan_ipv6": "dead:beef::1",
|
|
"wan": "dead:beef::1",
|
|
"wan_ipv6": "dead:beef::1",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
publicv6: func() ([]*net.IPAddr, error) {
|
|
return []*net.IPAddr{ipAddr("dead:beef::1")}, nil
|
|
},
|
|
},
|
|
{
|
|
desc: "bind addr any and advertise set should not detect",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr":"0.0.0.0", "advertise_addr": "1.2.3.4" }`},
|
|
hcl: []string{`bind_addr = "0.0.0.0" advertise_addr = "1.2.3.4"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.BindAddr = ipAddr("0.0.0.0")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
|
|
rt.RPCBindAddr = tcpAddr("0.0.0.0:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:8301")
|
|
rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.2.3.4",
|
|
"lan_ipv4": "1.2.3.4",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
privatev4: func() ([]*net.IPAddr, error) {
|
|
return nil, fmt.Errorf("should not detect advertise_addr")
|
|
},
|
|
},
|
|
{
|
|
desc: "client addr and ports == 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr":"0.0.0.0",
|
|
"ports":{}
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "0.0.0.0"
|
|
ports {}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("0.0.0.0:8600"), udpAddr("0.0.0.0:8600")}
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("0.0.0.0:8500")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client addr and ports < 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr":"0.0.0.0",
|
|
"ports": { "dns":-1, "http":-2, "https":-3, "grpc":-4 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "0.0.0.0"
|
|
ports { dns = -1 http = -2 https = -3 grpc = -4 }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
|
|
rt.DNSPort = -1
|
|
rt.DNSAddrs = nil
|
|
rt.HTTPPort = -1
|
|
rt.HTTPAddrs = nil
|
|
// HTTPS and gRPC default to disabled so shouldn't be different from
|
|
// default rt.
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client addr and ports > 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr":"0.0.0.0",
|
|
"ports":{ "dns": 1, "http": 2, "https": 3, "grpc": 4 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "0.0.0.0"
|
|
ports { dns = 1 http = 2 https = 3 grpc = 4 }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
|
|
rt.DNSPort = 1
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("0.0.0.0:1"), udpAddr("0.0.0.0:1")}
|
|
rt.HTTPPort = 2
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("0.0.0.0:2")}
|
|
rt.HTTPSPort = 3
|
|
rt.HTTPSAddrs = []net.Addr{tcpAddr("0.0.0.0:3")}
|
|
rt.GRPCPort = 4
|
|
rt.GRPCAddrs = []net.Addr{tcpAddr("0.0.0.0:4")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
|
|
{
|
|
desc: "client addr, addresses and ports == 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr":"0.0.0.0",
|
|
"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3", "grpc": "4.4.4.4" },
|
|
"ports":{}
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "0.0.0.0"
|
|
addresses = { dns = "1.1.1.1" http = "2.2.2.2" https = "3.3.3.3" grpc = "4.4.4.4" }
|
|
ports {}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("1.1.1.1:8600"), udpAddr("1.1.1.1:8600")}
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("2.2.2.2:8500")}
|
|
// HTTPS and gRPC default to disabled so shouldn't be different from
|
|
// default rt.
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client addr, addresses and ports < 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr":"0.0.0.0",
|
|
"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3", "grpc": "4.4.4.4" },
|
|
"ports": { "dns":-1, "http":-2, "https":-3, "grpc":-4 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "0.0.0.0"
|
|
addresses = { dns = "1.1.1.1" http = "2.2.2.2" https = "3.3.3.3" grpc = "4.4.4.4" }
|
|
ports { dns = -1 http = -2 https = -3 grpc = -4 }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
|
|
rt.DNSPort = -1
|
|
rt.DNSAddrs = nil
|
|
rt.HTTPPort = -1
|
|
rt.HTTPAddrs = nil
|
|
// HTTPS and gRPC default to disabled so shouldn't be different from
|
|
// default rt.
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client addr, addresses and ports",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr": "0.0.0.0",
|
|
"addresses": { "dns": "1.1.1.1", "http": "2.2.2.2", "https": "3.3.3.3", "grpc": "4.4.4.4" },
|
|
"ports":{ "dns":1, "http":2, "https":3, "grpc":4 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "0.0.0.0"
|
|
addresses = { dns = "1.1.1.1" http = "2.2.2.2" https = "3.3.3.3" grpc = "4.4.4.4" }
|
|
ports { dns = 1 http = 2 https = 3 grpc = 4 }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("0.0.0.0")}
|
|
rt.DNSPort = 1
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("1.1.1.1:1"), udpAddr("1.1.1.1:1")}
|
|
rt.HTTPPort = 2
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("2.2.2.2:2")}
|
|
rt.HTTPSPort = 3
|
|
rt.HTTPSAddrs = []net.Addr{tcpAddr("3.3.3.3:3")}
|
|
rt.GRPCPort = 4
|
|
rt.GRPCAddrs = []net.Addr{tcpAddr("4.4.4.4:4")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client template and ports",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr": "{{ printf \"1.2.3.4 2001:db8::1\" }}",
|
|
"ports":{ "dns":1, "http":2, "https":3, "grpc":4 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "{{ printf \"1.2.3.4 2001:db8::1\" }}"
|
|
ports { dns = 1 http = 2 https = 3 grpc = 4 }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("1.2.3.4"), ipAddr("2001:db8::1")}
|
|
rt.DNSPort = 1
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("1.2.3.4:1"), tcpAddr("[2001:db8::1]:1"), udpAddr("1.2.3.4:1"), udpAddr("[2001:db8::1]:1")}
|
|
rt.HTTPPort = 2
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("1.2.3.4:2"), tcpAddr("[2001:db8::1]:2")}
|
|
rt.HTTPSPort = 3
|
|
rt.HTTPSAddrs = []net.Addr{tcpAddr("1.2.3.4:3"), tcpAddr("[2001:db8::1]:3")}
|
|
rt.GRPCPort = 4
|
|
rt.GRPCAddrs = []net.Addr{tcpAddr("1.2.3.4:4"), tcpAddr("[2001:db8::1]:4")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client, address template and ports",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"client_addr": "{{ printf \"1.2.3.4 2001:db8::1\" }}",
|
|
"addresses": {
|
|
"dns": "{{ printf \"1.1.1.1 2001:db8::10 \" }}",
|
|
"http": "{{ printf \"2.2.2.2 unix://http 2001:db8::20 \" }}",
|
|
"https": "{{ printf \"3.3.3.3 unix://https 2001:db8::30 \" }}",
|
|
"grpc": "{{ printf \"4.4.4.4 unix://grpc 2001:db8::40 \" }}"
|
|
},
|
|
"ports":{ "dns":1, "http":2, "https":3, "grpc":4 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "{{ printf \"1.2.3.4 2001:db8::1\" }}"
|
|
addresses = {
|
|
dns = "{{ printf \"1.1.1.1 2001:db8::10 \" }}"
|
|
http = "{{ printf \"2.2.2.2 unix://http 2001:db8::20 \" }}"
|
|
https = "{{ printf \"3.3.3.3 unix://https 2001:db8::30 \" }}"
|
|
grpc = "{{ printf \"4.4.4.4 unix://grpc 2001:db8::40 \" }}"
|
|
}
|
|
ports { dns = 1 http = 2 https = 3 grpc = 4 }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ClientAddrs = []*net.IPAddr{ipAddr("1.2.3.4"), ipAddr("2001:db8::1")}
|
|
rt.DNSPort = 1
|
|
rt.DNSAddrs = []net.Addr{tcpAddr("1.1.1.1:1"), tcpAddr("[2001:db8::10]:1"), udpAddr("1.1.1.1:1"), udpAddr("[2001:db8::10]:1")}
|
|
rt.HTTPPort = 2
|
|
rt.HTTPAddrs = []net.Addr{tcpAddr("2.2.2.2:2"), unixAddr("unix://http"), tcpAddr("[2001:db8::20]:2")}
|
|
rt.HTTPSPort = 3
|
|
rt.HTTPSAddrs = []net.Addr{tcpAddr("3.3.3.3:3"), unixAddr("unix://https"), tcpAddr("[2001:db8::30]:3")}
|
|
rt.GRPCPort = 4
|
|
rt.GRPCAddrs = []net.Addr{tcpAddr("4.4.4.4:4"), unixAddr("unix://grpc"), tcpAddr("[2001:db8::40]:4")}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "advertise address lan template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "advertise_addr": "{{ printf \"1.2.3.4\" }}" }`},
|
|
hcl: []string{`advertise_addr = "{{ printf \"1.2.3.4\" }}"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.2.3.4",
|
|
"lan_ipv4": "1.2.3.4",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "advertise address wan template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "advertise_addr_wan": "{{ printf \"1.2.3.4\" }}" }`},
|
|
hcl: []string{`advertise_addr_wan = "{{ printf \"1.2.3.4\" }}"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "10.0.0.1",
|
|
"lan_ipv4": "10.0.0.1",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "advertise address lan with ports",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"ports": {
|
|
"server": 1000,
|
|
"serf_lan": 2000,
|
|
"serf_wan": 3000
|
|
},
|
|
"advertise_addr": "1.2.3.4"
|
|
}`},
|
|
hcl: []string{`
|
|
ports {
|
|
server = 1000
|
|
serf_lan = 2000
|
|
serf_wan = 3000
|
|
}
|
|
advertise_addr = "1.2.3.4"
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("1.2.3.4")
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.2.3.4:1000")
|
|
rt.RPCBindAddr = tcpAddr("0.0.0.0:1000")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.2.3.4:2000")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:3000")
|
|
rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:2000")
|
|
rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:3000")
|
|
rt.SerfPortLAN = 2000
|
|
rt.SerfPortWAN = 3000
|
|
rt.ServerPort = 1000
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.2.3.4",
|
|
"lan_ipv4": "1.2.3.4",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "advertise address wan with ports",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"ports": {
|
|
"server": 1000,
|
|
"serf_lan": 2000,
|
|
"serf_wan": 3000
|
|
},
|
|
"advertise_addr_wan": "1.2.3.4"
|
|
}`},
|
|
hcl: []string{`
|
|
ports {
|
|
server = 1000
|
|
serf_lan = 2000
|
|
serf_wan = 3000
|
|
}
|
|
advertise_addr_wan = "1.2.3.4"
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("10.0.0.1")
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.RPCAdvertiseAddr = tcpAddr("10.0.0.1:1000")
|
|
rt.RPCBindAddr = tcpAddr("0.0.0.0:1000")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("10.0.0.1:2000")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("1.2.3.4:3000")
|
|
rt.SerfBindAddrLAN = tcpAddr("0.0.0.0:2000")
|
|
rt.SerfBindAddrWAN = tcpAddr("0.0.0.0:3000")
|
|
rt.SerfPortLAN = 2000
|
|
rt.SerfPortWAN = 3000
|
|
rt.ServerPort = 1000
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "10.0.0.1",
|
|
"lan_ipv4": "10.0.0.1",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "allow disabling serf wan port",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"ports": {
|
|
"serf_wan": -1
|
|
},
|
|
"advertise_addr_wan": "1.2.3.4"
|
|
}`},
|
|
hcl: []string{`
|
|
ports {
|
|
serf_wan = -1
|
|
}
|
|
advertise_addr_wan = "1.2.3.4"
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrWAN = ipAddr("1.2.3.4")
|
|
rt.SerfAdvertiseAddrWAN = nil
|
|
rt.SerfBindAddrWAN = nil
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "10.0.0.1",
|
|
"lan_ipv4": "10.0.0.1",
|
|
"wan": "1.2.3.4",
|
|
"wan_ipv4": "1.2.3.4",
|
|
}
|
|
rt.DataDir = dataDir
|
|
rt.SerfPortWAN = -1
|
|
},
|
|
},
|
|
{
|
|
desc: "serf bind address lan template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "serf_lan": "{{ printf \"1.2.3.4\" }}" }`},
|
|
hcl: []string{`serf_lan = "{{ printf \"1.2.3.4\" }}"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.SerfBindAddrLAN = tcpAddr("1.2.3.4:8301")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "serf bind address wan template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "serf_wan": "{{ printf \"1.2.3.4\" }}" }`},
|
|
hcl: []string{`serf_wan = "{{ printf \"1.2.3.4\" }}"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.SerfBindAddrWAN = tcpAddr("1.2.3.4:8302")
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "dns recursor templates with deduplication",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "recursors": [ "{{ printf \"5.6.7.8:9999\" }}", "{{ printf \"1.2.3.4\" }}", "{{ printf \"5.6.7.8:9999\" }}" ] }`},
|
|
hcl: []string{`recursors = [ "{{ printf \"5.6.7.8:9999\" }}", "{{ printf \"1.2.3.4\" }}", "{{ printf \"5.6.7.8:9999\" }}" ] `},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DNSRecursors = []string{"5.6.7.8:9999", "1.2.3.4"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "start_join address template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "start_join": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
|
|
hcl: []string{`start_join = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.StartJoinAddrsLAN = []string{"1.2.3.4", "4.3.2.1"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "start_join_wan address template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "start_join_wan": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
|
|
hcl: []string{`start_join_wan = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.StartJoinAddrsWAN = []string{"1.2.3.4", "4.3.2.1"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "retry_join address template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "retry_join": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
|
|
hcl: []string{`retry_join = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinLAN = []string{"1.2.3.4", "4.3.2.1"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "retry_join_wan address template",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "retry_join_wan": ["{{ printf \"1.2.3.4 4.3.2.1\" }}"] }`},
|
|
hcl: []string{`retry_join_wan = ["{{ printf \"1.2.3.4 4.3.2.1\" }}"]`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.RetryJoinWAN = []string{"1.2.3.4", "4.3.2.1"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "min/max ports for dynamic exposed listeners",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"ports": {
|
|
"expose_min_port": 1234,
|
|
"expose_max_port": 5678
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
ports {
|
|
expose_min_port = 1234
|
|
expose_max_port = 5678
|
|
}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ExposeMinPort = 1234
|
|
rt.ExposeMaxPort = 5678
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "defaults for dynamic exposed listeners",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ExposeMinPort = 21500
|
|
rt.ExposeMaxPort = 21755
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
|
|
// ------------------------------------------------------------
|
|
// precedence rules
|
|
//
|
|
|
|
{
|
|
desc: "precedence: merge order",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{
|
|
`{
|
|
"bootstrap": true,
|
|
"bootstrap_expect": 1,
|
|
"datacenter": "a",
|
|
"start_join": ["a", "b"],
|
|
"node_meta": {"a":"b"}
|
|
}`,
|
|
`{
|
|
"bootstrap": false,
|
|
"bootstrap_expect": 0,
|
|
"datacenter":"b",
|
|
"start_join": ["c", "d"],
|
|
"node_meta": {"a":"c"}
|
|
}`,
|
|
},
|
|
hcl: []string{
|
|
`
|
|
bootstrap = true
|
|
bootstrap_expect = 1
|
|
datacenter = "a"
|
|
start_join = ["a", "b"]
|
|
node_meta = { "a" = "b" }
|
|
`,
|
|
`
|
|
bootstrap = false
|
|
bootstrap_expect = 0
|
|
datacenter = "b"
|
|
start_join = ["c", "d"]
|
|
node_meta = { "a" = "c" }
|
|
`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Bootstrap = false
|
|
rt.BootstrapExpect = 0
|
|
rt.Datacenter = "b"
|
|
rt.ACLDatacenter = "b"
|
|
rt.PrimaryDatacenter = "b"
|
|
rt.StartJoinAddrsLAN = []string{"a", "b", "c", "d"}
|
|
rt.NodeMeta = map[string]string{"a": "c"}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "precedence: flag before file",
|
|
json: []string{
|
|
`{
|
|
"advertise_addr": "1.2.3.4",
|
|
"advertise_addr_wan": "5.6.7.8",
|
|
"bootstrap":true,
|
|
"bootstrap_expect": 3,
|
|
"datacenter":"a",
|
|
"node_meta": {"a":"b"},
|
|
"recursors":["1.2.3.5", "5.6.7.9"],
|
|
"serf_lan": "a",
|
|
"serf_wan": "a",
|
|
"start_join":["a", "b"]
|
|
}`,
|
|
},
|
|
hcl: []string{
|
|
`
|
|
advertise_addr = "1.2.3.4"
|
|
advertise_addr_wan = "5.6.7.8"
|
|
bootstrap = true
|
|
bootstrap_expect = 3
|
|
datacenter = "a"
|
|
node_meta = { "a" = "b" }
|
|
recursors = ["1.2.3.5", "5.6.7.9"]
|
|
serf_lan = "a"
|
|
serf_wan = "a"
|
|
start_join = ["a", "b"]
|
|
`,
|
|
},
|
|
args: []string{
|
|
`-advertise=1.1.1.1`,
|
|
`-advertise-wan=2.2.2.2`,
|
|
`-bootstrap=false`,
|
|
`-bootstrap-expect=0`,
|
|
`-datacenter=b`,
|
|
`-data-dir=` + dataDir,
|
|
`-join`, `c`, `-join=d`,
|
|
`-node-meta=a:c`,
|
|
`-recursor`, `1.2.3.6`, `-recursor=5.6.7.10`,
|
|
`-serf-lan-bind=3.3.3.3`,
|
|
`-serf-wan-bind=4.4.4.4`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AdvertiseAddrLAN = ipAddr("1.1.1.1")
|
|
rt.AdvertiseAddrWAN = ipAddr("2.2.2.2")
|
|
rt.RPCAdvertiseAddr = tcpAddr("1.1.1.1:8300")
|
|
rt.SerfAdvertiseAddrLAN = tcpAddr("1.1.1.1:8301")
|
|
rt.SerfAdvertiseAddrWAN = tcpAddr("2.2.2.2:8302")
|
|
rt.Datacenter = "b"
|
|
rt.ACLDatacenter = "b"
|
|
rt.PrimaryDatacenter = "b"
|
|
rt.DNSRecursors = []string{"1.2.3.6", "5.6.7.10", "1.2.3.5", "5.6.7.9"}
|
|
rt.NodeMeta = map[string]string{"a": "c"}
|
|
rt.SerfBindAddrLAN = tcpAddr("3.3.3.3:8301")
|
|
rt.SerfBindAddrWAN = tcpAddr("4.4.4.4:8302")
|
|
rt.StartJoinAddrsLAN = []string{"c", "d", "a", "b"}
|
|
rt.TaggedAddresses = map[string]string{
|
|
"lan": "1.1.1.1",
|
|
"lan_ipv4": "1.1.1.1",
|
|
"wan": "2.2.2.2",
|
|
"wan_ipv4": "2.2.2.2",
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
|
|
// ------------------------------------------------------------
|
|
// transformations
|
|
//
|
|
|
|
{
|
|
desc: "raft performance scaling",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "performance": { "raft_multiplier": 9} }`},
|
|
hcl: []string{`performance = { raft_multiplier=9 }`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ConsulRaftElectionTimeout = 9 * 1000 * time.Millisecond
|
|
rt.ConsulRaftHeartbeatTimeout = 9 * 1000 * time.Millisecond
|
|
rt.ConsulRaftLeaderLeaseTimeout = 9 * 500 * time.Millisecond
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
|
|
{
|
|
desc: "Serf Allowed CIDRS LAN, multiple values from flags",
|
|
args: []string{`-data-dir=` + dataDir, `-serf-lan-allowed-cidrs=127.0.0.0/4`, `-serf-lan-allowed-cidrs=192.168.0.0/24`},
|
|
json: []string{},
|
|
hcl: []string{},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.SerfAllowedCIDRsLAN = []net.IPNet{*(parseCIDR(t, "127.0.0.0/4")), *(parseCIDR(t, "192.168.0.0/24"))}
|
|
},
|
|
},
|
|
{
|
|
desc: "Serf Allowed CIDRS LAN/WAN, multiple values from HCL/JSON",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{"serf_lan_allowed_cidrs": ["127.0.0.0/4", "192.168.0.0/24"]}`,
|
|
`{"serf_wan_allowed_cidrs": ["10.228.85.46/25"]}`},
|
|
hcl: []string{`serf_lan_allowed_cidrs=["127.0.0.0/4", "192.168.0.0/24"]`,
|
|
`serf_wan_allowed_cidrs=["10.228.85.46/25"]`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.SerfAllowedCIDRsLAN = []net.IPNet{*(parseCIDR(t, "127.0.0.0/4")), *(parseCIDR(t, "192.168.0.0/24"))}
|
|
rt.SerfAllowedCIDRsWAN = []net.IPNet{*(parseCIDR(t, "10.228.85.46/25"))}
|
|
},
|
|
},
|
|
{
|
|
desc: "Serf Allowed CIDRS WAN, multiple values from flags",
|
|
args: []string{`-data-dir=` + dataDir, `-serf-wan-allowed-cidrs=192.168.4.0/24`, `-serf-wan-allowed-cidrs=192.168.3.0/24`},
|
|
json: []string{},
|
|
hcl: []string{},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.SerfAllowedCIDRsWAN = []net.IPNet{*(parseCIDR(t, "192.168.4.0/24")), *(parseCIDR(t, "192.168.3.0/24"))}
|
|
},
|
|
},
|
|
|
|
// ------------------------------------------------------------
|
|
// validations
|
|
//
|
|
|
|
{
|
|
desc: "invalid input",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`this is not JSON`},
|
|
hcl: []string{`*** 0123 this is not HCL`},
|
|
err: "failed to parse",
|
|
},
|
|
{
|
|
desc: "datacenter is lower-cased",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "datacenter": "A" }`},
|
|
hcl: []string{`datacenter = "A"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Datacenter = "a"
|
|
rt.ACLDatacenter = "a"
|
|
rt.PrimaryDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "acl_datacenter is lower-cased",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "acl_datacenter": "A" }`},
|
|
hcl: []string{`acl_datacenter = "A"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ACLsEnabled = true
|
|
rt.ACLDatacenter = "a"
|
|
rt.DataDir = dataDir
|
|
rt.PrimaryDatacenter = "a"
|
|
},
|
|
warns: []string{`The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.`},
|
|
},
|
|
{
|
|
desc: "acl_replication_token enables acl replication",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "acl_replication_token": "a" }`},
|
|
hcl: []string{`acl_replication_token = "a"`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ACLTokens.ACLReplicationToken = "a"
|
|
rt.ACLTokenReplication = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "acl_enforce_version_8 is deprecated",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "acl_enforce_version_8": true }`},
|
|
hcl: []string{`acl_enforce_version_8 = true`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{`config key "acl_enforce_version_8" is deprecated and should be removed`},
|
|
},
|
|
|
|
{
|
|
desc: "advertise address detect fails v4",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "0.0.0.0"}`},
|
|
hcl: []string{`bind_addr = "0.0.0.0"`},
|
|
privatev4: func() ([]*net.IPAddr, error) {
|
|
return nil, errors.New("some error")
|
|
},
|
|
err: "Error detecting private IPv4 address: some error",
|
|
},
|
|
{
|
|
desc: "advertise address detect none v4",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "0.0.0.0"}`},
|
|
hcl: []string{`bind_addr = "0.0.0.0"`},
|
|
privatev4: func() ([]*net.IPAddr, error) {
|
|
return nil, nil
|
|
},
|
|
err: "No private IPv4 address found",
|
|
},
|
|
{
|
|
desc: "advertise address detect multiple v4",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "0.0.0.0"}`},
|
|
hcl: []string{`bind_addr = "0.0.0.0"`},
|
|
privatev4: func() ([]*net.IPAddr, error) {
|
|
return []*net.IPAddr{ipAddr("1.1.1.1"), ipAddr("2.2.2.2")}, nil
|
|
},
|
|
err: "Multiple private IPv4 addresses found. Please configure one",
|
|
},
|
|
{
|
|
desc: "advertise address detect fails v6",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "::"}`},
|
|
hcl: []string{`bind_addr = "::"`},
|
|
publicv6: func() ([]*net.IPAddr, error) {
|
|
return nil, errors.New("some error")
|
|
},
|
|
err: "Error detecting public IPv6 address: some error",
|
|
},
|
|
{
|
|
desc: "advertise address detect none v6",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "::"}`},
|
|
hcl: []string{`bind_addr = "::"`},
|
|
publicv6: func() ([]*net.IPAddr, error) {
|
|
return nil, nil
|
|
},
|
|
err: "No public IPv6 address found",
|
|
},
|
|
{
|
|
desc: "advertise address detect multiple v6",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "::"}`},
|
|
hcl: []string{`bind_addr = "::"`},
|
|
publicv6: func() ([]*net.IPAddr, error) {
|
|
return []*net.IPAddr{ipAddr("dead:beef::1"), ipAddr("dead:beef::2")}, nil
|
|
},
|
|
err: "Multiple public IPv6 addresses found. Please configure one",
|
|
},
|
|
{
|
|
desc: "ae_interval invalid == 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
jsontail: []string{`{ "ae_interval": "0s" }`},
|
|
hcltail: []string{`ae_interval = "0s"`},
|
|
err: `ae_interval cannot be 0s. Must be positive`,
|
|
},
|
|
{
|
|
desc: "ae_interval invalid < 0",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
jsontail: []string{`{ "ae_interval": "-1s" }`},
|
|
hcltail: []string{`ae_interval = "-1s"`},
|
|
err: `ae_interval cannot be -1s. Must be positive`,
|
|
},
|
|
{
|
|
desc: "acl_datacenter invalid",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "acl_datacenter": "%" }`},
|
|
hcl: []string{`acl_datacenter = "%"`},
|
|
err: `acl_datacenter can only contain lowercase alphanumeric, - or _ characters.`,
|
|
warns: []string{`The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.`},
|
|
},
|
|
{
|
|
desc: "autopilot.max_trailing_logs invalid",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "autopilot": { "max_trailing_logs": -1 } }`},
|
|
hcl: []string{`autopilot = { max_trailing_logs = -1 }`},
|
|
err: "autopilot.max_trailing_logs cannot be -1. Must be greater than or equal to zero",
|
|
},
|
|
{
|
|
desc: "bind_addr cannot be empty",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "" }`},
|
|
hcl: []string{`bind_addr = ""`},
|
|
err: "bind_addr cannot be empty",
|
|
},
|
|
{
|
|
desc: "bind_addr does not allow multiple addresses",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "1.1.1.1 2.2.2.2" }`},
|
|
hcl: []string{`bind_addr = "1.1.1.1 2.2.2.2"`},
|
|
err: "bind_addr cannot contain multiple addresses",
|
|
},
|
|
{
|
|
desc: "bind_addr cannot be a unix socket",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "bind_addr": "unix:///foo" }`},
|
|
hcl: []string{`bind_addr = "unix:///foo"`},
|
|
err: "bind_addr cannot be a unix socket",
|
|
},
|
|
{
|
|
desc: "bootstrap without server",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap": true }`},
|
|
hcl: []string{`bootstrap = true`},
|
|
err: "'bootstrap = true' requires 'server = true'",
|
|
},
|
|
{
|
|
desc: "bootstrap-expect without server",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap_expect": 3 }`},
|
|
hcl: []string{`bootstrap_expect = 3`},
|
|
err: "'bootstrap_expect > 0' requires 'server = true'",
|
|
},
|
|
{
|
|
desc: "bootstrap-expect invalid",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap_expect": -1 }`},
|
|
hcl: []string{`bootstrap_expect = -1`},
|
|
err: "bootstrap_expect cannot be -1. Must be greater than or equal to zero",
|
|
},
|
|
{
|
|
desc: "bootstrap-expect and dev mode",
|
|
args: []string{
|
|
`-dev`,
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap_expect": 3, "server": true }`},
|
|
hcl: []string{`bootstrap_expect = 3 server = true`},
|
|
err: "'bootstrap_expect > 0' not allowed in dev mode",
|
|
},
|
|
{
|
|
desc: "bootstrap-expect and bootstrap",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap": true, "bootstrap_expect": 3, "server": true }`},
|
|
hcl: []string{`bootstrap = true bootstrap_expect = 3 server = true`},
|
|
err: "'bootstrap_expect > 0' and 'bootstrap = true' are mutually exclusive",
|
|
},
|
|
{
|
|
desc: "bootstrap-expect=1 equals bootstrap",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap_expect": 1, "server": true }`},
|
|
hcl: []string{`bootstrap_expect = 1 server = true`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Bootstrap = true
|
|
rt.BootstrapExpect = 0
|
|
rt.LeaveOnTerm = false
|
|
rt.ServerMode = true
|
|
rt.SkipLeaveOnInt = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{"BootstrapExpect is set to 1; this is the same as Bootstrap mode.", "bootstrap = true: do not enable unless necessary"},
|
|
},
|
|
{
|
|
desc: "bootstrap-expect=2 warning",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap_expect": 2, "server": true }`},
|
|
hcl: []string{`bootstrap_expect = 2 server = true`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.BootstrapExpect = 2
|
|
rt.LeaveOnTerm = false
|
|
rt.ServerMode = true
|
|
rt.SkipLeaveOnInt = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{
|
|
`bootstrap_expect = 2: A cluster with 2 servers will provide no failure tolerance. See https://www.consul.io/docs/internals/consensus.html#deployment-table`,
|
|
`bootstrap_expect > 0: expecting 2 servers`,
|
|
},
|
|
},
|
|
{
|
|
desc: "bootstrap-expect > 2 but even warning",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "bootstrap_expect": 4, "server": true }`},
|
|
hcl: []string{`bootstrap_expect = 4 server = true`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.BootstrapExpect = 4
|
|
rt.LeaveOnTerm = false
|
|
rt.ServerMode = true
|
|
rt.SkipLeaveOnInt = true
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{
|
|
`bootstrap_expect is even number: A cluster with an even number of servers does not achieve optimum fault tolerance. See https://www.consul.io/docs/internals/consensus.html#deployment-table`,
|
|
`bootstrap_expect > 0: expecting 4 servers`,
|
|
},
|
|
},
|
|
{
|
|
desc: "client mode sets LeaveOnTerm and SkipLeaveOnInt correctly",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "server": false }`},
|
|
hcl: []string{` server = false`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.LeaveOnTerm = true
|
|
rt.ServerMode = false
|
|
rt.SkipLeaveOnInt = false
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "client does not allow socket",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "client_addr": "unix:///foo" }`},
|
|
hcl: []string{`client_addr = "unix:///foo"`},
|
|
err: "client_addr cannot be a unix socket",
|
|
},
|
|
{
|
|
desc: "datacenter invalid",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{ "datacenter": "%" }`},
|
|
hcl: []string{`datacenter = "%"`},
|
|
err: `datacenter can only contain lowercase alphanumeric, - or _ characters.`,
|
|
},
|
|
{
|
|
desc: "dns does not allow socket",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "addresses": {"dns": "unix:///foo" } }`},
|
|
hcl: []string{`addresses = { dns = "unix:///foo" }`},
|
|
err: "DNS address cannot be a unix socket",
|
|
},
|
|
{
|
|
desc: "ui enabled and dir specified",
|
|
args: []string{
|
|
`-datacenter=a`,
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
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
|
|
// to avoid combinatory explosion for tests use 0.0.0.0, :: or [::] but not all of them
|
|
{
|
|
desc: "advertise_addr any",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "advertise_addr": "0.0.0.0" }`},
|
|
hcl: []string{`advertise_addr = "0.0.0.0"`},
|
|
err: "Advertise address cannot be 0.0.0.0, :: or [::]",
|
|
},
|
|
{
|
|
desc: "advertise_addr_wan any",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "advertise_addr_wan": "::" }`},
|
|
hcl: []string{`advertise_addr_wan = "::"`},
|
|
err: "Advertise WAN address cannot be 0.0.0.0, :: or [::]",
|
|
},
|
|
{
|
|
desc: "recursors any",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "recursors": ["::"] }`},
|
|
hcl: []string{`recursors = ["::"]`},
|
|
err: "DNS recursor address cannot be 0.0.0.0, :: or [::]",
|
|
},
|
|
{
|
|
desc: "dns_config.udp_answer_limit invalid",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "dns_config": { "udp_answer_limit": -1 } }`},
|
|
hcl: []string{`dns_config = { udp_answer_limit = -1 }`},
|
|
err: "dns_config.udp_answer_limit cannot be -1. Must be greater than or equal to zero",
|
|
},
|
|
{
|
|
desc: "dns_config.a_record_limit invalid",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "dns_config": { "a_record_limit": -1 } }`},
|
|
hcl: []string{`dns_config = { a_record_limit = -1 }`},
|
|
err: "dns_config.a_record_limit cannot be -1. Must be greater than or equal to zero",
|
|
},
|
|
{
|
|
desc: "performance.raft_multiplier < 0",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "performance": { "raft_multiplier": -1 } }`},
|
|
hcl: []string{`performance = { raft_multiplier = -1 }`},
|
|
err: `performance.raft_multiplier cannot be -1. Must be between 1 and 10`,
|
|
},
|
|
{
|
|
desc: "performance.raft_multiplier == 0",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "performance": { "raft_multiplier": 0 } }`},
|
|
hcl: []string{`performance = { raft_multiplier = 0 }`},
|
|
err: `performance.raft_multiplier cannot be 0. Must be between 1 and 10`,
|
|
},
|
|
{
|
|
desc: "performance.raft_multiplier > 10",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "performance": { "raft_multiplier": 20 } }`},
|
|
hcl: []string{`performance = { raft_multiplier = 20 }`},
|
|
err: `performance.raft_multiplier cannot be 20. Must be between 1 and 10`,
|
|
},
|
|
{
|
|
desc: "node_name invalid",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-node=`,
|
|
},
|
|
hostname: func() (string, error) { return "", nil },
|
|
err: "node_name cannot be empty",
|
|
},
|
|
{
|
|
desc: "node_meta key too long",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "dns_config": { "udp_answer_limit": 1 } }`,
|
|
`{ "node_meta": { "` + randomString(130) + `": "a" } }`,
|
|
},
|
|
hcl: []string{
|
|
`dns_config = { udp_answer_limit = 1 }`,
|
|
`node_meta = { "` + randomString(130) + `" = "a" }`,
|
|
},
|
|
err: "Key is too long (limit: 128 characters)",
|
|
},
|
|
{
|
|
desc: "node_meta value too long",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "dns_config": { "udp_answer_limit": 1 } }`,
|
|
`{ "node_meta": { "a": "` + randomString(520) + `" } }`,
|
|
},
|
|
hcl: []string{
|
|
`dns_config = { udp_answer_limit = 1 }`,
|
|
`node_meta = { "a" = "` + randomString(520) + `" }`,
|
|
},
|
|
err: "Value is too long (limit: 512 characters)",
|
|
},
|
|
{
|
|
desc: "node_meta too many keys",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "dns_config": { "udp_answer_limit": 1 } }`,
|
|
`{ "node_meta": {` + metaPairs(70, "json") + `} }`,
|
|
},
|
|
hcl: []string{
|
|
`dns_config = { udp_answer_limit = 1 }`,
|
|
`node_meta = {` + metaPairs(70, "hcl") + ` }`,
|
|
},
|
|
err: "Node metadata cannot contain more than 64 key/value pairs",
|
|
},
|
|
{
|
|
desc: "unique listeners dns vs http",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"client_addr": "1.2.3.4",
|
|
"ports": { "dns": 1000, "http": 1000 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "1.2.3.4"
|
|
ports = { dns = 1000 http = 1000 }
|
|
`},
|
|
err: "HTTP address 1.2.3.4:1000 already configured for DNS",
|
|
},
|
|
{
|
|
desc: "unique listeners dns vs https",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"client_addr": "1.2.3.4",
|
|
"ports": { "dns": 1000, "https": 1000 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "1.2.3.4"
|
|
ports = { dns = 1000 https = 1000 }
|
|
`},
|
|
err: "HTTPS address 1.2.3.4:1000 already configured for DNS",
|
|
},
|
|
{
|
|
desc: "unique listeners http vs https",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"client_addr": "1.2.3.4",
|
|
"ports": { "http": 1000, "https": 1000 }
|
|
}`},
|
|
hcl: []string{`
|
|
client_addr = "1.2.3.4"
|
|
ports = { http = 1000 https = 1000 }
|
|
`},
|
|
err: "HTTPS address 1.2.3.4:1000 already configured for HTTP",
|
|
},
|
|
{
|
|
desc: "unique advertise addresses HTTP vs RPC",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"addresses": { "http": "10.0.0.1" },
|
|
"ports": { "http": 1000, "server": 1000 }
|
|
}`},
|
|
hcl: []string{`
|
|
addresses = { http = "10.0.0.1" }
|
|
ports = { http = 1000 server = 1000 }
|
|
`},
|
|
err: "RPC Advertise address 10.0.0.1:1000 already configured for HTTP",
|
|
},
|
|
{
|
|
desc: "unique advertise addresses RPC vs Serf LAN",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"ports": { "server": 1000, "serf_lan": 1000 }
|
|
}`},
|
|
hcl: []string{`
|
|
ports = { server = 1000 serf_lan = 1000 }
|
|
`},
|
|
err: "Serf Advertise LAN address 10.0.0.1:1000 already configured for RPC Advertise",
|
|
},
|
|
{
|
|
desc: "unique advertise addresses RPC vs Serf WAN",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"ports": { "server": 1000, "serf_wan": 1000 }
|
|
}`},
|
|
hcl: []string{`
|
|
ports = { server = 1000 serf_wan = 1000 }
|
|
`},
|
|
err: "Serf Advertise WAN address 10.0.0.1:1000 already configured for RPC Advertise",
|
|
},
|
|
{
|
|
desc: "http use_cache defaults to true",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"http_config": {}
|
|
}`},
|
|
hcl: []string{`
|
|
http_config = {}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.HTTPUseCache = true
|
|
},
|
|
},
|
|
{
|
|
desc: "http use_cache is enabled when true",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"http_config": { "use_cache": true }
|
|
}`},
|
|
hcl: []string{`
|
|
http_config = { use_cache = true }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.HTTPUseCache = true
|
|
},
|
|
},
|
|
{
|
|
desc: "http use_cache is disabled when false",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"http_config": { "use_cache": false }
|
|
}`},
|
|
hcl: []string{`
|
|
http_config = { use_cache = false }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.HTTPUseCache = false
|
|
},
|
|
},
|
|
{
|
|
desc: "sidecar_service can't have ID",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"service": {
|
|
"name": "web",
|
|
"port": 1234,
|
|
"connect": {
|
|
"sidecar_service": {
|
|
"ID": "random-sidecar-id"
|
|
}
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
service {
|
|
name = "web"
|
|
port = 1234
|
|
connect {
|
|
sidecar_service {
|
|
ID = "random-sidecar-id"
|
|
}
|
|
}
|
|
}
|
|
`},
|
|
err: "sidecar_service can't specify an ID",
|
|
},
|
|
{
|
|
desc: "sidecar_service can't have nested sidecar",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"service": {
|
|
"name": "web",
|
|
"port": 1234,
|
|
"connect": {
|
|
"sidecar_service": {
|
|
"connect": {
|
|
"sidecar_service": {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
service {
|
|
name = "web"
|
|
port = 1234
|
|
connect {
|
|
sidecar_service {
|
|
connect {
|
|
sidecar_service {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`},
|
|
err: "sidecar_service can't have a nested sidecar_service",
|
|
},
|
|
{
|
|
desc: "telemetry.prefix_filter cannot be empty",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"telemetry": { "prefix_filter": [""] }
|
|
}`},
|
|
hcl: []string{`
|
|
telemetry = { prefix_filter = [""] }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
},
|
|
warns: []string{"Cannot have empty filter rule in prefix_filter"},
|
|
},
|
|
{
|
|
desc: "telemetry.prefix_filter must start with + or -",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"telemetry": { "prefix_filter": ["+foo", "-bar", "nix"] }
|
|
}`},
|
|
hcl: []string{`
|
|
telemetry = { prefix_filter = ["+foo", "-bar", "nix"] }
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.Telemetry.AllowedPrefixes = []string{"foo"}
|
|
rt.Telemetry.BlockedPrefixes = []string{"consul.api.http", "bar"}
|
|
},
|
|
warns: []string{`Filter rule must begin with either '+' or '-': "nix"`},
|
|
},
|
|
{
|
|
desc: "encrypt has invalid key",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{ "encrypt": "this is not a valid key" }`},
|
|
hcl: []string{` encrypt = "this is not a valid key" `},
|
|
err: "encrypt has invalid key: illegal base64 data at input byte 4",
|
|
},
|
|
{
|
|
desc: "multiple check files",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "check": { "name": "a", "args": ["/bin/true"] } }`,
|
|
`{ "check": { "name": "b", "args": ["/bin/false"] } }`,
|
|
},
|
|
hcl: []string{
|
|
`check = { name = "a" args = ["/bin/true"] }`,
|
|
`check = { name = "b" args = ["/bin/false"] }`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Checks = []*structs.CheckDefinition{
|
|
{Name: "a", ScriptArgs: []string{"/bin/true"}, OutputMaxSize: checks.DefaultBufSize},
|
|
{Name: "b", ScriptArgs: []string{"/bin/false"}, OutputMaxSize: checks.DefaultBufSize},
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "grpc check",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "check": { "name": "a", "grpc": "localhost:12345/foo", "grpc_use_tls": true } }`,
|
|
},
|
|
hcl: []string{
|
|
`check = { name = "a" grpc = "localhost:12345/foo", grpc_use_tls = true }`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Checks = []*structs.CheckDefinition{
|
|
{Name: "a", GRPC: "localhost:12345/foo", GRPCUseTLS: true, OutputMaxSize: checks.DefaultBufSize},
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "alias check with no node",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "check": { "name": "a", "alias_service": "foo" } }`,
|
|
},
|
|
hcl: []string{
|
|
`check = { name = "a", alias_service = "foo" }`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Checks = []*structs.CheckDefinition{
|
|
{Name: "a", AliasService: "foo", OutputMaxSize: checks.DefaultBufSize},
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "multiple service files",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "service": { "name": "a", "port": 80 } }`,
|
|
`{ "service": { "name": "b", "port": 90, "meta": {"my": "value"}, "weights": {"passing": 13} } }`,
|
|
},
|
|
hcl: []string{
|
|
`service = { name = "a" port = 80 }`,
|
|
`service = { name = "b" port = 90 meta={my="value"}, weights={passing=13}}`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Services = []*structs.ServiceDefinition{
|
|
{
|
|
Name: "a",
|
|
Port: 80,
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "b",
|
|
Port: 90,
|
|
Meta: map[string]string{"my": "value"},
|
|
Weights: &structs.Weights{
|
|
Passing: 13,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "service with wrong meta: too long key",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "service": { "name": "a", "port": 80, "meta": { "` + randomString(520) + `": "metaValue" } } }`,
|
|
},
|
|
hcl: []string{
|
|
`service = { name = "a" port = 80, meta={` + randomString(520) + `="metaValue"} }`,
|
|
},
|
|
err: `Key is too long`,
|
|
},
|
|
{
|
|
desc: "service with wrong meta: too long value",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "service": { "name": "a", "port": 80, "meta": { "a": "` + randomString(520) + `" } } }`,
|
|
},
|
|
hcl: []string{
|
|
`service = { name = "a" port = 80, meta={a="` + randomString(520) + `"} }`,
|
|
},
|
|
err: `Value is too long`,
|
|
},
|
|
{
|
|
desc: "service with wrong meta: too many meta",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "service": { "name": "a", "port": 80, "meta": { ` + metaPairs(70, "json") + `} } }`,
|
|
},
|
|
hcl: []string{
|
|
`service = { name = "a" port = 80 meta={` + metaPairs(70, "hcl") + `} }`,
|
|
},
|
|
err: `invalid meta for service a: Node metadata cannot contain more than 64 key`,
|
|
},
|
|
{
|
|
desc: "translated keys",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{
|
|
"service": {
|
|
"name": "a",
|
|
"port": 80,
|
|
"tagged_addresses": {
|
|
"wan": {
|
|
"address": "198.18.3.4",
|
|
"port": 443
|
|
}
|
|
},
|
|
"enable_tag_override": true,
|
|
"check": {
|
|
"id": "x",
|
|
"name": "y",
|
|
"DockerContainerID": "z",
|
|
"DeregisterCriticalServiceAfter": "10s",
|
|
"ScriptArgs": ["a", "b"]
|
|
}
|
|
}
|
|
}`,
|
|
},
|
|
hcl: []string{
|
|
`service = {
|
|
name = "a"
|
|
port = 80
|
|
enable_tag_override = true
|
|
tagged_addresses = {
|
|
wan = {
|
|
address = "198.18.3.4"
|
|
port = 443
|
|
}
|
|
}
|
|
check = {
|
|
id = "x"
|
|
name = "y"
|
|
DockerContainerID = "z"
|
|
DeregisterCriticalServiceAfter = "10s"
|
|
ScriptArgs = ["a", "b"]
|
|
}
|
|
}`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.Services = []*structs.ServiceDefinition{
|
|
{
|
|
Name: "a",
|
|
Port: 80,
|
|
TaggedAddresses: map[string]structs.ServiceAddress{
|
|
"wan": {
|
|
Address: "198.18.3.4",
|
|
Port: 443,
|
|
},
|
|
},
|
|
EnableTagOverride: true,
|
|
Checks: []*structs.CheckType{
|
|
{
|
|
CheckID: types.CheckID("x"),
|
|
Name: "y",
|
|
DockerContainerID: "z",
|
|
DeregisterCriticalServiceAfter: 10 * time.Second,
|
|
ScriptArgs: []string{"a", "b"},
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
}
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
{
|
|
desc: "ignore snapshot_agent sub-object",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{
|
|
`{ "snapshot_agent": { "dont": "care" } }`,
|
|
},
|
|
hcl: []string{
|
|
`snapshot_agent = { dont = "care" }`,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
},
|
|
},
|
|
|
|
{
|
|
// Test that slices in structured config are preserved by
|
|
// decode.HookWeakDecodeFromSlice.
|
|
desc: "service.connectsidecar_service with checks and upstreams",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"service": {
|
|
"name": "web",
|
|
"port": 1234,
|
|
"connect": {
|
|
"sidecar_service": {
|
|
"port": 2345,
|
|
"checks": [
|
|
{
|
|
"TCP": "127.0.0.1:2345",
|
|
"Interval": "10s"
|
|
}
|
|
],
|
|
"proxy": {
|
|
"expose": {
|
|
"checks": true,
|
|
"paths": [
|
|
{
|
|
"path": "/health",
|
|
"local_path_port": 8080,
|
|
"listener_port": 21500,
|
|
"protocol": "http"
|
|
}
|
|
]
|
|
},
|
|
"upstreams": [
|
|
{
|
|
"destination_name": "db",
|
|
"local_bind_port": 7000
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
service {
|
|
name = "web"
|
|
port = 1234
|
|
connect {
|
|
sidecar_service {
|
|
port = 2345
|
|
checks = [
|
|
{
|
|
tcp = "127.0.0.1:2345"
|
|
interval = "10s"
|
|
}
|
|
]
|
|
proxy {
|
|
expose {
|
|
checks = true
|
|
paths = [
|
|
{
|
|
path = "/health"
|
|
local_path_port = 8080
|
|
listener_port = 21500
|
|
protocol = "http"
|
|
}
|
|
]
|
|
},
|
|
upstreams = [
|
|
{
|
|
destination_name = "db"
|
|
local_bind_port = 7000
|
|
},
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.Services = []*structs.ServiceDefinition{
|
|
{
|
|
Name: "web",
|
|
Port: 1234,
|
|
Connect: &structs.ServiceConnect{
|
|
SidecarService: &structs.ServiceDefinition{
|
|
Port: 2345,
|
|
Checks: structs.CheckTypes{
|
|
{
|
|
TCP: "127.0.0.1:2345",
|
|
Interval: 10 * time.Second,
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
},
|
|
},
|
|
Proxy: &structs.ConnectProxyConfig{
|
|
Expose: structs.ExposeConfig{
|
|
Checks: true,
|
|
Paths: []structs.ExposePath{
|
|
{
|
|
Path: "/health",
|
|
LocalPathPort: 8080,
|
|
ListenerPort: 21500,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
Upstreams: structs.Upstreams{
|
|
structs.Upstream{
|
|
DestinationType: "service",
|
|
DestinationName: "db",
|
|
LocalBindPort: 7000,
|
|
},
|
|
},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
// Test that slices in structured config are preserved by
|
|
// decode.HookWeakDecodeFromSlice.
|
|
desc: "services.connect.sidecar_service with checks and upstreams",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"services": [{
|
|
"name": "web",
|
|
"port": 1234,
|
|
"connect": {
|
|
"sidecar_service": {
|
|
"port": 2345,
|
|
"checks": [
|
|
{
|
|
"TCP": "127.0.0.1:2345",
|
|
"Interval": "10s"
|
|
}
|
|
],
|
|
"proxy": {
|
|
"expose": {
|
|
"checks": true,
|
|
"paths": [
|
|
{
|
|
"path": "/health",
|
|
"local_path_port": 8080,
|
|
"listener_port": 21500,
|
|
"protocol": "http"
|
|
}
|
|
]
|
|
},
|
|
"upstreams": [
|
|
{
|
|
"destination_name": "db",
|
|
"local_bind_port": 7000
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}]
|
|
}`},
|
|
hcl: []string{`
|
|
services = [{
|
|
name = "web"
|
|
port = 1234
|
|
connect {
|
|
sidecar_service {
|
|
port = 2345
|
|
checks = [
|
|
{
|
|
tcp = "127.0.0.1:2345"
|
|
interval = "10s"
|
|
}
|
|
]
|
|
proxy {
|
|
expose {
|
|
checks = true
|
|
paths = [
|
|
{
|
|
path = "/health"
|
|
local_path_port = 8080
|
|
listener_port = 21500
|
|
protocol = "http"
|
|
}
|
|
]
|
|
},
|
|
upstreams = [
|
|
{
|
|
destination_name = "db"
|
|
local_bind_port = 7000
|
|
},
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}]
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.Services = []*structs.ServiceDefinition{
|
|
{
|
|
Name: "web",
|
|
Port: 1234,
|
|
Connect: &structs.ServiceConnect{
|
|
SidecarService: &structs.ServiceDefinition{
|
|
Port: 2345,
|
|
Checks: structs.CheckTypes{
|
|
{
|
|
TCP: "127.0.0.1:2345",
|
|
Interval: 10 * time.Second,
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
},
|
|
},
|
|
Proxy: &structs.ConnectProxyConfig{
|
|
Expose: structs.ExposeConfig{
|
|
Checks: true,
|
|
Paths: []structs.ExposePath{
|
|
{
|
|
Path: "/health",
|
|
LocalPathPort: 8080,
|
|
ListenerPort: 21500,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
Upstreams: structs.Upstreams{
|
|
structs.Upstream{
|
|
DestinationType: "service",
|
|
DestinationName: "db",
|
|
LocalBindPort: 7000,
|
|
},
|
|
},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
// This tests checks that VerifyServerHostname implies VerifyOutgoing
|
|
desc: "verify_server_hostname implies verify_outgoing",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"verify_server_hostname": true
|
|
}`},
|
|
hcl: []string{`
|
|
verify_server_hostname = true
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.VerifyServerHostname = true
|
|
rt.VerifyOutgoing = true
|
|
},
|
|
},
|
|
{
|
|
desc: "auto_encrypt.allow_tls works implies connect",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"verify_incoming": true,
|
|
"auto_encrypt": { "allow_tls": true },
|
|
"server": true
|
|
}`},
|
|
hcl: []string{`
|
|
verify_incoming = true
|
|
auto_encrypt { allow_tls = true }
|
|
server = true
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.VerifyIncoming = true
|
|
rt.AutoEncryptAllowTLS = true
|
|
rt.ConnectEnabled = true
|
|
|
|
// server things
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
},
|
|
},
|
|
{
|
|
desc: "auto_encrypt.allow_tls works with verify_incoming",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"verify_incoming": true,
|
|
"auto_encrypt": { "allow_tls": true },
|
|
"server": true
|
|
}`},
|
|
hcl: []string{`
|
|
verify_incoming = true
|
|
auto_encrypt { allow_tls = true }
|
|
server = true
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.VerifyIncoming = true
|
|
rt.AutoEncryptAllowTLS = true
|
|
rt.ConnectEnabled = true
|
|
|
|
// server things
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
},
|
|
},
|
|
{
|
|
desc: "auto_encrypt.allow_tls works with verify_incoming_rpc",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"verify_incoming_rpc": true,
|
|
"auto_encrypt": { "allow_tls": true },
|
|
"server": true
|
|
}`},
|
|
hcl: []string{`
|
|
verify_incoming_rpc = true
|
|
auto_encrypt { allow_tls = true }
|
|
server = true
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.VerifyIncomingRPC = true
|
|
rt.AutoEncryptAllowTLS = true
|
|
rt.ConnectEnabled = true
|
|
|
|
// server things
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
},
|
|
},
|
|
{
|
|
desc: "auto_encrypt.allow_tls warns without verify_incoming or verify_incoming_rpc",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"auto_encrypt": { "allow_tls": true },
|
|
"server": true
|
|
}`},
|
|
hcl: []string{`
|
|
auto_encrypt { allow_tls = true }
|
|
server = true
|
|
`},
|
|
warns: []string{"if auto_encrypt.allow_tls is turned on, either verify_incoming or verify_incoming_rpc should be enabled. It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards."},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.AutoEncryptAllowTLS = true
|
|
rt.ConnectEnabled = true
|
|
// server things
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
},
|
|
},
|
|
{
|
|
desc: "auto_encrypt.allow_tls errors in client mode",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"auto_encrypt": { "allow_tls": true },
|
|
"server": false
|
|
}`},
|
|
hcl: []string{`
|
|
auto_encrypt { allow_tls = true }
|
|
server = false
|
|
`},
|
|
err: "auto_encrypt.allow_tls can only be used on a server.",
|
|
},
|
|
{
|
|
desc: "auto_encrypt.tls errors in server mode",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"auto_encrypt": { "tls": true },
|
|
"server": true
|
|
}`},
|
|
hcl: []string{`
|
|
auto_encrypt { tls = true }
|
|
server = true
|
|
`},
|
|
err: "auto_encrypt.tls can only be used on a client.",
|
|
},
|
|
{
|
|
desc: "test connect vault provider configuration",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"connect": {
|
|
"enabled": true,
|
|
"ca_provider": "vault",
|
|
"ca_config": {
|
|
"ca_file": "/capath/ca.pem",
|
|
"ca_path": "/capath/",
|
|
"cert_file": "/certpath/cert.pem",
|
|
"key_file": "/certpath/key.pem",
|
|
"tls_server_name": "server.name",
|
|
"tls_skip_verify": true,
|
|
"token": "abc",
|
|
"root_pki_path": "consul-vault",
|
|
"intermediate_pki_path": "connect-intermediate"
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
connect {
|
|
enabled = true
|
|
ca_provider = "vault"
|
|
ca_config {
|
|
ca_file = "/capath/ca.pem"
|
|
ca_path = "/capath/"
|
|
cert_file = "/certpath/cert.pem"
|
|
key_file = "/certpath/key.pem"
|
|
tls_server_name = "server.name"
|
|
tls_skip_verify = true
|
|
token = "abc"
|
|
root_pki_path = "consul-vault"
|
|
intermediate_pki_path = "connect-intermediate"
|
|
}
|
|
}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConnectEnabled = true
|
|
rt.ConnectCAProvider = "vault"
|
|
rt.ConnectCAConfig = map[string]interface{}{
|
|
"CAFile": "/capath/ca.pem",
|
|
"CAPath": "/capath/",
|
|
"CertFile": "/certpath/cert.pem",
|
|
"KeyFile": "/certpath/key.pem",
|
|
"TLSServerName": "server.name",
|
|
"TLSSkipVerify": true,
|
|
"Token": "abc",
|
|
"RootPKIPath": "consul-vault",
|
|
"IntermediatePKIPath": "connect-intermediate",
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "Connect AWS CA provider configuration",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"connect": {
|
|
"enabled": true,
|
|
"ca_provider": "aws-pca",
|
|
"ca_config": {
|
|
"existing_arn": "foo",
|
|
"delete_on_exit": true
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
connect {
|
|
enabled = true
|
|
ca_provider = "aws-pca"
|
|
ca_config {
|
|
existing_arn = "foo"
|
|
delete_on_exit = true
|
|
}
|
|
}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConnectEnabled = true
|
|
rt.ConnectCAProvider = "aws-pca"
|
|
rt.ConnectCAConfig = map[string]interface{}{
|
|
"ExistingARN": "foo",
|
|
"DeleteOnExit": true,
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "Connect AWS CA provider TTL validation",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"connect": {
|
|
"enabled": true,
|
|
"ca_provider": "aws-pca",
|
|
"ca_config": {
|
|
"leaf_cert_ttl": "1h"
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
connect {
|
|
enabled = true
|
|
ca_provider = "aws-pca"
|
|
ca_config {
|
|
leaf_cert_ttl = "1h"
|
|
}
|
|
}
|
|
`},
|
|
err: "AWS PCA doesn't support certificates that are valid for less than 24 hours",
|
|
},
|
|
{
|
|
desc: "Connect AWS CA provider EC key length validation",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"connect": {
|
|
"enabled": true,
|
|
"ca_provider": "aws-pca",
|
|
"ca_config": {
|
|
"private_key_bits": 521
|
|
}
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
connect {
|
|
enabled = true
|
|
ca_provider = "aws-pca"
|
|
ca_config {
|
|
private_key_bits = 521
|
|
}
|
|
}
|
|
`},
|
|
err: "AWS PCA only supports P256 EC curve",
|
|
},
|
|
{
|
|
desc: "connect.enable_mesh_gateway_wan_federation requires connect.enabled",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"connect": {
|
|
"enabled": false,
|
|
"enable_mesh_gateway_wan_federation": true
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
connect {
|
|
enabled = false
|
|
enable_mesh_gateway_wan_federation = true
|
|
}
|
|
`},
|
|
err: "'connect.enable_mesh_gateway_wan_federation=true' requires 'connect.enabled=true'",
|
|
},
|
|
{
|
|
desc: "connect.enable_mesh_gateway_wan_federation cannot use -join-wan",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-join-wan=1.2.3.4`,
|
|
},
|
|
json: []string{`{
|
|
"server": true,
|
|
"primary_datacenter": "one",
|
|
"datacenter": "one",
|
|
"connect": {
|
|
"enabled": true,
|
|
"enable_mesh_gateway_wan_federation": true
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
server = true
|
|
primary_datacenter = "one"
|
|
datacenter = "one"
|
|
connect {
|
|
enabled = true
|
|
enable_mesh_gateway_wan_federation = true
|
|
}
|
|
`},
|
|
err: "'start_join_wan' is incompatible with 'connect.enable_mesh_gateway_wan_federation = true'",
|
|
},
|
|
{
|
|
desc: "connect.enable_mesh_gateway_wan_federation cannot use -retry-join-wan",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-retry-join-wan=1.2.3.4`,
|
|
},
|
|
json: []string{`{
|
|
"server": true,
|
|
"primary_datacenter": "one",
|
|
"datacenter": "one",
|
|
"connect": {
|
|
"enabled": true,
|
|
"enable_mesh_gateway_wan_federation": true
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
server = true
|
|
primary_datacenter = "one"
|
|
datacenter = "one"
|
|
connect {
|
|
enabled = true
|
|
enable_mesh_gateway_wan_federation = true
|
|
}
|
|
`},
|
|
err: "'retry_join_wan' is incompatible with 'connect.enable_mesh_gateway_wan_federation = true'",
|
|
},
|
|
{
|
|
desc: "connect.enable_mesh_gateway_wan_federation requires server mode",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"server": false,
|
|
"connect": {
|
|
"enabled": true,
|
|
"enable_mesh_gateway_wan_federation": true
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
server = false
|
|
connect {
|
|
enabled = true
|
|
enable_mesh_gateway_wan_federation = true
|
|
}
|
|
`},
|
|
err: "'connect.enable_mesh_gateway_wan_federation = true' requires 'server = true'",
|
|
},
|
|
{
|
|
desc: "connect.enable_mesh_gateway_wan_federation requires no slashes in node names",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"server": true,
|
|
"node_name": "really/why",
|
|
"connect": {
|
|
"enabled": true,
|
|
"enable_mesh_gateway_wan_federation": true
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
server = true
|
|
node_name = "really/why"
|
|
connect {
|
|
enabled = true
|
|
enable_mesh_gateway_wan_federation = true
|
|
}
|
|
`},
|
|
err: "'connect.enable_mesh_gateway_wan_federation = true' requires that 'node_name' not contain '/' characters",
|
|
},
|
|
{
|
|
desc: "primary_gateways requires server mode",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"server": false,
|
|
"primary_gateways": [ "foo.local", "bar.local" ]
|
|
}`},
|
|
hcl: []string{`
|
|
server = false
|
|
primary_gateways = [ "foo.local", "bar.local" ]
|
|
`},
|
|
err: "'primary_gateways' requires 'server = true'",
|
|
},
|
|
{
|
|
desc: "primary_gateways only works in a secondary datacenter",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"server": true,
|
|
"primary_datacenter": "one",
|
|
"datacenter": "one",
|
|
"primary_gateways": [ "foo.local", "bar.local" ]
|
|
}`},
|
|
hcl: []string{`
|
|
server = true
|
|
primary_datacenter = "one"
|
|
datacenter = "one"
|
|
primary_gateways = [ "foo.local", "bar.local" ]
|
|
`},
|
|
err: "'primary_gateways' should only be configured in a secondary datacenter",
|
|
},
|
|
{
|
|
desc: "connect.enable_mesh_gateway_wan_federation in secondary with primary_gateways configured",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
json: []string{`{
|
|
"server": true,
|
|
"primary_datacenter": "one",
|
|
"datacenter": "two",
|
|
"primary_gateways": [ "foo.local", "bar.local" ],
|
|
"connect": {
|
|
"enabled": true,
|
|
"enable_mesh_gateway_wan_federation": true
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
server = true
|
|
primary_datacenter = "one"
|
|
datacenter = "two"
|
|
primary_gateways = [ "foo.local", "bar.local" ]
|
|
connect {
|
|
enabled = true
|
|
enable_mesh_gateway_wan_federation = true
|
|
}
|
|
`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.Datacenter = "two"
|
|
rt.PrimaryDatacenter = "one"
|
|
rt.ACLDatacenter = "one"
|
|
rt.PrimaryGateways = []string{"foo.local", "bar.local"}
|
|
rt.ConnectEnabled = true
|
|
rt.ConnectMeshGatewayWANFederationEnabled = true
|
|
// server things
|
|
rt.ServerMode = true
|
|
rt.LeaveOnTerm = false
|
|
rt.SkipLeaveOnInt = true
|
|
},
|
|
},
|
|
|
|
// ------------------------------------------------------------
|
|
// ConfigEntry Handling
|
|
//
|
|
{
|
|
desc: "ConfigEntry bootstrap doesn't parse",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"foo": "bar"
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
foo = "bar"
|
|
}
|
|
}`},
|
|
err: "config_entries.bootstrap[0]: Payload does not contain a kind/Kind",
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap unknown kind",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"kind": "foo",
|
|
"name": "bar",
|
|
"baz": 1
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
kind = "foo"
|
|
name = "bar"
|
|
baz = 1
|
|
}
|
|
}`},
|
|
err: "config_entries.bootstrap[0]: invalid config entry kind: foo",
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap invalid service-defaults",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"kind": "service-defaults",
|
|
"name": "web",
|
|
"made_up_key": "blah"
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
kind = "service-defaults"
|
|
name = "web"
|
|
made_up_key = "blah"
|
|
}
|
|
}`},
|
|
err: "config_entries.bootstrap[0]: 1 error occurred:\n\t* invalid config key \"made_up_key\"\n\n",
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap proxy-defaults (snake-case)",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"kind": "proxy-defaults",
|
|
"name": "global",
|
|
"config": {
|
|
"bar": "abc",
|
|
"moreconfig": {
|
|
"moar": "config"
|
|
}
|
|
},
|
|
"mesh_gateway": {
|
|
"mode": "remote"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
kind = "proxy-defaults"
|
|
name = "global"
|
|
config {
|
|
"bar" = "abc"
|
|
"moreconfig" {
|
|
"moar" = "config"
|
|
}
|
|
}
|
|
mesh_gateway {
|
|
mode = "remote"
|
|
}
|
|
}
|
|
}`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
|
&structs.ProxyConfigEntry{
|
|
Kind: structs.ProxyDefaults,
|
|
Name: structs.ProxyConfigGlobal,
|
|
EnterpriseMeta: *defaultEntMeta,
|
|
Config: map[string]interface{}{
|
|
"bar": "abc",
|
|
"moreconfig": map[string]interface{}{
|
|
"moar": "config",
|
|
},
|
|
},
|
|
MeshGateway: structs.MeshGatewayConfig{
|
|
Mode: structs.MeshGatewayModeRemote,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap proxy-defaults (camel-case)",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"Kind": "proxy-defaults",
|
|
"Name": "global",
|
|
"Config": {
|
|
"bar": "abc",
|
|
"moreconfig": {
|
|
"moar": "config"
|
|
}
|
|
},
|
|
"MeshGateway": {
|
|
"Mode": "remote"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
Kind = "proxy-defaults"
|
|
Name = "global"
|
|
Config {
|
|
"bar" = "abc"
|
|
"moreconfig" {
|
|
"moar" = "config"
|
|
}
|
|
}
|
|
MeshGateway {
|
|
Mode = "remote"
|
|
}
|
|
}
|
|
}`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
|
&structs.ProxyConfigEntry{
|
|
Kind: structs.ProxyDefaults,
|
|
Name: structs.ProxyConfigGlobal,
|
|
EnterpriseMeta: *defaultEntMeta,
|
|
Config: map[string]interface{}{
|
|
"bar": "abc",
|
|
"moreconfig": map[string]interface{}{
|
|
"moar": "config",
|
|
},
|
|
},
|
|
MeshGateway: structs.MeshGatewayConfig{
|
|
Mode: structs.MeshGatewayModeRemote,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap service-defaults (snake-case)",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"kind": "service-defaults",
|
|
"name": "web",
|
|
"meta" : {
|
|
"foo": "bar",
|
|
"gir": "zim"
|
|
},
|
|
"protocol": "http",
|
|
"external_sni": "abc-123",
|
|
"mesh_gateway": {
|
|
"mode": "remote"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
kind = "service-defaults"
|
|
name = "web"
|
|
meta {
|
|
"foo" = "bar"
|
|
"gir" = "zim"
|
|
}
|
|
protocol = "http"
|
|
external_sni = "abc-123"
|
|
mesh_gateway {
|
|
mode = "remote"
|
|
}
|
|
}
|
|
}`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
|
&structs.ServiceConfigEntry{
|
|
Kind: structs.ServiceDefaults,
|
|
Name: "web",
|
|
Meta: map[string]string{
|
|
"foo": "bar",
|
|
"gir": "zim",
|
|
},
|
|
EnterpriseMeta: *defaultEntMeta,
|
|
Protocol: "http",
|
|
ExternalSNI: "abc-123",
|
|
MeshGateway: structs.MeshGatewayConfig{
|
|
Mode: structs.MeshGatewayModeRemote,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap service-defaults (camel-case)",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"Kind": "service-defaults",
|
|
"Name": "web",
|
|
"Meta" : {
|
|
"foo": "bar",
|
|
"gir": "zim"
|
|
},
|
|
"Protocol": "http",
|
|
"ExternalSNI": "abc-123",
|
|
"MeshGateway": {
|
|
"Mode": "remote"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
Kind = "service-defaults"
|
|
Name = "web"
|
|
Meta {
|
|
"foo" = "bar"
|
|
"gir" = "zim"
|
|
}
|
|
Protocol = "http"
|
|
ExternalSNI = "abc-123"
|
|
MeshGateway {
|
|
Mode = "remote"
|
|
}
|
|
}
|
|
}`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
|
&structs.ServiceConfigEntry{
|
|
Kind: structs.ServiceDefaults,
|
|
Name: "web",
|
|
Meta: map[string]string{
|
|
"foo": "bar",
|
|
"gir": "zim",
|
|
},
|
|
EnterpriseMeta: *defaultEntMeta,
|
|
Protocol: "http",
|
|
ExternalSNI: "abc-123",
|
|
MeshGateway: structs.MeshGatewayConfig{
|
|
Mode: structs.MeshGatewayModeRemote,
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "ConfigEntry bootstrap service-router (snake-case)",
|
|
args: []string{`-data-dir=` + dataDir},
|
|
json: []string{`{
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"kind": "service-router",
|
|
"name": "main",
|
|
"meta" : {
|
|
"foo": "bar",
|
|
"gir": "zim"
|
|
},
|
|
"routes": [
|
|
{
|
|
"match": {
|
|
"http": {
|
|
"path_exact": "/foo",
|
|
"header": [
|
|
{
|
|
"name": "debug1",
|
|
"present": true
|
|
},
|
|
{
|
|
"name": "debug2",
|
|
"present": true,
|
|
"invert": true
|
|
},
|
|
{
|
|
"name": "debug3",
|
|
"exact": "1"
|
|
},
|
|
{
|
|
"name": "debug4",
|
|
"prefix": "aaa"
|
|
},
|
|
{
|
|
"name": "debug5",
|
|
"suffix": "bbb"
|
|
},
|
|
{
|
|
"name": "debug6",
|
|
"regex": "a.*z"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"destination": {
|
|
"service" : "carrot",
|
|
"service_subset" : "kale",
|
|
"namespace" : "leek",
|
|
"prefix_rewrite" : "/alternate",
|
|
"request_timeout" : "99s",
|
|
"num_retries" : 12345,
|
|
"retry_on_connect_failure": true,
|
|
"retry_on_status_codes" : [401, 209]
|
|
}
|
|
},
|
|
{
|
|
"match": {
|
|
"http": {
|
|
"path_prefix": "/foo",
|
|
"methods": [ "GET", "DELETE" ],
|
|
"query_param": [
|
|
{
|
|
"name": "hack1",
|
|
"present": true
|
|
},
|
|
{
|
|
"name": "hack2",
|
|
"exact": "1"
|
|
},
|
|
{
|
|
"name": "hack3",
|
|
"regex": "a.*z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"match": {
|
|
"http": {
|
|
"path_regex": "/foo"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}`},
|
|
hcl: []string{`
|
|
config_entries {
|
|
bootstrap {
|
|
kind = "service-router"
|
|
name = "main"
|
|
meta {
|
|
"foo" = "bar"
|
|
"gir" = "zim"
|
|
}
|
|
routes = [
|
|
{
|
|
match {
|
|
http {
|
|
path_exact = "/foo"
|
|
header = [
|
|
{
|
|
name = "debug1"
|
|
present = true
|
|
},
|
|
{
|
|
name = "debug2"
|
|
present = true
|
|
invert = true
|
|
},
|
|
{
|
|
name = "debug3"
|
|
exact = "1"
|
|
},
|
|
{
|
|
name = "debug4"
|
|
prefix = "aaa"
|
|
},
|
|
{
|
|
name = "debug5"
|
|
suffix = "bbb"
|
|
},
|
|
{
|
|
name = "debug6"
|
|
regex = "a.*z"
|
|
},
|
|
]
|
|
}
|
|
}
|
|
destination {
|
|
service = "carrot"
|
|
service_subset = "kale"
|
|
namespace = "leek"
|
|
prefix_rewrite = "/alternate"
|
|
request_timeout = "99s"
|
|
num_retries = 12345
|
|
retry_on_connect_failure = true
|
|
retry_on_status_codes = [401, 209]
|
|
}
|
|
},
|
|
{
|
|
match {
|
|
http {
|
|
path_prefix = "/foo"
|
|
methods = [ "GET", "DELETE" ]
|
|
query_param = [
|
|
{
|
|
name = "hack1"
|
|
present = true
|
|
},
|
|
{
|
|
name = "hack2"
|
|
exact = "1"
|
|
},
|
|
{
|
|
name = "hack3"
|
|
regex = "a.*z"
|
|
},
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
match {
|
|
http {
|
|
path_regex = "/foo"
|
|
}
|
|
}
|
|
},
|
|
]
|
|
}
|
|
}`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
rt.ConfigEntryBootstrap = []structs.ConfigEntry{
|
|
&structs.ServiceRouterConfigEntry{
|
|
Kind: structs.ServiceRouter,
|
|
Name: "main",
|
|
Meta: map[string]string{
|
|
"foo": "bar",
|
|
"gir": "zim",
|
|
},
|
|
EnterpriseMeta: *defaultEntMeta,
|
|
Routes: []structs.ServiceRoute{
|
|
{
|
|
Match: &structs.ServiceRouteMatch{
|
|
HTTP: &structs.ServiceRouteHTTPMatch{
|
|
PathExact: "/foo",
|
|
Header: []structs.ServiceRouteHTTPMatchHeader{
|
|
{
|
|
Name: "debug1",
|
|
Present: true,
|
|
},
|
|
{
|
|
Name: "debug2",
|
|
Present: true,
|
|
Invert: true,
|
|
},
|
|
{
|
|
Name: "debug3",
|
|
Exact: "1",
|
|
},
|
|
{
|
|
Name: "debug4",
|
|
Prefix: "aaa",
|
|
},
|
|
{
|
|
Name: "debug5",
|
|
Suffix: "bbb",
|
|
},
|
|
{
|
|
Name: "debug6",
|
|
Regex: "a.*z",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Destination: &structs.ServiceRouteDestination{
|
|
Service: "carrot",
|
|
ServiceSubset: "kale",
|
|
Namespace: "leek",
|
|
PrefixRewrite: "/alternate",
|
|
RequestTimeout: 99 * time.Second,
|
|
NumRetries: 12345,
|
|
RetryOnConnectFailure: true,
|
|
RetryOnStatusCodes: []uint32{401, 209},
|
|
},
|
|
},
|
|
{
|
|
Match: &structs.ServiceRouteMatch{
|
|
HTTP: &structs.ServiceRouteHTTPMatch{
|
|
PathPrefix: "/foo",
|
|
Methods: []string{"GET", "DELETE"},
|
|
QueryParam: []structs.ServiceRouteHTTPMatchQueryParam{
|
|
{
|
|
Name: "hack1",
|
|
Present: true,
|
|
},
|
|
{
|
|
Name: "hack2",
|
|
Exact: "1",
|
|
},
|
|
{
|
|
Name: "hack3",
|
|
Regex: "a.*z",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Match: &structs.ServiceRouteMatch{
|
|
HTTP: &structs.ServiceRouteHTTPMatch{
|
|
PathRegex: "/foo",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
// TODO(rb): add in missing tests for ingress-gateway (snake + camel)
|
|
// TODO(rb): add in missing tests for terminating-gateway (snake + camel)
|
|
|
|
///////////////////////////////////
|
|
// Defaults sanity checks
|
|
|
|
{
|
|
desc: "default limits",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.DataDir = dataDir
|
|
// Note that in the happy case this test will pass even if you comment
|
|
// out all the stuff below since rt is also initialized from the
|
|
// defaults. But it's still valuable as it will fail as soon as the
|
|
// defaults are changed from these values forcing that change to be
|
|
// intentional.
|
|
rt.RPCHandshakeTimeout = 5 * time.Second
|
|
rt.HTTPSHandshakeTimeout = 5 * time.Second
|
|
rt.HTTPMaxConnsPerClient = 200
|
|
rt.RPCMaxConnsPerClient = 100
|
|
},
|
|
},
|
|
|
|
///////////////////////////////////
|
|
// Auto Config related tests
|
|
{
|
|
desc: "auto config and auto encrypt error",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
enabled = true
|
|
intro_token = "blah"
|
|
server_addresses = ["198.18.0.1"]
|
|
}
|
|
auto_encrypt {
|
|
tls = true
|
|
}
|
|
verify_outgoing = true
|
|
`},
|
|
json: []string{`{
|
|
"auto_config": {
|
|
"enabled": true,
|
|
"intro_token": "blah",
|
|
"server_addresses": ["198.18.0.1"]
|
|
},
|
|
"auto_encrypt": {
|
|
"tls": true
|
|
},
|
|
"verify_outgoing": true
|
|
}`},
|
|
err: "both auto_encrypt.tls and auto_config.enabled cannot be set to true.",
|
|
},
|
|
{
|
|
desc: "auto config not allowed for servers",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
server = true
|
|
auto_config {
|
|
enabled = true
|
|
intro_token = "blah"
|
|
server_addresses = ["198.18.0.1"]
|
|
}
|
|
verify_outgoing = true
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"server": true,
|
|
"auto_config": {
|
|
"enabled": true,
|
|
"intro_token": "blah",
|
|
"server_addresses": ["198.18.0.1"]
|
|
},
|
|
"verify_outgoing": true
|
|
}`},
|
|
err: "auto_config.enabled cannot be set to true for server agents",
|
|
},
|
|
|
|
{
|
|
desc: "auto config tls not enabled",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
enabled = true
|
|
server_addresses = ["198.18.0.1"]
|
|
intro_token = "foo"
|
|
}
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"enabled": true,
|
|
"server_addresses": ["198.18.0.1"],
|
|
"intro_token": "foo"
|
|
}
|
|
}`},
|
|
err: "auto_config.enabled cannot be set without configuring TLS for server communications",
|
|
},
|
|
|
|
{
|
|
desc: "auto config server tls not enabled",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
server = true
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
}
|
|
}
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"server": true,
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true
|
|
}
|
|
}
|
|
}`},
|
|
err: "auto_config.authorization.enabled cannot be set without providing a TLS certificate for the server",
|
|
},
|
|
|
|
{
|
|
desc: "auto config no intro token",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
enabled = true
|
|
server_addresses = ["198.18.0.1"]
|
|
}
|
|
verify_outgoing = true
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"enabled": true,
|
|
"server_addresses": ["198.18.0.1"]
|
|
},
|
|
"verify_outgoing": true
|
|
}`},
|
|
err: "One of auto_config.intro_token, auto_config.intro_token_file or the CONSUL_INTRO_TOKEN environment variable must be set to enable auto_config",
|
|
},
|
|
|
|
{
|
|
desc: "auto config no server addresses",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
enabled = true
|
|
intro_token = "blah"
|
|
}
|
|
verify_outgoing = true
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"enabled": true,
|
|
"intro_token": "blah"
|
|
},
|
|
"verify_outgoing": true
|
|
}`},
|
|
err: "auto_config.enabled is set without providing a list of addresses",
|
|
},
|
|
|
|
{
|
|
desc: "auto config client",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
enabled = true
|
|
intro_token = "blah"
|
|
intro_token_file = "blah"
|
|
server_addresses = ["198.18.0.1"]
|
|
dns_sans = ["foo"]
|
|
ip_sans = ["invalid", "127.0.0.1"]
|
|
}
|
|
verify_outgoing = true
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"enabled": true,
|
|
"intro_token": "blah",
|
|
"intro_token_file": "blah",
|
|
"server_addresses": ["198.18.0.1"],
|
|
"dns_sans": ["foo"],
|
|
"ip_sans": ["invalid", "127.0.0.1"]
|
|
},
|
|
"verify_outgoing": true
|
|
}`},
|
|
warns: []string{
|
|
"Cannot parse ip \"invalid\" from auto_config.ip_sans",
|
|
"Both an intro token and intro token file are set. The intro token will be used instead of the file",
|
|
},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.ConnectEnabled = true
|
|
rt.AutoConfig.Enabled = true
|
|
rt.AutoConfig.IntroToken = "blah"
|
|
rt.AutoConfig.IntroTokenFile = "blah"
|
|
rt.AutoConfig.ServerAddresses = []string{"198.18.0.1"}
|
|
rt.AutoConfig.DNSSANs = []string{"foo"}
|
|
rt.AutoConfig.IPSANs = []net.IP{net.IPv4(127, 0, 0, 1)}
|
|
rt.DataDir = dataDir
|
|
rt.VerifyOutgoing = true
|
|
},
|
|
},
|
|
|
|
{
|
|
desc: "auto config authorizer client not allowed",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
}
|
|
}
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true
|
|
}
|
|
}
|
|
}`},
|
|
err: "auto_config.authorization.enabled cannot be set to true for client agents",
|
|
},
|
|
|
|
{
|
|
desc: "auto config authorizer invalid config",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-server`,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
}
|
|
}
|
|
cert_file = "foo"
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true
|
|
}
|
|
},
|
|
"cert_file": "foo"
|
|
}`},
|
|
err: `auto_config.authorization.static has invalid configuration: exactly one of 'JWTValidationPubKeys', 'JWKSURL', or 'OIDCDiscoveryURL' must be set for type "jwt"`,
|
|
},
|
|
|
|
{
|
|
desc: "auto config authorizer invalid config 2",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-server`,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
static {
|
|
jwks_url = "https://fake.uri.local"
|
|
oidc_discovery_url = "https://fake.uri.local"
|
|
}
|
|
}
|
|
}
|
|
cert_file = "foo"
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true,
|
|
"static": {
|
|
"jwks_url": "https://fake.uri.local",
|
|
"oidc_discovery_url": "https://fake.uri.local"
|
|
}
|
|
}
|
|
},
|
|
"cert_file": "foo"
|
|
}`},
|
|
err: `auto_config.authorization.static has invalid configuration: exactly one of 'JWTValidationPubKeys', 'JWKSURL', or 'OIDCDiscoveryURL' must be set for type "jwt"`,
|
|
},
|
|
|
|
{
|
|
desc: "auto config authorizer require token replication in secondary",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-server`,
|
|
},
|
|
hcl: []string{`
|
|
primary_datacenter = "otherdc"
|
|
acl {
|
|
enabled = true
|
|
}
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
static {
|
|
jwks_url = "https://fake.uri.local"
|
|
oidc_discovery_url = "https://fake.uri.local"
|
|
}
|
|
}
|
|
}
|
|
cert_file = "foo"
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"primary_datacenter": "otherdc",
|
|
"acl": {
|
|
"enabled": true
|
|
},
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true,
|
|
"static": {
|
|
"jwks_url": "https://fake.uri.local",
|
|
"oidc_discovery_url": "https://fake.uri.local"
|
|
}
|
|
}
|
|
},
|
|
"cert_file": "foo"
|
|
}`},
|
|
err: `Enabling auto-config authorization (auto_config.authorization.enabled) in non primary datacenters with ACLs enabled (acl.enabled) requires also enabling ACL token replication (acl.enable_token_replication)`,
|
|
},
|
|
|
|
{
|
|
desc: "auto config authorizer invalid claim assertion",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-server`,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
static {
|
|
jwt_validation_pub_keys = ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"]
|
|
claim_assertions = [
|
|
"values.node == ${node}"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
cert_file = "foo"
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true,
|
|
"static": {
|
|
"jwt_validation_pub_keys": ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"],
|
|
"claim_assertions": [
|
|
"values.node == ${node}"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"cert_file": "foo"
|
|
}`},
|
|
err: `auto_config.authorization.static.claim_assertion "values.node == ${node}" is invalid: Selector "values" is not valid`,
|
|
},
|
|
{
|
|
desc: "auto config authorizer ok",
|
|
args: []string{
|
|
`-data-dir=` + dataDir,
|
|
`-server`,
|
|
},
|
|
hcl: []string{`
|
|
auto_config {
|
|
authorization {
|
|
enabled = true
|
|
static {
|
|
jwt_validation_pub_keys = ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"]
|
|
claim_assertions = [
|
|
"value.node == ${node}"
|
|
]
|
|
claim_mappings = {
|
|
node = "node"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cert_file = "foo"
|
|
`},
|
|
json: []string{`
|
|
{
|
|
"auto_config": {
|
|
"authorization": {
|
|
"enabled": true,
|
|
"static": {
|
|
"jwt_validation_pub_keys": ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"],
|
|
"claim_assertions": [
|
|
"value.node == ${node}"
|
|
],
|
|
"claim_mappings": {
|
|
"node": "node"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"cert_file": "foo"
|
|
}`},
|
|
patch: func(rt *RuntimeConfig) {
|
|
rt.AutoConfig.Authorizer.Enabled = true
|
|
rt.AutoConfig.Authorizer.AuthMethod.Config["ClaimMappings"] = map[string]string{
|
|
"node": "node",
|
|
}
|
|
rt.AutoConfig.Authorizer.AuthMethod.Config["JWTValidationPubKeys"] = []string{"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"}
|
|
rt.AutoConfig.Authorizer.ClaimAssertions = []string{"value.node == ${node}"}
|
|
rt.DataDir = dataDir
|
|
rt.LeaveOnTerm = false
|
|
rt.ServerMode = true
|
|
rt.SkipLeaveOnInt = true
|
|
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)
|
|
}
|
|
|
|
func testConfig(t *testing.T, tests []configTest, dataDir string) {
|
|
t.Helper()
|
|
for _, tt := range tests {
|
|
for pass, format := range []string{"json", "hcl"} {
|
|
// clean data dir before every test
|
|
cleanDir(dataDir)
|
|
|
|
// when we test only flags then there are no JSON or HCL
|
|
// sources and we need to make only one pass over the
|
|
// tests.
|
|
flagsOnly := len(tt.json) == 0 && len(tt.hcl) == 0
|
|
if flagsOnly && pass > 0 {
|
|
continue
|
|
}
|
|
|
|
// json and hcl sources need to be in sync
|
|
// to make sure we're generating the same config
|
|
if len(tt.json) != len(tt.hcl) && !tt.skipformat {
|
|
t.Fatal(tt.desc, ": JSON and HCL test case out of sync")
|
|
}
|
|
|
|
// select the source
|
|
srcs, tails := tt.json, tt.jsontail
|
|
if format == "hcl" {
|
|
srcs, tails = tt.hcl, tt.hcltail
|
|
}
|
|
|
|
// If we're skipping a format and the current format is empty,
|
|
// then skip it!
|
|
if tt.skipformat && len(srcs) == 0 {
|
|
continue
|
|
}
|
|
|
|
// build the description
|
|
var desc []string
|
|
if !flagsOnly {
|
|
desc = append(desc, format)
|
|
}
|
|
if tt.desc != "" {
|
|
desc = append(desc, tt.desc)
|
|
}
|
|
|
|
t.Run(strings.Join(desc, ":"), func(t *testing.T) {
|
|
// first parse the flags
|
|
flags := BuilderOpts{}
|
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
|
AddFlags(fs, &flags)
|
|
err := fs.Parse(tt.args)
|
|
if err != nil {
|
|
t.Fatalf("ParseFlags failed: %s", err)
|
|
}
|
|
require.Len(t, fs.Args(), 0)
|
|
|
|
if tt.pre != nil {
|
|
tt.pre()
|
|
}
|
|
defer func() {
|
|
if tt.post != nil {
|
|
tt.post()
|
|
}
|
|
}()
|
|
|
|
// Then create a builder with the flags.
|
|
b, err := NewBuilder(flags)
|
|
if err != nil {
|
|
t.Fatal("NewBuilder", err)
|
|
}
|
|
|
|
patchBuilderShims(b)
|
|
if tt.hostname != nil {
|
|
b.hostname = tt.hostname
|
|
}
|
|
if tt.privatev4 != nil {
|
|
b.getPrivateIPv4 = tt.privatev4
|
|
}
|
|
if tt.publicv6 != nil {
|
|
b.getPublicIPv6 = tt.publicv6
|
|
}
|
|
|
|
// read the source fragements
|
|
for i, data := range srcs {
|
|
b.Sources = append(b.Sources, FileSource{
|
|
Name: fmt.Sprintf("src-%d.%s", i, format),
|
|
Format: format,
|
|
Data: data,
|
|
})
|
|
}
|
|
for i, data := range tails {
|
|
b.Tail = append(b.Tail, FileSource{
|
|
Name: fmt.Sprintf("tail-%d.%s", i, format),
|
|
Format: format,
|
|
Data: data,
|
|
})
|
|
}
|
|
|
|
// build/merge the config fragments
|
|
actual, err := b.BuildAndValidate()
|
|
if err == nil && tt.err != "" {
|
|
t.Fatalf("got no error want %q", tt.err)
|
|
}
|
|
if err != nil && tt.err == "" {
|
|
t.Fatalf("got error %s want nil", err)
|
|
}
|
|
if err == nil && tt.err != "" {
|
|
t.Fatalf("got nil want error to contain %q", tt.err)
|
|
}
|
|
if err != nil && tt.err != "" && !strings.Contains(err.Error(), tt.err) {
|
|
t.Fatalf("error %q does not contain %q", err.Error(), tt.err)
|
|
}
|
|
if tt.err != "" {
|
|
return
|
|
}
|
|
require.Equal(t, tt.warns, b.Warnings, "warnings")
|
|
|
|
// build a default configuration, then patch the fields we expect to change
|
|
// and compare it with the generated configuration. Since the expected
|
|
// runtime config has been validated we do not need to validate it again.
|
|
x, err := NewBuilder(BuilderOpts{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
x.hostname = b.hostname
|
|
x.getPrivateIPv4 = func() ([]*net.IPAddr, error) { return []*net.IPAddr{ipAddr("10.0.0.1")}, nil }
|
|
x.getPublicIPv6 = func() ([]*net.IPAddr, error) { return []*net.IPAddr{ipAddr("dead:beef::1")}, nil }
|
|
expected, err := x.Build()
|
|
if err != nil {
|
|
t.Fatalf("build default failed: %s", err)
|
|
}
|
|
if tt.patch != nil {
|
|
tt.patch(&expected)
|
|
}
|
|
|
|
// both DataDir fields should always be the same, so test for the
|
|
// invariant, and than updated the expected, so that every test
|
|
// case does not need to set this field.
|
|
require.Equal(t, actual.DataDir, actual.ACLTokens.DataDir)
|
|
expected.ACLTokens.DataDir = actual.ACLTokens.DataDir
|
|
|
|
require.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNewBuilder_InvalidConfigFormat(t *testing.T) {
|
|
_, err := NewBuilder(BuilderOpts{ConfigFormat: "yaml"})
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "-config-format must be either 'hcl' or 'json'")
|
|
}
|
|
|
|
// TestFullConfig tests the conversion from a fully populated JSON or
|
|
// HCL config file to a RuntimeConfig structure. All fields must be set
|
|
// to a unique non-zero value.
|
|
//
|
|
// To aid populating the fields the following bash functions can be used
|
|
// to generate random strings and ints:
|
|
//
|
|
// random-int() { echo $RANDOM }
|
|
// random-string() { base64 /dev/urandom | tr -d '/+' | fold -w ${1:-32} | head -n 1 }
|
|
//
|
|
// To generate a random string of length 8 run the following command in
|
|
// a terminal:
|
|
//
|
|
// random-string 8
|
|
//
|
|
func TestFullConfig(t *testing.T) {
|
|
dataDir := testutil.TempDir(t, "consul")
|
|
|
|
cidr := func(s string) *net.IPNet {
|
|
_, n, _ := net.ParseCIDR(s)
|
|
return n
|
|
}
|
|
|
|
defaultEntMeta := structs.DefaultEnterpriseMeta()
|
|
|
|
flagSrc := []string{`-dev`}
|
|
src := map[string]string{
|
|
"json": `{
|
|
"acl_agent_master_token": "furuQD0b",
|
|
"acl_agent_token": "cOshLOQ2",
|
|
"acl_datacenter": "m3urck3z",
|
|
"acl_default_policy": "ArK3WIfE",
|
|
"acl_down_policy": "vZXMfMP0",
|
|
"acl_enable_key_list_policy": true,
|
|
"acl_master_token": "C1Q1oIwh",
|
|
"acl_replication_token": "LMmgy5dO",
|
|
"acl_token": "O1El0wan",
|
|
"acl_ttl": "18060s",
|
|
"acl" : {
|
|
"enabled" : true,
|
|
"down_policy" : "03eb2aee",
|
|
"default_policy" : "72c2e7a0",
|
|
"enable_key_list_policy": true,
|
|
"enable_token_persistence": true,
|
|
"policy_ttl": "1123s",
|
|
"role_ttl": "9876s",
|
|
"token_ttl": "3321s",
|
|
"enable_token_replication" : true,
|
|
"msp_disable_bootstrap": true,
|
|
"tokens" : {
|
|
"master" : "8a19ac27",
|
|
"agent_master" : "64fd0e08",
|
|
"replication" : "5795983a",
|
|
"agent" : "bed2377c",
|
|
"default" : "418fdff1",
|
|
"managed_service_provider": [
|
|
{
|
|
"accessor_id": "first",
|
|
"secret_id": "fb0cee1f-2847-467c-99db-a897cff5fd4d"
|
|
},
|
|
{
|
|
"accessor_id": "second",
|
|
"secret_id": "1046c8da-e166-4667-897a-aefb343db9db"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"addresses": {
|
|
"dns": "93.95.95.81",
|
|
"http": "83.39.91.39",
|
|
"https": "95.17.17.19",
|
|
"grpc": "32.31.61.91"
|
|
},
|
|
"advertise_addr": "17.99.29.16",
|
|
"advertise_addr_wan": "78.63.37.19",
|
|
"audit": {
|
|
"enabled": false
|
|
},
|
|
"auto_config": {
|
|
"enabled": false,
|
|
"intro_token": "OpBPGRwt",
|
|
"intro_token_file": "gFvAXwI8",
|
|
"dns_sans": ["6zdaWg9J"],
|
|
"ip_sans": ["198.18.99.99"],
|
|
"server_addresses": ["198.18.100.1"],
|
|
"authorization": {
|
|
"enabled": true,
|
|
"static": {
|
|
"allow_reuse": true,
|
|
"claim_mappings": {
|
|
"node": "node"
|
|
},
|
|
"list_claim_mappings": {
|
|
"foo": "bar"
|
|
},
|
|
"bound_issuer": "consul",
|
|
"bound_audiences": ["consul-cluster-1"],
|
|
"claim_assertions": ["value.node == \"${node}\""],
|
|
"jwt_validation_pub_keys": ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"]
|
|
}
|
|
}
|
|
},
|
|
"autopilot": {
|
|
"cleanup_dead_servers": true,
|
|
"disable_upgrade_migration": true,
|
|
"last_contact_threshold": "12705s",
|
|
"max_trailing_logs": 17849,
|
|
"min_quorum": 3,
|
|
"redundancy_zone_tag": "3IsufDJf",
|
|
"server_stabilization_time": "23057s",
|
|
"upgrade_version_tag": "W9pDwFAL"
|
|
},
|
|
"bind_addr": "16.99.34.17",
|
|
"bootstrap": true,
|
|
"bootstrap_expect": 53,
|
|
"cache": {
|
|
"entry_fetch_max_burst": 42,
|
|
"entry_fetch_rate": 0.334
|
|
},
|
|
"ca_file": "erA7T0PM",
|
|
"ca_path": "mQEN1Mfp",
|
|
"cert_file": "7s4QAzDk",
|
|
"check": {
|
|
"id": "fZaCAXww",
|
|
"name": "OOM2eo0f",
|
|
"notes": "zXzXI9Gt",
|
|
"service_id": "L8G0QNmR",
|
|
"token": "oo4BCTgJ",
|
|
"status": "qLykAl5u",
|
|
"args": ["f3BemRjy", "e5zgpef7"],
|
|
"http": "29B93haH",
|
|
"header": {
|
|
"hBq0zn1q": [ "2a9o9ZKP", "vKwA5lR6" ],
|
|
"f3r6xFtM": [ "RyuIdDWv", "QbxEcIUM" ]
|
|
},
|
|
"method": "Dou0nGT5",
|
|
"body": "5PBQd2OT",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"tcp": "JY6fTTcw",
|
|
"interval": "18714s",
|
|
"docker_container_id": "qF66POS9",
|
|
"shell": "sOnDy228",
|
|
"tls_skip_verify": true,
|
|
"timeout": "5954s",
|
|
"ttl": "30044s",
|
|
"deregister_critical_service_after": "13209s"
|
|
},
|
|
"checks": [
|
|
{
|
|
"id": "uAjE6m9Z",
|
|
"name": "QsZRGpYr",
|
|
"notes": "VJ7Sk4BY",
|
|
"service_id": "lSulPcyz",
|
|
"token": "toO59sh8",
|
|
"status": "9RlWsXMV",
|
|
"args": ["4BAJttck", "4D2NPtTQ"],
|
|
"http": "dohLcyQ2",
|
|
"header": {
|
|
"ZBfTin3L": [ "1sDbEqYG", "lJGASsWK" ],
|
|
"Ui0nU99X": [ "LMccm3Qe", "k5H5RggQ" ]
|
|
},
|
|
"method": "aldrIQ4l",
|
|
"body": "wSjTy7dg",
|
|
"tcp": "RJQND605",
|
|
"interval": "22164s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "ipgdFtjd",
|
|
"shell": "qAeOYy0M",
|
|
"tls_skip_verify": true,
|
|
"timeout": "1813s",
|
|
"ttl": "21743s",
|
|
"deregister_critical_service_after": "14232s"
|
|
},
|
|
{
|
|
"id": "Cqq95BhP",
|
|
"name": "3qXpkS0i",
|
|
"notes": "sb5qLTex",
|
|
"service_id": "CmUUcRna",
|
|
"token": "a3nQzHuy",
|
|
"status": "irj26nf3",
|
|
"args": ["9s526ogY", "gSlOHj1w"],
|
|
"http": "yzhgsQ7Y",
|
|
"header": {
|
|
"zcqwA8dO": [ "qb1zx0DL", "sXCxPFsD" ],
|
|
"qxvdnSE9": [ "6wBPUYdF", "YYh8wtSZ" ]
|
|
},
|
|
"method": "gLrztrNw",
|
|
"body": "0jkKgGUC",
|
|
"tcp": "4jG5casb",
|
|
"interval": "28767s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "THW6u7rL",
|
|
"shell": "C1Zt3Zwh",
|
|
"tls_skip_verify": true,
|
|
"timeout": "18506s",
|
|
"ttl": "31006s",
|
|
"deregister_critical_service_after": "2366s"
|
|
}
|
|
],
|
|
"check_update_interval": "16507s",
|
|
"client_addr": "93.83.18.19",
|
|
"config_entries": {
|
|
"bootstrap": [
|
|
{
|
|
"kind": "proxy-defaults",
|
|
"name": "global",
|
|
"config": {
|
|
"foo": "bar",
|
|
"bar": 1.0
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"auto_encrypt": {
|
|
"tls": false,
|
|
"dns_san": ["a.com", "b.com"],
|
|
"ip_san": ["192.168.4.139", "192.168.4.140"],
|
|
"allow_tls": true
|
|
},
|
|
"connect": {
|
|
"ca_provider": "consul",
|
|
"ca_config": {
|
|
"rotation_period": "90h",
|
|
"intermediate_cert_ttl": "8760h",
|
|
"leaf_cert_ttl": "1h",
|
|
"csr_max_per_second": 100,
|
|
"csr_max_concurrent": 2
|
|
},
|
|
"enable_mesh_gateway_wan_federation": false,
|
|
"enabled": true
|
|
},
|
|
"gossip_lan" : {
|
|
"gossip_nodes": 6,
|
|
"gossip_interval" : "25252s",
|
|
"retransmit_mult" : 1234,
|
|
"suspicion_mult" : 1235,
|
|
"probe_interval" : "101ms",
|
|
"probe_timeout" : "102ms"
|
|
},
|
|
"gossip_wan" : {
|
|
"gossip_nodes" : 2,
|
|
"gossip_interval" : "6966s",
|
|
"retransmit_mult" : 16384,
|
|
"suspicion_mult" : 16385,
|
|
"probe_interval" : "103ms",
|
|
"probe_timeout" : "104ms"
|
|
},
|
|
"data_dir": "` + dataDir + `",
|
|
"datacenter": "rzo029wg",
|
|
"default_query_time": "16743s",
|
|
"disable_anonymous_signature": true,
|
|
"disable_coordinates": true,
|
|
"disable_host_node_id": true,
|
|
"disable_http_unprintable_char_filter": true,
|
|
"disable_keyring_file": true,
|
|
"disable_remote_exec": true,
|
|
"disable_update_check": true,
|
|
"discard_check_output": true,
|
|
"discovery_max_stale": "5s",
|
|
"domain": "7W1xXSqd",
|
|
"alt_domain": "1789hsd",
|
|
"dns_config": {
|
|
"allow_stale": true,
|
|
"a_record_limit": 29907,
|
|
"disable_compression": true,
|
|
"enable_truncate": true,
|
|
"max_stale": "29685s",
|
|
"node_ttl": "7084s",
|
|
"only_passing": true,
|
|
"recursor_timeout": "4427s",
|
|
"service_ttl": {
|
|
"*": "32030s"
|
|
},
|
|
"udp_answer_limit": 29909,
|
|
"use_cache": true,
|
|
"cache_max_age": "5m",
|
|
"prefer_namespace": true
|
|
},
|
|
"enable_acl_replication": true,
|
|
"enable_agent_tls_for_checks": true,
|
|
"enable_central_service_config": false,
|
|
"enable_debug": true,
|
|
"enable_script_checks": true,
|
|
"enable_local_script_checks": true,
|
|
"enable_syslog": true,
|
|
"encrypt": "A4wELWqH",
|
|
"encrypt_verify_incoming": true,
|
|
"encrypt_verify_outgoing": true,
|
|
"http_config": {
|
|
"block_endpoints": [ "RBvAFcGD", "fWOWFznh" ],
|
|
"allow_write_http_from": [ "127.0.0.1/8", "22.33.44.55/32", "0.0.0.0/0" ],
|
|
"response_headers": {
|
|
"M6TKa9NP": "xjuxjOzQ",
|
|
"JRCrHZed": "rl0mTx81"
|
|
},
|
|
"use_cache": false
|
|
},
|
|
"key_file": "IEkkwgIA",
|
|
"leave_on_terminate": true,
|
|
"limits": {
|
|
"http_max_conns_per_client": 100,
|
|
"https_handshake_timeout": "2391ms",
|
|
"rpc_handshake_timeout": "1932ms",
|
|
"rpc_rate": 12029.43,
|
|
"rpc_max_burst": 44848,
|
|
"rpc_max_conns_per_client": 2954,
|
|
"kv_max_value_size": 1234567800000000,
|
|
"txn_max_req_len": 5678000000000000
|
|
},
|
|
"log_level": "k1zo9Spt",
|
|
"log_json": true,
|
|
"max_query_time": "18237s",
|
|
"node_id": "AsUIlw99",
|
|
"node_meta": {
|
|
"5mgGQMBk": "mJLtVMSG",
|
|
"A7ynFMJB": "0Nx6RGab"
|
|
},
|
|
"node_name": "otlLxGaI",
|
|
"non_voting_server": true,
|
|
"performance": {
|
|
"leave_drain_time": "8265s",
|
|
"raft_multiplier": 5,
|
|
"rpc_hold_timeout": "15707s"
|
|
},
|
|
"pid_file": "43xN80Km",
|
|
"ports": {
|
|
"dns": 7001,
|
|
"http": 7999,
|
|
"https": 15127,
|
|
"server": 3757,
|
|
"grpc": 4881,
|
|
"sidecar_min_port": 8888,
|
|
"sidecar_max_port": 9999,
|
|
"expose_min_port": 1111,
|
|
"expose_max_port": 2222
|
|
},
|
|
"protocol": 30793,
|
|
"primary_datacenter": "ejtmd43d",
|
|
"primary_gateways": [ "aej8eeZo", "roh2KahS" ],
|
|
"primary_gateways_interval": "18866s",
|
|
"raft_protocol": 19016,
|
|
"raft_snapshot_threshold": 16384,
|
|
"raft_snapshot_interval": "30s",
|
|
"raft_trailing_logs": 83749,
|
|
"reconnect_timeout": "23739s",
|
|
"reconnect_timeout_wan": "26694s",
|
|
"recursors": [ "63.38.39.58", "92.49.18.18" ],
|
|
"rejoin_after_leave": true,
|
|
"retry_interval": "8067s",
|
|
"retry_interval_wan": "28866s",
|
|
"retry_join": [ "pbsSFY7U", "l0qLtWij" ],
|
|
"retry_join_wan": [ "PFsR02Ye", "rJdQIhER" ],
|
|
"retry_max": 913,
|
|
"retry_max_wan": 23160,
|
|
"segment": "BC2NhTDi",
|
|
"segments": [
|
|
{
|
|
"name": "PExYMe2E",
|
|
"bind": "36.73.36.19",
|
|
"port": 38295,
|
|
"rpc_listener": true,
|
|
"advertise": "63.39.19.18"
|
|
},
|
|
{
|
|
"name": "UzCvJgup",
|
|
"bind": "37.58.38.19",
|
|
"port": 39292,
|
|
"rpc_listener": true,
|
|
"advertise": "83.58.26.27"
|
|
}
|
|
],
|
|
"serf_lan": "99.43.63.15",
|
|
"serf_wan": "67.88.33.19",
|
|
"server": true,
|
|
"server_name": "Oerr9n1G",
|
|
"service": {
|
|
"id": "dLOXpSCI",
|
|
"name": "o1ynPkp0",
|
|
"meta": {
|
|
"mymeta": "data"
|
|
},
|
|
"tagged_addresses": {
|
|
"lan": {
|
|
"address": "2d79888a",
|
|
"port": 2143
|
|
},
|
|
"wan": {
|
|
"address": "d4db85e2",
|
|
"port": 6109
|
|
}
|
|
},
|
|
"tags": ["nkwshvM5", "NTDWn3ek"],
|
|
"address": "cOlSOhbp",
|
|
"token": "msy7iWER",
|
|
"port": 24237,
|
|
"weights": {
|
|
"passing": 100,
|
|
"warning": 1
|
|
},
|
|
"enable_tag_override": true,
|
|
"check": {
|
|
"id": "RMi85Dv8",
|
|
"name": "iehanzuq",
|
|
"status": "rCvn53TH",
|
|
"notes": "fti5lfF3",
|
|
"args": ["16WRUmwS", "QWk7j7ae"],
|
|
"http": "dl3Fgme3",
|
|
"header": {
|
|
"rjm4DEd3": ["2m3m2Fls"],
|
|
"l4HwQ112": ["fk56MNlo", "dhLK56aZ"]
|
|
},
|
|
"method": "9afLm3Mj",
|
|
"body": "wVVL2V6f",
|
|
"tcp": "fjiLFqVd",
|
|
"interval": "23926s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "dO5TtRHk",
|
|
"shell": "e6q2ttES",
|
|
"tls_skip_verify": true,
|
|
"timeout": "38483s",
|
|
"ttl": "10943s",
|
|
"deregister_critical_service_after": "68787s"
|
|
},
|
|
"checks": [
|
|
{
|
|
"id": "Zv99e9Ka",
|
|
"name": "sgV4F7Pk",
|
|
"notes": "yP5nKbW0",
|
|
"status": "7oLMEyfu",
|
|
"args": ["5wEZtZpv", "0Ihyk8cS"],
|
|
"http": "KyDjGY9H",
|
|
"header": {
|
|
"gv5qefTz": [ "5Olo2pMG", "PvvKWQU5" ],
|
|
"SHOVq1Vv": [ "jntFhyym", "GYJh32pp" ]
|
|
},
|
|
"method": "T66MFBfR",
|
|
"body": "OwGjTFQi",
|
|
"tcp": "bNnNfx2A",
|
|
"interval": "22224s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "ipgdFtjd",
|
|
"shell": "omVZq7Sz",
|
|
"tls_skip_verify": true,
|
|
"timeout": "18913s",
|
|
"ttl": "44743s",
|
|
"deregister_critical_service_after": "8482s"
|
|
},
|
|
{
|
|
"id": "G79O6Mpr",
|
|
"name": "IEqrzrsd",
|
|
"notes": "SVqApqeM",
|
|
"status": "XXkVoZXt",
|
|
"args": ["wD05Bvao", "rLYB7kQC"],
|
|
"http": "kyICZsn8",
|
|
"header": {
|
|
"4ebP5vL4": [ "G20SrL5Q", "DwPKlMbo" ],
|
|
"p2UI34Qz": [ "UsG1D0Qh", "NHhRiB6s" ]
|
|
},
|
|
"method": "ciYHWors",
|
|
"body": "lUVLGYU7",
|
|
"tcp": "FfvCwlqH",
|
|
"interval": "12356s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "HBndBU6R",
|
|
"shell": "hVI33JjA",
|
|
"tls_skip_verify": true,
|
|
"timeout": "38282s",
|
|
"ttl": "1181s",
|
|
"deregister_critical_service_after": "4992s"
|
|
}
|
|
],
|
|
"connect": {
|
|
"native": true
|
|
}
|
|
},
|
|
"services": [
|
|
{
|
|
"id": "wI1dzxS4",
|
|
"name": "7IszXMQ1",
|
|
"tags": ["0Zwg8l6v", "zebELdN5"],
|
|
"address": "9RhqPSPB",
|
|
"token": "myjKJkWH",
|
|
"port": 72219,
|
|
"enable_tag_override": true,
|
|
"check": {
|
|
"id": "qmfeO5if",
|
|
"name": "atDGP7n5",
|
|
"status": "pDQKEhWL",
|
|
"notes": "Yt8EDLev",
|
|
"args": ["81EDZLPa", "bPY5X8xd"],
|
|
"http": "qzHYvmJO",
|
|
"header": {
|
|
"UkpmZ3a3": ["2dfzXuxZ"],
|
|
"cVFpko4u": ["gGqdEB6k", "9LsRo22u"]
|
|
},
|
|
"method": "X5DrovFc",
|
|
"body": "WeikigLh",
|
|
"tcp": "ICbxkpSF",
|
|
"interval": "24392s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "ZKXr68Yb",
|
|
"shell": "CEfzx0Fo",
|
|
"tls_skip_verify": true,
|
|
"timeout": "38333s",
|
|
"ttl": "57201s",
|
|
"deregister_critical_service_after": "44214s"
|
|
},
|
|
"connect": {
|
|
"sidecar_service": {}
|
|
}
|
|
},
|
|
{
|
|
"id": "MRHVMZuD",
|
|
"name": "6L6BVfgH",
|
|
"tags": ["7Ale4y6o", "PMBW08hy"],
|
|
"address": "R6H6g8h0",
|
|
"token": "ZgY8gjMI",
|
|
"port": 38292,
|
|
"weights": {
|
|
"passing": 1979,
|
|
"warning": 6
|
|
},
|
|
"enable_tag_override": true,
|
|
"checks": [
|
|
{
|
|
"id": "GTti9hCo",
|
|
"name": "9OOS93ne",
|
|
"notes": "CQy86DH0",
|
|
"status": "P0SWDvrk",
|
|
"args": ["EXvkYIuG", "BATOyt6h"],
|
|
"http": "u97ByEiW",
|
|
"header": {
|
|
"MUlReo8L": [ "AUZG7wHG", "gsN0Dc2N" ],
|
|
"1UJXjVrT": [ "OJgxzTfk", "xZZrFsq7" ]
|
|
},
|
|
"method": "5wkAxCUE",
|
|
"body": "7CRjCJyz",
|
|
"tcp": "MN3oA9D2",
|
|
"interval": "32718s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "cU15LMet",
|
|
"shell": "nEz9qz2l",
|
|
"tls_skip_verify": true,
|
|
"timeout": "34738s",
|
|
"ttl": "22773s",
|
|
"deregister_critical_service_after": "84282s"
|
|
},
|
|
{
|
|
"id": "UHsDeLxG",
|
|
"name": "PQSaPWlT",
|
|
"notes": "jKChDOdl",
|
|
"status": "5qFz6OZn",
|
|
"args": ["NMtYWlT9", "vj74JXsm"],
|
|
"http": "1LBDJhw4",
|
|
"header": {
|
|
"cXPmnv1M": [ "imDqfaBx", "NFxZ1bQe" ],
|
|
"vr7wY7CS": [ "EtCoNPPL", "9vAarJ5s" ]
|
|
},
|
|
"method": "wzByP903",
|
|
"body": "4I8ucZgZ",
|
|
"tcp": "2exjZIGE",
|
|
"interval": "5656s",
|
|
"output_max_size": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"docker_container_id": "5tDBWpfA",
|
|
"shell": "rlTpLM8s",
|
|
"tls_skip_verify": true,
|
|
"timeout": "4868s",
|
|
"ttl": "11222s",
|
|
"deregister_critical_service_after": "68482s"
|
|
}
|
|
],
|
|
"connect": {}
|
|
},
|
|
{
|
|
"id": "Kh81CPF6",
|
|
"kind": "connect-proxy",
|
|
"name": "Kh81CPF6-proxy",
|
|
"port": 31471,
|
|
"proxy": {
|
|
"config": {
|
|
"cedGGtZf": "pWrUNiWw"
|
|
},
|
|
"destination_service_id": "6L6BVfgH-id",
|
|
"destination_service_name": "6L6BVfgH",
|
|
"local_service_address": "127.0.0.2",
|
|
"local_service_port": 23759,
|
|
"expose": {
|
|
"checks": true,
|
|
"paths": [
|
|
{
|
|
"path": "/health",
|
|
"local_path_port": 8080,
|
|
"listener_port": 21500,
|
|
"protocol": "http"
|
|
}
|
|
]
|
|
},
|
|
"upstreams": [
|
|
{
|
|
"destination_name": "KPtAj2cb",
|
|
"local_bind_port": 4051,
|
|
"config": {
|
|
"kzRnZOyd": "nUNKoL8H"
|
|
}
|
|
},
|
|
{
|
|
"destination_name": "KSd8HsRl",
|
|
"destination_namespace": "9nakw0td",
|
|
"destination_type": "prepared_query",
|
|
"local_bind_address": "127.24.88.0",
|
|
"local_bind_port": 11884
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"id": "kvVqbwSE",
|
|
"kind": "mesh-gateway",
|
|
"name": "gw-primary-dc",
|
|
"port": 27147,
|
|
"proxy": {
|
|
"config": {
|
|
"1CuJHVfw" : "Kzqsa7yc"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"session_ttl_min": "26627s",
|
|
"skip_leave_on_interrupt": true,
|
|
"start_join": [ "LR3hGDoG", "MwVpZ4Up" ],
|
|
"start_join_wan": [ "EbFSc3nA", "kwXTh623" ],
|
|
"syslog_facility": "hHv79Uia",
|
|
"tagged_addresses": {
|
|
"7MYgHrYH": "dALJAhLD",
|
|
"h6DdBy6K": "ebrr9zZ8"
|
|
},
|
|
"telemetry": {
|
|
"circonus_api_app": "p4QOTe9j",
|
|
"circonus_api_token": "E3j35V23",
|
|
"circonus_api_url": "mEMjHpGg",
|
|
"circonus_broker_id": "BHlxUhed",
|
|
"circonus_broker_select_tag": "13xy1gHm",
|
|
"circonus_check_display_name": "DRSlQR6n",
|
|
"circonus_check_force_metric_activation": "Ua5FGVYf",
|
|
"circonus_check_id": "kGorutad",
|
|
"circonus_check_instance_id": "rwoOL6R4",
|
|
"circonus_check_search_tag": "ovT4hT4f",
|
|
"circonus_check_tags": "prvO4uBl",
|
|
"circonus_submission_interval": "DolzaflP",
|
|
"circonus_submission_url": "gTcbS93G",
|
|
"disable_hostname": true,
|
|
"dogstatsd_addr": "0wSndumK",
|
|
"dogstatsd_tags": [ "3N81zSUB","Xtj8AnXZ" ],
|
|
"filter_default": true,
|
|
"prefix_filter": [ "+oJotS8XJ","-cazlEhGn" ],
|
|
"metrics_prefix": "ftO6DySn",
|
|
"prometheus_retention_time": "15s",
|
|
"statsd_address": "drce87cy",
|
|
"statsite_address": "HpFwKB8R"
|
|
},
|
|
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
|
"tls_min_version": "pAOWafkR",
|
|
"tls_prefer_server_cipher_suites": true,
|
|
"translate_wan_addrs": true,
|
|
"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",
|
|
"user": "E0nB1DwA"
|
|
},
|
|
"verify_incoming": true,
|
|
"verify_incoming_https": true,
|
|
"verify_incoming_rpc": true,
|
|
"verify_outgoing": true,
|
|
"verify_server_hostname": true,
|
|
"watches": [
|
|
{
|
|
"type": "key",
|
|
"datacenter": "GyE6jpeW",
|
|
"key": "j9lF1Tve",
|
|
"handler": "90N7S4LN"
|
|
}, {
|
|
"type": "keyprefix",
|
|
"datacenter": "fYrl3F5d",
|
|
"key": "sl3Dffu7",
|
|
"args": ["dltjDJ2a", "flEa7C2d"]
|
|
}
|
|
]
|
|
}`,
|
|
"hcl": `
|
|
acl_agent_master_token = "furuQD0b"
|
|
acl_agent_token = "cOshLOQ2"
|
|
acl_datacenter = "m3urck3z"
|
|
acl_default_policy = "ArK3WIfE"
|
|
acl_down_policy = "vZXMfMP0"
|
|
acl_enable_key_list_policy = true
|
|
acl_master_token = "C1Q1oIwh"
|
|
acl_replication_token = "LMmgy5dO"
|
|
acl_token = "O1El0wan"
|
|
acl_ttl = "18060s"
|
|
acl = {
|
|
enabled = true
|
|
down_policy = "03eb2aee"
|
|
default_policy = "72c2e7a0"
|
|
enable_key_list_policy = true
|
|
enable_token_persistence = true
|
|
policy_ttl = "1123s"
|
|
role_ttl = "9876s"
|
|
token_ttl = "3321s"
|
|
enable_token_replication = true
|
|
msp_disable_bootstrap = true
|
|
tokens = {
|
|
master = "8a19ac27",
|
|
agent_master = "64fd0e08",
|
|
replication = "5795983a",
|
|
agent = "bed2377c",
|
|
default = "418fdff1",
|
|
managed_service_provider = [
|
|
{
|
|
accessor_id = "first",
|
|
secret_id = "fb0cee1f-2847-467c-99db-a897cff5fd4d"
|
|
},
|
|
{
|
|
accessor_id = "second",
|
|
secret_id = "1046c8da-e166-4667-897a-aefb343db9db"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
addresses = {
|
|
dns = "93.95.95.81"
|
|
http = "83.39.91.39"
|
|
https = "95.17.17.19"
|
|
grpc = "32.31.61.91"
|
|
}
|
|
advertise_addr = "17.99.29.16"
|
|
advertise_addr_wan = "78.63.37.19"
|
|
audit = {
|
|
enabled = false
|
|
}
|
|
auto_config = {
|
|
enabled = false
|
|
intro_token = "OpBPGRwt"
|
|
intro_token_file = "gFvAXwI8"
|
|
dns_sans = ["6zdaWg9J"]
|
|
ip_sans = ["198.18.99.99"]
|
|
server_addresses = ["198.18.100.1"]
|
|
authorization = {
|
|
enabled = true
|
|
static {
|
|
allow_reuse = true
|
|
claim_mappings = {
|
|
node = "node"
|
|
}
|
|
list_claim_mappings = {
|
|
foo = "bar"
|
|
}
|
|
bound_issuer = "consul"
|
|
bound_audiences = ["consul-cluster-1"]
|
|
claim_assertions = ["value.node == \"${node}\""]
|
|
jwt_validation_pub_keys = ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"]
|
|
}
|
|
}
|
|
}
|
|
autopilot = {
|
|
cleanup_dead_servers = true
|
|
disable_upgrade_migration = true
|
|
last_contact_threshold = "12705s"
|
|
max_trailing_logs = 17849
|
|
min_quorum = 3
|
|
redundancy_zone_tag = "3IsufDJf"
|
|
server_stabilization_time = "23057s"
|
|
upgrade_version_tag = "W9pDwFAL"
|
|
}
|
|
bind_addr = "16.99.34.17"
|
|
bootstrap = true
|
|
bootstrap_expect = 53
|
|
cache = {
|
|
entry_fetch_max_burst = 42
|
|
entry_fetch_rate = 0.334
|
|
},
|
|
ca_file = "erA7T0PM"
|
|
ca_path = "mQEN1Mfp"
|
|
cert_file = "7s4QAzDk"
|
|
check = {
|
|
id = "fZaCAXww"
|
|
name = "OOM2eo0f"
|
|
notes = "zXzXI9Gt"
|
|
service_id = "L8G0QNmR"
|
|
token = "oo4BCTgJ"
|
|
status = "qLykAl5u"
|
|
args = ["f3BemRjy", "e5zgpef7"]
|
|
http = "29B93haH"
|
|
header = {
|
|
hBq0zn1q = [ "2a9o9ZKP", "vKwA5lR6" ]
|
|
f3r6xFtM = [ "RyuIdDWv", "QbxEcIUM" ]
|
|
}
|
|
method = "Dou0nGT5"
|
|
body = "5PBQd2OT"
|
|
tcp = "JY6fTTcw"
|
|
interval = "18714s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "qF66POS9"
|
|
shell = "sOnDy228"
|
|
tls_skip_verify = true
|
|
timeout = "5954s"
|
|
ttl = "30044s"
|
|
deregister_critical_service_after = "13209s"
|
|
},
|
|
checks = [
|
|
{
|
|
id = "uAjE6m9Z"
|
|
name = "QsZRGpYr"
|
|
notes = "VJ7Sk4BY"
|
|
service_id = "lSulPcyz"
|
|
token = "toO59sh8"
|
|
status = "9RlWsXMV"
|
|
args = ["4BAJttck", "4D2NPtTQ"]
|
|
http = "dohLcyQ2"
|
|
header = {
|
|
"ZBfTin3L" = [ "1sDbEqYG", "lJGASsWK" ]
|
|
"Ui0nU99X" = [ "LMccm3Qe", "k5H5RggQ" ]
|
|
}
|
|
method = "aldrIQ4l"
|
|
body = "wSjTy7dg"
|
|
tcp = "RJQND605"
|
|
interval = "22164s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "ipgdFtjd"
|
|
shell = "qAeOYy0M"
|
|
tls_skip_verify = true
|
|
timeout = "1813s"
|
|
ttl = "21743s"
|
|
deregister_critical_service_after = "14232s"
|
|
},
|
|
{
|
|
id = "Cqq95BhP"
|
|
name = "3qXpkS0i"
|
|
notes = "sb5qLTex"
|
|
service_id = "CmUUcRna"
|
|
token = "a3nQzHuy"
|
|
status = "irj26nf3"
|
|
args = ["9s526ogY", "gSlOHj1w"]
|
|
http = "yzhgsQ7Y"
|
|
header = {
|
|
"zcqwA8dO" = [ "qb1zx0DL", "sXCxPFsD" ]
|
|
"qxvdnSE9" = [ "6wBPUYdF", "YYh8wtSZ" ]
|
|
}
|
|
method = "gLrztrNw"
|
|
body = "0jkKgGUC"
|
|
tcp = "4jG5casb"
|
|
interval = "28767s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "THW6u7rL"
|
|
shell = "C1Zt3Zwh"
|
|
tls_skip_verify = true
|
|
timeout = "18506s"
|
|
ttl = "31006s"
|
|
deregister_critical_service_after = "2366s"
|
|
}
|
|
]
|
|
check_update_interval = "16507s"
|
|
client_addr = "93.83.18.19"
|
|
config_entries {
|
|
# This is using the repeated block-to-array HCL magic
|
|
bootstrap {
|
|
kind = "proxy-defaults"
|
|
name = "global"
|
|
config {
|
|
foo = "bar"
|
|
bar = 1.0
|
|
}
|
|
}
|
|
}
|
|
auto_encrypt = {
|
|
tls = false
|
|
dns_san = ["a.com", "b.com"]
|
|
ip_san = ["192.168.4.139", "192.168.4.140"]
|
|
allow_tls = true
|
|
}
|
|
connect {
|
|
ca_provider = "consul"
|
|
ca_config {
|
|
rotation_period = "90h"
|
|
intermediate_cert_ttl = "8760h"
|
|
leaf_cert_ttl = "1h"
|
|
# hack float since json parses numbers as float and we have to
|
|
# assert against the same thing
|
|
csr_max_per_second = 100.0
|
|
csr_max_concurrent = 2.0
|
|
}
|
|
enable_mesh_gateway_wan_federation = false
|
|
enabled = true
|
|
}
|
|
gossip_lan {
|
|
gossip_nodes = 6
|
|
gossip_interval = "25252s"
|
|
retransmit_mult = 1234
|
|
suspicion_mult = 1235
|
|
probe_interval = "101ms"
|
|
probe_timeout = "102ms"
|
|
}
|
|
gossip_wan {
|
|
gossip_nodes = 2
|
|
gossip_interval = "6966s"
|
|
retransmit_mult = 16384
|
|
suspicion_mult = 16385
|
|
probe_interval = "103ms"
|
|
probe_timeout = "104ms"
|
|
}
|
|
data_dir = "` + dataDir + `"
|
|
datacenter = "rzo029wg"
|
|
default_query_time = "16743s"
|
|
disable_anonymous_signature = true
|
|
disable_coordinates = true
|
|
disable_host_node_id = true
|
|
disable_http_unprintable_char_filter = true
|
|
disable_keyring_file = true
|
|
disable_remote_exec = true
|
|
disable_update_check = true
|
|
discard_check_output = true
|
|
discovery_max_stale = "5s"
|
|
domain = "7W1xXSqd"
|
|
alt_domain = "1789hsd"
|
|
dns_config {
|
|
allow_stale = true
|
|
a_record_limit = 29907
|
|
disable_compression = true
|
|
enable_truncate = true
|
|
max_stale = "29685s"
|
|
node_ttl = "7084s"
|
|
only_passing = true
|
|
recursor_timeout = "4427s"
|
|
service_ttl = {
|
|
"*" = "32030s"
|
|
}
|
|
udp_answer_limit = 29909
|
|
use_cache = true
|
|
cache_max_age = "5m"
|
|
prefer_namespace = true
|
|
}
|
|
enable_acl_replication = true
|
|
enable_agent_tls_for_checks = true
|
|
enable_central_service_config = false
|
|
enable_debug = true
|
|
enable_script_checks = true
|
|
enable_local_script_checks = true
|
|
enable_syslog = true
|
|
encrypt = "A4wELWqH"
|
|
encrypt_verify_incoming = true
|
|
encrypt_verify_outgoing = true
|
|
http_config {
|
|
block_endpoints = [ "RBvAFcGD", "fWOWFznh" ]
|
|
allow_write_http_from = [ "127.0.0.1/8", "22.33.44.55/32", "0.0.0.0/0" ]
|
|
response_headers = {
|
|
"M6TKa9NP" = "xjuxjOzQ"
|
|
"JRCrHZed" = "rl0mTx81"
|
|
}
|
|
use_cache = false
|
|
}
|
|
key_file = "IEkkwgIA"
|
|
leave_on_terminate = true
|
|
limits {
|
|
http_max_conns_per_client = 100
|
|
https_handshake_timeout = "2391ms"
|
|
rpc_handshake_timeout = "1932ms"
|
|
rpc_rate = 12029.43
|
|
rpc_max_burst = 44848
|
|
rpc_max_conns_per_client = 2954
|
|
kv_max_value_size = 1234567800000000
|
|
txn_max_req_len = 5678000000000000
|
|
}
|
|
log_level = "k1zo9Spt"
|
|
log_json = true
|
|
max_query_time = "18237s"
|
|
node_id = "AsUIlw99"
|
|
node_meta {
|
|
"5mgGQMBk" = "mJLtVMSG"
|
|
"A7ynFMJB" = "0Nx6RGab"
|
|
}
|
|
node_name = "otlLxGaI"
|
|
non_voting_server = true
|
|
performance {
|
|
leave_drain_time = "8265s"
|
|
raft_multiplier = 5
|
|
rpc_hold_timeout = "15707s"
|
|
}
|
|
pid_file = "43xN80Km"
|
|
ports {
|
|
dns = 7001
|
|
http = 7999
|
|
https = 15127
|
|
server = 3757
|
|
grpc = 4881
|
|
proxy_min_port = 2000
|
|
proxy_max_port = 3000
|
|
sidecar_min_port = 8888
|
|
sidecar_max_port = 9999
|
|
expose_min_port = 1111
|
|
expose_max_port = 2222
|
|
}
|
|
protocol = 30793
|
|
primary_datacenter = "ejtmd43d"
|
|
primary_gateways = [ "aej8eeZo", "roh2KahS" ]
|
|
primary_gateways_interval = "18866s"
|
|
raft_protocol = 19016
|
|
raft_snapshot_threshold = 16384
|
|
raft_snapshot_interval = "30s"
|
|
raft_trailing_logs = 83749
|
|
reconnect_timeout = "23739s"
|
|
reconnect_timeout_wan = "26694s"
|
|
recursors = [ "63.38.39.58", "92.49.18.18" ]
|
|
rejoin_after_leave = true
|
|
retry_interval = "8067s"
|
|
retry_interval_wan = "28866s"
|
|
retry_join = [ "pbsSFY7U", "l0qLtWij" ]
|
|
retry_join_wan = [ "PFsR02Ye", "rJdQIhER" ]
|
|
retry_max = 913
|
|
retry_max_wan = 23160
|
|
segment = "BC2NhTDi"
|
|
segments = [
|
|
{
|
|
name = "PExYMe2E"
|
|
bind = "36.73.36.19"
|
|
port = 38295
|
|
rpc_listener = true
|
|
advertise = "63.39.19.18"
|
|
},
|
|
{
|
|
name = "UzCvJgup"
|
|
bind = "37.58.38.19"
|
|
port = 39292
|
|
rpc_listener = true
|
|
advertise = "83.58.26.27"
|
|
}
|
|
]
|
|
serf_lan = "99.43.63.15"
|
|
serf_wan = "67.88.33.19"
|
|
server = true
|
|
server_name = "Oerr9n1G"
|
|
service = {
|
|
id = "dLOXpSCI"
|
|
name = "o1ynPkp0"
|
|
meta = {
|
|
mymeta = "data"
|
|
}
|
|
tagged_addresses = {
|
|
lan = {
|
|
address = "2d79888a"
|
|
port = 2143
|
|
}
|
|
wan = {
|
|
address = "d4db85e2"
|
|
port = 6109
|
|
}
|
|
}
|
|
tags = ["nkwshvM5", "NTDWn3ek"]
|
|
address = "cOlSOhbp"
|
|
token = "msy7iWER"
|
|
port = 24237
|
|
weights = {
|
|
passing = 100,
|
|
warning = 1
|
|
}
|
|
enable_tag_override = true
|
|
check = {
|
|
id = "RMi85Dv8"
|
|
name = "iehanzuq"
|
|
status = "rCvn53TH"
|
|
notes = "fti5lfF3"
|
|
args = ["16WRUmwS", "QWk7j7ae"]
|
|
http = "dl3Fgme3"
|
|
header = {
|
|
rjm4DEd3 = [ "2m3m2Fls" ]
|
|
l4HwQ112 = [ "fk56MNlo", "dhLK56aZ" ]
|
|
}
|
|
method = "9afLm3Mj"
|
|
body = "wVVL2V6f"
|
|
tcp = "fjiLFqVd"
|
|
interval = "23926s"
|
|
docker_container_id = "dO5TtRHk"
|
|
shell = "e6q2ttES"
|
|
tls_skip_verify = true
|
|
timeout = "38483s"
|
|
ttl = "10943s"
|
|
deregister_critical_service_after = "68787s"
|
|
}
|
|
checks = [
|
|
{
|
|
id = "Zv99e9Ka"
|
|
name = "sgV4F7Pk"
|
|
notes = "yP5nKbW0"
|
|
status = "7oLMEyfu"
|
|
args = ["5wEZtZpv", "0Ihyk8cS"]
|
|
http = "KyDjGY9H"
|
|
header = {
|
|
"gv5qefTz" = [ "5Olo2pMG", "PvvKWQU5" ]
|
|
"SHOVq1Vv" = [ "jntFhyym", "GYJh32pp" ]
|
|
}
|
|
method = "T66MFBfR"
|
|
body = "OwGjTFQi"
|
|
tcp = "bNnNfx2A"
|
|
interval = "22224s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "ipgdFtjd"
|
|
shell = "omVZq7Sz"
|
|
tls_skip_verify = true
|
|
timeout = "18913s"
|
|
ttl = "44743s"
|
|
deregister_critical_service_after = "8482s"
|
|
},
|
|
{
|
|
id = "G79O6Mpr"
|
|
name = "IEqrzrsd"
|
|
notes = "SVqApqeM"
|
|
status = "XXkVoZXt"
|
|
args = ["wD05Bvao", "rLYB7kQC"]
|
|
http = "kyICZsn8"
|
|
header = {
|
|
"4ebP5vL4" = [ "G20SrL5Q", "DwPKlMbo" ]
|
|
"p2UI34Qz" = [ "UsG1D0Qh", "NHhRiB6s" ]
|
|
}
|
|
method = "ciYHWors"
|
|
body = "lUVLGYU7"
|
|
tcp = "FfvCwlqH"
|
|
interval = "12356s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "HBndBU6R"
|
|
shell = "hVI33JjA"
|
|
tls_skip_verify = true
|
|
timeout = "38282s"
|
|
ttl = "1181s"
|
|
deregister_critical_service_after = "4992s"
|
|
}
|
|
]
|
|
connect {
|
|
native = true
|
|
}
|
|
}
|
|
services = [
|
|
{
|
|
id = "wI1dzxS4"
|
|
name = "7IszXMQ1"
|
|
tags = ["0Zwg8l6v", "zebELdN5"]
|
|
address = "9RhqPSPB"
|
|
token = "myjKJkWH"
|
|
port = 72219
|
|
enable_tag_override = true
|
|
check = {
|
|
id = "qmfeO5if"
|
|
name = "atDGP7n5"
|
|
status = "pDQKEhWL"
|
|
notes = "Yt8EDLev"
|
|
args = ["81EDZLPa", "bPY5X8xd"]
|
|
http = "qzHYvmJO"
|
|
header = {
|
|
UkpmZ3a3 = [ "2dfzXuxZ" ]
|
|
cVFpko4u = [ "gGqdEB6k", "9LsRo22u" ]
|
|
}
|
|
method = "X5DrovFc"
|
|
body = "WeikigLh"
|
|
tcp = "ICbxkpSF"
|
|
interval = "24392s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "ZKXr68Yb"
|
|
shell = "CEfzx0Fo"
|
|
tls_skip_verify = true
|
|
timeout = "38333s"
|
|
ttl = "57201s"
|
|
deregister_critical_service_after = "44214s"
|
|
}
|
|
connect {
|
|
sidecar_service {}
|
|
}
|
|
},
|
|
{
|
|
id = "MRHVMZuD"
|
|
name = "6L6BVfgH"
|
|
tags = ["7Ale4y6o", "PMBW08hy"]
|
|
address = "R6H6g8h0"
|
|
token = "ZgY8gjMI"
|
|
port = 38292
|
|
weights = {
|
|
passing = 1979,
|
|
warning = 6
|
|
}
|
|
enable_tag_override = true
|
|
checks = [
|
|
{
|
|
id = "GTti9hCo"
|
|
name = "9OOS93ne"
|
|
notes = "CQy86DH0"
|
|
status = "P0SWDvrk"
|
|
args = ["EXvkYIuG", "BATOyt6h"]
|
|
http = "u97ByEiW"
|
|
header = {
|
|
"MUlReo8L" = [ "AUZG7wHG", "gsN0Dc2N" ]
|
|
"1UJXjVrT" = [ "OJgxzTfk", "xZZrFsq7" ]
|
|
}
|
|
method = "5wkAxCUE"
|
|
body = "7CRjCJyz"
|
|
tcp = "MN3oA9D2"
|
|
interval = "32718s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "cU15LMet"
|
|
shell = "nEz9qz2l"
|
|
tls_skip_verify = true
|
|
timeout = "34738s"
|
|
ttl = "22773s"
|
|
deregister_critical_service_after = "84282s"
|
|
},
|
|
{
|
|
id = "UHsDeLxG"
|
|
name = "PQSaPWlT"
|
|
notes = "jKChDOdl"
|
|
status = "5qFz6OZn"
|
|
args = ["NMtYWlT9", "vj74JXsm"]
|
|
http = "1LBDJhw4"
|
|
header = {
|
|
"cXPmnv1M" = [ "imDqfaBx", "NFxZ1bQe" ],
|
|
"vr7wY7CS" = [ "EtCoNPPL", "9vAarJ5s" ]
|
|
}
|
|
method = "wzByP903"
|
|
body = "4I8ucZgZ"
|
|
tcp = "2exjZIGE"
|
|
interval = "5656s"
|
|
output_max_size = ` + strconv.Itoa(checks.DefaultBufSize) + `
|
|
docker_container_id = "5tDBWpfA"
|
|
shell = "rlTpLM8s"
|
|
tls_skip_verify = true
|
|
timeout = "4868s"
|
|
ttl = "11222s"
|
|
deregister_critical_service_after = "68482s"
|
|
}
|
|
]
|
|
connect {}
|
|
},
|
|
{
|
|
id = "Kh81CPF6"
|
|
name = "Kh81CPF6-proxy"
|
|
port = 31471
|
|
kind = "connect-proxy"
|
|
proxy {
|
|
destination_service_name = "6L6BVfgH"
|
|
destination_service_id = "6L6BVfgH-id"
|
|
local_service_address = "127.0.0.2"
|
|
local_service_port = 23759
|
|
config {
|
|
cedGGtZf = "pWrUNiWw"
|
|
}
|
|
upstreams = [
|
|
{
|
|
destination_name = "KPtAj2cb"
|
|
local_bind_port = 4051
|
|
config {
|
|
kzRnZOyd = "nUNKoL8H"
|
|
}
|
|
},
|
|
{
|
|
destination_type = "prepared_query"
|
|
destination_namespace = "9nakw0td"
|
|
destination_name = "KSd8HsRl"
|
|
local_bind_port = 11884
|
|
local_bind_address = "127.24.88.0"
|
|
},
|
|
]
|
|
expose {
|
|
checks = true
|
|
paths = [
|
|
{
|
|
path = "/health"
|
|
local_path_port = 8080
|
|
listener_port = 21500
|
|
protocol = "http"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id = "kvVqbwSE"
|
|
kind = "mesh-gateway"
|
|
name = "gw-primary-dc"
|
|
port = 27147
|
|
proxy {
|
|
config {
|
|
"1CuJHVfw" = "Kzqsa7yc"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
session_ttl_min = "26627s"
|
|
skip_leave_on_interrupt = true
|
|
start_join = [ "LR3hGDoG", "MwVpZ4Up" ]
|
|
start_join_wan = [ "EbFSc3nA", "kwXTh623" ]
|
|
syslog_facility = "hHv79Uia"
|
|
tagged_addresses = {
|
|
"7MYgHrYH" = "dALJAhLD"
|
|
"h6DdBy6K" = "ebrr9zZ8"
|
|
}
|
|
telemetry {
|
|
circonus_api_app = "p4QOTe9j"
|
|
circonus_api_token = "E3j35V23"
|
|
circonus_api_url = "mEMjHpGg"
|
|
circonus_broker_id = "BHlxUhed"
|
|
circonus_broker_select_tag = "13xy1gHm"
|
|
circonus_check_display_name = "DRSlQR6n"
|
|
circonus_check_force_metric_activation = "Ua5FGVYf"
|
|
circonus_check_id = "kGorutad"
|
|
circonus_check_instance_id = "rwoOL6R4"
|
|
circonus_check_search_tag = "ovT4hT4f"
|
|
circonus_check_tags = "prvO4uBl"
|
|
circonus_submission_interval = "DolzaflP"
|
|
circonus_submission_url = "gTcbS93G"
|
|
disable_hostname = true
|
|
dogstatsd_addr = "0wSndumK"
|
|
dogstatsd_tags = [ "3N81zSUB","Xtj8AnXZ" ]
|
|
filter_default = true
|
|
prefix_filter = [ "+oJotS8XJ","-cazlEhGn" ]
|
|
metrics_prefix = "ftO6DySn"
|
|
prometheus_retention_time = "15s"
|
|
statsd_address = "drce87cy"
|
|
statsite_address = "HpFwKB8R"
|
|
}
|
|
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
|
|
tls_min_version = "pAOWafkR"
|
|
tls_prefer_server_cipher_suites = true
|
|
translate_wan_addrs = true
|
|
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"
|
|
user = "E0nB1DwA"
|
|
}
|
|
verify_incoming = true
|
|
verify_incoming_https = true
|
|
verify_incoming_rpc = true
|
|
verify_outgoing = true
|
|
verify_server_hostname = true
|
|
watches = [{
|
|
type = "key"
|
|
datacenter = "GyE6jpeW"
|
|
key = "j9lF1Tve"
|
|
handler = "90N7S4LN"
|
|
}, {
|
|
type = "keyprefix"
|
|
datacenter = "fYrl3F5d"
|
|
key = "sl3Dffu7"
|
|
args = ["dltjDJ2a", "flEa7C2d"]
|
|
}]
|
|
`}
|
|
|
|
tail := map[string][]Source{
|
|
"json": {
|
|
FileSource{
|
|
Name: "tail.non-user.json",
|
|
Format: "json",
|
|
Data: `
|
|
{
|
|
"acl_disabled_ttl": "957s",
|
|
"acl" : {
|
|
"disabled_ttl" : "957s"
|
|
},
|
|
"ae_interval": "10003s",
|
|
"check_deregister_interval_min": "27870s",
|
|
"check_reap_interval": "10662s",
|
|
"discovery_max_stale": "5s",
|
|
"segment_limit": 24705,
|
|
"segment_name_limit": 27046,
|
|
"sync_coordinate_interval_min": "27983s",
|
|
"sync_coordinate_rate_target": 137.81
|
|
}`,
|
|
},
|
|
FileSource{
|
|
Name: "tail.consul.json",
|
|
Format: "json",
|
|
Data: `
|
|
{
|
|
"consul": {
|
|
"coordinate": {
|
|
"update_batch_size": 9244,
|
|
"update_max_batches": 15164,
|
|
"update_period": "25093s"
|
|
},
|
|
"raft": {
|
|
"election_timeout": "31947s",
|
|
"heartbeat_timeout": "25699s",
|
|
"leader_lease_timeout": "15351s"
|
|
},
|
|
"server": {
|
|
"health_interval": "17455s"
|
|
}
|
|
}
|
|
}`,
|
|
},
|
|
},
|
|
"hcl": {
|
|
FileSource{
|
|
Name: "tail.non-user.hcl",
|
|
Format: "hcl",
|
|
Data: `
|
|
acl_disabled_ttl = "957s"
|
|
acl = {
|
|
disabled_ttl = "957s"
|
|
}
|
|
ae_interval = "10003s"
|
|
check_deregister_interval_min = "27870s"
|
|
check_reap_interval = "10662s"
|
|
discovery_max_stale = "5s"
|
|
segment_limit = 24705
|
|
segment_name_limit = 27046
|
|
sync_coordinate_interval_min = "27983s"
|
|
sync_coordinate_rate_target = 137.81
|
|
`,
|
|
},
|
|
FileSource{
|
|
Name: "tail.consul.hcl",
|
|
Format: "hcl",
|
|
Data: `
|
|
consul = {
|
|
coordinate = {
|
|
update_batch_size = 9244
|
|
update_max_batches = 15164
|
|
update_period = "25093s"
|
|
}
|
|
raft = {
|
|
election_timeout = "31947s"
|
|
heartbeat_timeout = "25699s"
|
|
leader_lease_timeout = "15351s"
|
|
}
|
|
server = {
|
|
health_interval = "17455s"
|
|
}
|
|
}
|
|
`,
|
|
},
|
|
},
|
|
}
|
|
|
|
want := RuntimeConfig{
|
|
// non-user configurable values
|
|
ACLDisabledTTL: 957 * time.Second,
|
|
AEInterval: 10003 * time.Second,
|
|
CheckDeregisterIntervalMin: 27870 * time.Second,
|
|
CheckReapInterval: 10662 * time.Second,
|
|
SegmentLimit: 24705,
|
|
SegmentNameLimit: 27046,
|
|
SyncCoordinateIntervalMin: 27983 * time.Second,
|
|
SyncCoordinateRateTarget: 137.81,
|
|
|
|
Revision: "JNtPSav3",
|
|
Version: "R909Hblt",
|
|
VersionPrerelease: "ZT1JOQLn",
|
|
|
|
// consul configuration
|
|
ConsulCoordinateUpdateBatchSize: 9244,
|
|
ConsulCoordinateUpdateMaxBatches: 15164,
|
|
ConsulCoordinateUpdatePeriod: 25093 * time.Second,
|
|
ConsulRaftElectionTimeout: 5 * 31947 * time.Second,
|
|
ConsulRaftHeartbeatTimeout: 5 * 25699 * time.Second,
|
|
ConsulRaftLeaderLeaseTimeout: 5 * 15351 * time.Second,
|
|
GossipLANGossipInterval: 25252 * time.Second,
|
|
GossipLANGossipNodes: 6,
|
|
GossipLANProbeInterval: 101 * time.Millisecond,
|
|
GossipLANProbeTimeout: 102 * time.Millisecond,
|
|
GossipLANSuspicionMult: 1235,
|
|
GossipLANRetransmitMult: 1234,
|
|
GossipWANGossipInterval: 6966 * time.Second,
|
|
GossipWANGossipNodes: 2,
|
|
GossipWANProbeInterval: 103 * time.Millisecond,
|
|
GossipWANProbeTimeout: 104 * time.Millisecond,
|
|
GossipWANSuspicionMult: 16385,
|
|
GossipWANRetransmitMult: 16384,
|
|
ConsulServerHealthInterval: 17455 * time.Second,
|
|
|
|
// user configurable values
|
|
|
|
ACLTokens: token.Config{
|
|
EnablePersistence: true,
|
|
DataDir: dataDir,
|
|
ACLDefaultToken: "418fdff1",
|
|
ACLAgentToken: "bed2377c",
|
|
ACLAgentMasterToken: "64fd0e08",
|
|
ACLReplicationToken: "5795983a",
|
|
},
|
|
|
|
ACLsEnabled: true,
|
|
ACLDatacenter: "ejtmd43d",
|
|
ACLDefaultPolicy: "72c2e7a0",
|
|
ACLDownPolicy: "03eb2aee",
|
|
ACLEnableKeyListPolicy: true,
|
|
ACLMasterToken: "8a19ac27",
|
|
ACLTokenTTL: 3321 * time.Second,
|
|
ACLPolicyTTL: 1123 * time.Second,
|
|
ACLRoleTTL: 9876 * time.Second,
|
|
ACLTokenReplication: true,
|
|
AdvertiseAddrLAN: ipAddr("17.99.29.16"),
|
|
AdvertiseAddrWAN: ipAddr("78.63.37.19"),
|
|
AutopilotCleanupDeadServers: true,
|
|
AutopilotDisableUpgradeMigration: true,
|
|
AutopilotLastContactThreshold: 12705 * time.Second,
|
|
AutopilotMaxTrailingLogs: 17849,
|
|
AutopilotMinQuorum: 3,
|
|
AutopilotRedundancyZoneTag: "3IsufDJf",
|
|
AutopilotServerStabilizationTime: 23057 * time.Second,
|
|
AutopilotUpgradeVersionTag: "W9pDwFAL",
|
|
BindAddr: ipAddr("16.99.34.17"),
|
|
Bootstrap: true,
|
|
BootstrapExpect: 53,
|
|
Cache: cache.Options{
|
|
EntryFetchMaxBurst: 42,
|
|
EntryFetchRate: 0.334,
|
|
},
|
|
CAFile: "erA7T0PM",
|
|
CAPath: "mQEN1Mfp",
|
|
CertFile: "7s4QAzDk",
|
|
CheckOutputMaxSize: checks.DefaultBufSize,
|
|
Checks: []*structs.CheckDefinition{
|
|
{
|
|
ID: "uAjE6m9Z",
|
|
Name: "QsZRGpYr",
|
|
Notes: "VJ7Sk4BY",
|
|
ServiceID: "lSulPcyz",
|
|
Token: "toO59sh8",
|
|
Status: "9RlWsXMV",
|
|
ScriptArgs: []string{"4BAJttck", "4D2NPtTQ"},
|
|
HTTP: "dohLcyQ2",
|
|
Header: map[string][]string{
|
|
"ZBfTin3L": {"1sDbEqYG", "lJGASsWK"},
|
|
"Ui0nU99X": {"LMccm3Qe", "k5H5RggQ"},
|
|
},
|
|
Method: "aldrIQ4l",
|
|
Body: "wSjTy7dg",
|
|
TCP: "RJQND605",
|
|
Interval: 22164 * time.Second,
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
DockerContainerID: "ipgdFtjd",
|
|
Shell: "qAeOYy0M",
|
|
TLSSkipVerify: true,
|
|
Timeout: 1813 * time.Second,
|
|
TTL: 21743 * time.Second,
|
|
DeregisterCriticalServiceAfter: 14232 * time.Second,
|
|
},
|
|
{
|
|
ID: "Cqq95BhP",
|
|
Name: "3qXpkS0i",
|
|
Notes: "sb5qLTex",
|
|
ServiceID: "CmUUcRna",
|
|
Token: "a3nQzHuy",
|
|
Status: "irj26nf3",
|
|
ScriptArgs: []string{"9s526ogY", "gSlOHj1w"},
|
|
HTTP: "yzhgsQ7Y",
|
|
Header: map[string][]string{
|
|
"zcqwA8dO": {"qb1zx0DL", "sXCxPFsD"},
|
|
"qxvdnSE9": {"6wBPUYdF", "YYh8wtSZ"},
|
|
},
|
|
Method: "gLrztrNw",
|
|
Body: "0jkKgGUC",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "4jG5casb",
|
|
Interval: 28767 * time.Second,
|
|
DockerContainerID: "THW6u7rL",
|
|
Shell: "C1Zt3Zwh",
|
|
TLSSkipVerify: true,
|
|
Timeout: 18506 * time.Second,
|
|
TTL: 31006 * time.Second,
|
|
DeregisterCriticalServiceAfter: 2366 * time.Second,
|
|
},
|
|
{
|
|
ID: "fZaCAXww",
|
|
Name: "OOM2eo0f",
|
|
Notes: "zXzXI9Gt",
|
|
ServiceID: "L8G0QNmR",
|
|
Token: "oo4BCTgJ",
|
|
Status: "qLykAl5u",
|
|
ScriptArgs: []string{"f3BemRjy", "e5zgpef7"},
|
|
HTTP: "29B93haH",
|
|
Header: map[string][]string{
|
|
"hBq0zn1q": {"2a9o9ZKP", "vKwA5lR6"},
|
|
"f3r6xFtM": {"RyuIdDWv", "QbxEcIUM"},
|
|
},
|
|
Method: "Dou0nGT5",
|
|
Body: "5PBQd2OT",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "JY6fTTcw",
|
|
Interval: 18714 * time.Second,
|
|
DockerContainerID: "qF66POS9",
|
|
Shell: "sOnDy228",
|
|
TLSSkipVerify: true,
|
|
Timeout: 5954 * time.Second,
|
|
TTL: 30044 * time.Second,
|
|
DeregisterCriticalServiceAfter: 13209 * time.Second,
|
|
},
|
|
},
|
|
CheckUpdateInterval: 16507 * time.Second,
|
|
ClientAddrs: []*net.IPAddr{ipAddr("93.83.18.19")},
|
|
ConfigEntryBootstrap: []structs.ConfigEntry{
|
|
&structs.ProxyConfigEntry{
|
|
Kind: structs.ProxyDefaults,
|
|
Name: structs.ProxyConfigGlobal,
|
|
EnterpriseMeta: *defaultEntMeta,
|
|
Config: map[string]interface{}{
|
|
"foo": "bar",
|
|
// has to be a float due to being a map[string]interface
|
|
"bar": float64(1),
|
|
},
|
|
},
|
|
},
|
|
AutoEncryptTLS: false,
|
|
AutoEncryptDNSSAN: []string{"a.com", "b.com"},
|
|
AutoEncryptIPSAN: []net.IP{net.ParseIP("192.168.4.139"), net.ParseIP("192.168.4.140")},
|
|
AutoEncryptAllowTLS: true,
|
|
AutoConfig: AutoConfig{
|
|
Enabled: false,
|
|
IntroToken: "OpBPGRwt",
|
|
IntroTokenFile: "gFvAXwI8",
|
|
DNSSANs: []string{"6zdaWg9J"},
|
|
IPSANs: []net.IP{net.IPv4(198, 18, 99, 99)},
|
|
ServerAddresses: []string{"198.18.100.1"},
|
|
Authorizer: AutoConfigAuthorizer{
|
|
Enabled: true,
|
|
AllowReuse: true,
|
|
ClaimAssertions: []string{"value.node == \"${node}\""},
|
|
AuthMethod: structs.ACLAuthMethod{
|
|
Name: "Auto Config Authorizer",
|
|
Type: "jwt",
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
Config: map[string]interface{}{
|
|
"JWTValidationPubKeys": []string{"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERVchfCZng4mmdvQz1+sJHRN40snC\nYt8NjYOnbnScEXMkyoUmASr88gb7jaVAVt3RYASAbgBjB2Z+EUizWkx5Tg==\n-----END PUBLIC KEY-----"},
|
|
"ClaimMappings": map[string]string{
|
|
"node": "node",
|
|
},
|
|
"BoundIssuer": "consul",
|
|
"BoundAudiences": []string{"consul-cluster-1"},
|
|
"ListClaimMappings": map[string]string{
|
|
"foo": "bar",
|
|
},
|
|
"OIDCDiscoveryURL": "",
|
|
"OIDCDiscoveryCACert": "",
|
|
"JWKSURL": "",
|
|
"JWKSCACert": "",
|
|
"ExpirationLeeway": 0 * time.Second,
|
|
"NotBeforeLeeway": 0 * time.Second,
|
|
"ClockSkewLeeway": 0 * time.Second,
|
|
"JWTSupportedAlgs": []string(nil),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
ConnectEnabled: true,
|
|
ConnectSidecarMinPort: 8888,
|
|
ConnectSidecarMaxPort: 9999,
|
|
ExposeMinPort: 1111,
|
|
ExposeMaxPort: 2222,
|
|
ConnectCAProvider: "consul",
|
|
ConnectCAConfig: map[string]interface{}{
|
|
"RotationPeriod": "90h",
|
|
"IntermediateCertTTL": "8760h",
|
|
"LeafCertTTL": "1h",
|
|
"CSRMaxPerSecond": float64(100),
|
|
"CSRMaxConcurrent": float64(2),
|
|
},
|
|
ConnectMeshGatewayWANFederationEnabled: false,
|
|
DNSAddrs: []net.Addr{tcpAddr("93.95.95.81:7001"), udpAddr("93.95.95.81:7001")},
|
|
DNSARecordLimit: 29907,
|
|
DNSAllowStale: true,
|
|
DNSDisableCompression: true,
|
|
DNSDomain: "7W1xXSqd",
|
|
DNSAltDomain: "1789hsd",
|
|
DNSEnableTruncate: true,
|
|
DNSMaxStale: 29685 * time.Second,
|
|
DNSNodeTTL: 7084 * time.Second,
|
|
DNSOnlyPassing: true,
|
|
DNSPort: 7001,
|
|
DNSRecursorTimeout: 4427 * time.Second,
|
|
DNSRecursors: []string{"63.38.39.58", "92.49.18.18"},
|
|
DNSSOA: RuntimeSOAConfig{Refresh: 3600, Retry: 600, Expire: 86400, Minttl: 0},
|
|
DNSServiceTTL: map[string]time.Duration{"*": 32030 * time.Second},
|
|
DNSUDPAnswerLimit: 29909,
|
|
DNSNodeMetaTXT: true,
|
|
DNSUseCache: true,
|
|
DNSCacheMaxAge: 5 * time.Minute,
|
|
DataDir: dataDir,
|
|
Datacenter: "rzo029wg",
|
|
DefaultQueryTime: 16743 * time.Second,
|
|
DevMode: true,
|
|
DisableAnonymousSignature: true,
|
|
DisableCoordinates: true,
|
|
DisableHostNodeID: true,
|
|
DisableHTTPUnprintableCharFilter: true,
|
|
DisableKeyringFile: true,
|
|
DisableRemoteExec: true,
|
|
DisableUpdateCheck: true,
|
|
DiscardCheckOutput: true,
|
|
DiscoveryMaxStale: 5 * time.Second,
|
|
EnableAgentTLSForChecks: true,
|
|
EnableCentralServiceConfig: false,
|
|
EnableDebug: true,
|
|
EnableRemoteScriptChecks: true,
|
|
EnableLocalScriptChecks: true,
|
|
EncryptKey: "A4wELWqH",
|
|
EncryptVerifyIncoming: true,
|
|
EncryptVerifyOutgoing: true,
|
|
GRPCPort: 4881,
|
|
GRPCAddrs: []net.Addr{tcpAddr("32.31.61.91:4881")},
|
|
HTTPAddrs: []net.Addr{tcpAddr("83.39.91.39:7999")},
|
|
HTTPBlockEndpoints: []string{"RBvAFcGD", "fWOWFznh"},
|
|
AllowWriteHTTPFrom: []*net.IPNet{cidr("127.0.0.0/8"), cidr("22.33.44.55/32"), cidr("0.0.0.0/0")},
|
|
HTTPPort: 7999,
|
|
HTTPResponseHeaders: map[string]string{"M6TKa9NP": "xjuxjOzQ", "JRCrHZed": "rl0mTx81"},
|
|
HTTPSAddrs: []net.Addr{tcpAddr("95.17.17.19:15127")},
|
|
HTTPMaxConnsPerClient: 100,
|
|
HTTPSHandshakeTimeout: 2391 * time.Millisecond,
|
|
HTTPSPort: 15127,
|
|
HTTPUseCache: false,
|
|
KeyFile: "IEkkwgIA",
|
|
KVMaxValueSize: 1234567800000000,
|
|
LeaveDrainTime: 8265 * time.Second,
|
|
LeaveOnTerm: true,
|
|
Logging: logging.Config{
|
|
LogLevel: "k1zo9Spt",
|
|
LogJSON: true,
|
|
EnableSyslog: true,
|
|
SyslogFacility: "hHv79Uia",
|
|
},
|
|
MaxQueryTime: 18237 * time.Second,
|
|
NodeID: types.NodeID("AsUIlw99"),
|
|
NodeMeta: map[string]string{"5mgGQMBk": "mJLtVMSG", "A7ynFMJB": "0Nx6RGab"},
|
|
NodeName: "otlLxGaI",
|
|
NonVotingServer: true,
|
|
PidFile: "43xN80Km",
|
|
PrimaryDatacenter: "ejtmd43d",
|
|
PrimaryGateways: []string{"aej8eeZo", "roh2KahS"},
|
|
PrimaryGatewaysInterval: 18866 * time.Second,
|
|
RPCAdvertiseAddr: tcpAddr("17.99.29.16:3757"),
|
|
RPCBindAddr: tcpAddr("16.99.34.17:3757"),
|
|
RPCHandshakeTimeout: 1932 * time.Millisecond,
|
|
RPCHoldTimeout: 15707 * time.Second,
|
|
RPCProtocol: 30793,
|
|
RPCRateLimit: 12029.43,
|
|
RPCMaxBurst: 44848,
|
|
RPCMaxConnsPerClient: 2954,
|
|
RaftProtocol: 19016,
|
|
RaftSnapshotThreshold: 16384,
|
|
RaftSnapshotInterval: 30 * time.Second,
|
|
RaftTrailingLogs: 83749,
|
|
ReconnectTimeoutLAN: 23739 * time.Second,
|
|
ReconnectTimeoutWAN: 26694 * time.Second,
|
|
RejoinAfterLeave: true,
|
|
RetryJoinIntervalLAN: 8067 * time.Second,
|
|
RetryJoinIntervalWAN: 28866 * time.Second,
|
|
RetryJoinLAN: []string{"pbsSFY7U", "l0qLtWij"},
|
|
RetryJoinMaxAttemptsLAN: 913,
|
|
RetryJoinMaxAttemptsWAN: 23160,
|
|
RetryJoinWAN: []string{"PFsR02Ye", "rJdQIhER"},
|
|
SegmentName: "BC2NhTDi",
|
|
Segments: []structs.NetworkSegment{
|
|
{
|
|
Name: "PExYMe2E",
|
|
Bind: tcpAddr("36.73.36.19:38295"),
|
|
Advertise: tcpAddr("63.39.19.18:38295"),
|
|
RPCListener: true,
|
|
},
|
|
{
|
|
Name: "UzCvJgup",
|
|
Bind: tcpAddr("37.58.38.19:39292"),
|
|
Advertise: tcpAddr("83.58.26.27:39292"),
|
|
RPCListener: true,
|
|
},
|
|
},
|
|
SerfPortLAN: 8301,
|
|
SerfPortWAN: 8302,
|
|
ServerMode: true,
|
|
ServerName: "Oerr9n1G",
|
|
ServerPort: 3757,
|
|
Services: []*structs.ServiceDefinition{
|
|
{
|
|
ID: "wI1dzxS4",
|
|
Name: "7IszXMQ1",
|
|
Tags: []string{"0Zwg8l6v", "zebELdN5"},
|
|
Address: "9RhqPSPB",
|
|
Token: "myjKJkWH",
|
|
Port: 72219,
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
EnableTagOverride: true,
|
|
Checks: []*structs.CheckType{
|
|
{
|
|
CheckID: "qmfeO5if",
|
|
Name: "atDGP7n5",
|
|
Status: "pDQKEhWL",
|
|
Notes: "Yt8EDLev",
|
|
ScriptArgs: []string{"81EDZLPa", "bPY5X8xd"},
|
|
HTTP: "qzHYvmJO",
|
|
Header: map[string][]string{
|
|
"UkpmZ3a3": {"2dfzXuxZ"},
|
|
"cVFpko4u": {"gGqdEB6k", "9LsRo22u"},
|
|
},
|
|
Method: "X5DrovFc",
|
|
Body: "WeikigLh",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "ICbxkpSF",
|
|
Interval: 24392 * time.Second,
|
|
DockerContainerID: "ZKXr68Yb",
|
|
Shell: "CEfzx0Fo",
|
|
TLSSkipVerify: true,
|
|
Timeout: 38333 * time.Second,
|
|
TTL: 57201 * time.Second,
|
|
DeregisterCriticalServiceAfter: 44214 * time.Second,
|
|
},
|
|
},
|
|
// Note that although this SidecarService is only syntax sugar for
|
|
// registering another service, that has to happen in the agent code so
|
|
// it can make intelligent decisions about automatic port assignments
|
|
// etc. So we expect config just to pass it through verbatim.
|
|
Connect: &structs.ServiceConnect{
|
|
SidecarService: &structs.ServiceDefinition{
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "MRHVMZuD",
|
|
Name: "6L6BVfgH",
|
|
Tags: []string{"7Ale4y6o", "PMBW08hy"},
|
|
Address: "R6H6g8h0",
|
|
Token: "ZgY8gjMI",
|
|
Port: 38292,
|
|
Weights: &structs.Weights{
|
|
Passing: 1979,
|
|
Warning: 6,
|
|
},
|
|
EnableTagOverride: true,
|
|
Checks: structs.CheckTypes{
|
|
&structs.CheckType{
|
|
CheckID: "GTti9hCo",
|
|
Name: "9OOS93ne",
|
|
Notes: "CQy86DH0",
|
|
Status: "P0SWDvrk",
|
|
ScriptArgs: []string{"EXvkYIuG", "BATOyt6h"},
|
|
HTTP: "u97ByEiW",
|
|
Header: map[string][]string{
|
|
"MUlReo8L": {"AUZG7wHG", "gsN0Dc2N"},
|
|
"1UJXjVrT": {"OJgxzTfk", "xZZrFsq7"},
|
|
},
|
|
Method: "5wkAxCUE",
|
|
Body: "7CRjCJyz",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "MN3oA9D2",
|
|
Interval: 32718 * time.Second,
|
|
DockerContainerID: "cU15LMet",
|
|
Shell: "nEz9qz2l",
|
|
TLSSkipVerify: true,
|
|
Timeout: 34738 * time.Second,
|
|
TTL: 22773 * time.Second,
|
|
DeregisterCriticalServiceAfter: 84282 * time.Second,
|
|
},
|
|
&structs.CheckType{
|
|
CheckID: "UHsDeLxG",
|
|
Name: "PQSaPWlT",
|
|
Notes: "jKChDOdl",
|
|
Status: "5qFz6OZn",
|
|
ScriptArgs: []string{"NMtYWlT9", "vj74JXsm"},
|
|
HTTP: "1LBDJhw4",
|
|
Header: map[string][]string{
|
|
"cXPmnv1M": {"imDqfaBx", "NFxZ1bQe"},
|
|
"vr7wY7CS": {"EtCoNPPL", "9vAarJ5s"},
|
|
},
|
|
Method: "wzByP903",
|
|
Body: "4I8ucZgZ",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "2exjZIGE",
|
|
Interval: 5656 * time.Second,
|
|
DockerContainerID: "5tDBWpfA",
|
|
Shell: "rlTpLM8s",
|
|
TLSSkipVerify: true,
|
|
Timeout: 4868 * time.Second,
|
|
TTL: 11222 * time.Second,
|
|
DeregisterCriticalServiceAfter: 68482 * time.Second,
|
|
},
|
|
},
|
|
Connect: &structs.ServiceConnect{},
|
|
},
|
|
{
|
|
ID: "Kh81CPF6",
|
|
Name: "Kh81CPF6-proxy",
|
|
Port: 31471,
|
|
Kind: "connect-proxy",
|
|
Proxy: &structs.ConnectProxyConfig{
|
|
DestinationServiceName: "6L6BVfgH",
|
|
DestinationServiceID: "6L6BVfgH-id",
|
|
LocalServiceAddress: "127.0.0.2",
|
|
LocalServicePort: 23759,
|
|
Config: map[string]interface{}{
|
|
"cedGGtZf": "pWrUNiWw",
|
|
},
|
|
Upstreams: structs.Upstreams{
|
|
{
|
|
DestinationType: "service", // Default should be explicitly filled
|
|
DestinationName: "KPtAj2cb",
|
|
LocalBindPort: 4051,
|
|
Config: map[string]interface{}{
|
|
"kzRnZOyd": "nUNKoL8H",
|
|
},
|
|
},
|
|
{
|
|
DestinationType: "prepared_query",
|
|
DestinationNamespace: "9nakw0td",
|
|
DestinationName: "KSd8HsRl",
|
|
LocalBindPort: 11884,
|
|
LocalBindAddress: "127.24.88.0",
|
|
},
|
|
},
|
|
Expose: structs.ExposeConfig{
|
|
Checks: true,
|
|
Paths: []structs.ExposePath{
|
|
{
|
|
Path: "/health",
|
|
LocalPathPort: 8080,
|
|
ListenerPort: 21500,
|
|
Protocol: "http",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
{
|
|
ID: "kvVqbwSE",
|
|
Kind: "mesh-gateway",
|
|
Name: "gw-primary-dc",
|
|
Port: 27147,
|
|
Proxy: &structs.ConnectProxyConfig{
|
|
Config: map[string]interface{}{
|
|
"1CuJHVfw": "Kzqsa7yc",
|
|
},
|
|
Upstreams: structs.Upstreams{},
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 1,
|
|
Warning: 1,
|
|
},
|
|
},
|
|
{
|
|
ID: "dLOXpSCI",
|
|
Name: "o1ynPkp0",
|
|
TaggedAddresses: map[string]structs.ServiceAddress{
|
|
"lan": {
|
|
Address: "2d79888a",
|
|
Port: 2143,
|
|
},
|
|
"wan": {
|
|
Address: "d4db85e2",
|
|
Port: 6109,
|
|
},
|
|
},
|
|
Tags: []string{"nkwshvM5", "NTDWn3ek"},
|
|
Address: "cOlSOhbp",
|
|
Token: "msy7iWER",
|
|
Meta: map[string]string{"mymeta": "data"},
|
|
Port: 24237,
|
|
Weights: &structs.Weights{
|
|
Passing: 100,
|
|
Warning: 1,
|
|
},
|
|
EnableTagOverride: true,
|
|
Connect: &structs.ServiceConnect{
|
|
Native: true,
|
|
},
|
|
Checks: structs.CheckTypes{
|
|
&structs.CheckType{
|
|
CheckID: "Zv99e9Ka",
|
|
Name: "sgV4F7Pk",
|
|
Notes: "yP5nKbW0",
|
|
Status: "7oLMEyfu",
|
|
ScriptArgs: []string{"5wEZtZpv", "0Ihyk8cS"},
|
|
HTTP: "KyDjGY9H",
|
|
Header: map[string][]string{
|
|
"gv5qefTz": {"5Olo2pMG", "PvvKWQU5"},
|
|
"SHOVq1Vv": {"jntFhyym", "GYJh32pp"},
|
|
},
|
|
Method: "T66MFBfR",
|
|
Body: "OwGjTFQi",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "bNnNfx2A",
|
|
Interval: 22224 * time.Second,
|
|
DockerContainerID: "ipgdFtjd",
|
|
Shell: "omVZq7Sz",
|
|
TLSSkipVerify: true,
|
|
Timeout: 18913 * time.Second,
|
|
TTL: 44743 * time.Second,
|
|
DeregisterCriticalServiceAfter: 8482 * time.Second,
|
|
},
|
|
&structs.CheckType{
|
|
CheckID: "G79O6Mpr",
|
|
Name: "IEqrzrsd",
|
|
Notes: "SVqApqeM",
|
|
Status: "XXkVoZXt",
|
|
ScriptArgs: []string{"wD05Bvao", "rLYB7kQC"},
|
|
HTTP: "kyICZsn8",
|
|
Header: map[string][]string{
|
|
"4ebP5vL4": {"G20SrL5Q", "DwPKlMbo"},
|
|
"p2UI34Qz": {"UsG1D0Qh", "NHhRiB6s"},
|
|
},
|
|
Method: "ciYHWors",
|
|
Body: "lUVLGYU7",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "FfvCwlqH",
|
|
Interval: 12356 * time.Second,
|
|
DockerContainerID: "HBndBU6R",
|
|
Shell: "hVI33JjA",
|
|
TLSSkipVerify: true,
|
|
Timeout: 38282 * time.Second,
|
|
TTL: 1181 * time.Second,
|
|
DeregisterCriticalServiceAfter: 4992 * time.Second,
|
|
},
|
|
&structs.CheckType{
|
|
CheckID: "RMi85Dv8",
|
|
Name: "iehanzuq",
|
|
Status: "rCvn53TH",
|
|
Notes: "fti5lfF3",
|
|
ScriptArgs: []string{"16WRUmwS", "QWk7j7ae"},
|
|
HTTP: "dl3Fgme3",
|
|
Header: map[string][]string{
|
|
"rjm4DEd3": {"2m3m2Fls"},
|
|
"l4HwQ112": {"fk56MNlo", "dhLK56aZ"},
|
|
},
|
|
Method: "9afLm3Mj",
|
|
Body: "wVVL2V6f",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
TCP: "fjiLFqVd",
|
|
Interval: 23926 * time.Second,
|
|
DockerContainerID: "dO5TtRHk",
|
|
Shell: "e6q2ttES",
|
|
TLSSkipVerify: true,
|
|
Timeout: 38483 * time.Second,
|
|
TTL: 10943 * time.Second,
|
|
DeregisterCriticalServiceAfter: 68787 * time.Second,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
SerfAdvertiseAddrLAN: tcpAddr("17.99.29.16:8301"),
|
|
SerfAdvertiseAddrWAN: tcpAddr("78.63.37.19:8302"),
|
|
SerfBindAddrLAN: tcpAddr("99.43.63.15:8301"),
|
|
SerfBindAddrWAN: tcpAddr("67.88.33.19:8302"),
|
|
SerfAllowedCIDRsLAN: []net.IPNet{},
|
|
SerfAllowedCIDRsWAN: []net.IPNet{},
|
|
SessionTTLMin: 26627 * time.Second,
|
|
SkipLeaveOnInt: true,
|
|
StartJoinAddrsLAN: []string{"LR3hGDoG", "MwVpZ4Up"},
|
|
StartJoinAddrsWAN: []string{"EbFSc3nA", "kwXTh623"},
|
|
Telemetry: lib.TelemetryConfig{
|
|
CirconusAPIApp: "p4QOTe9j",
|
|
CirconusAPIToken: "E3j35V23",
|
|
CirconusAPIURL: "mEMjHpGg",
|
|
CirconusBrokerID: "BHlxUhed",
|
|
CirconusBrokerSelectTag: "13xy1gHm",
|
|
CirconusCheckDisplayName: "DRSlQR6n",
|
|
CirconusCheckForceMetricActivation: "Ua5FGVYf",
|
|
CirconusCheckID: "kGorutad",
|
|
CirconusCheckInstanceID: "rwoOL6R4",
|
|
CirconusCheckSearchTag: "ovT4hT4f",
|
|
CirconusCheckTags: "prvO4uBl",
|
|
CirconusSubmissionInterval: "DolzaflP",
|
|
CirconusSubmissionURL: "gTcbS93G",
|
|
DisableHostname: true,
|
|
DogstatsdAddr: "0wSndumK",
|
|
DogstatsdTags: []string{"3N81zSUB", "Xtj8AnXZ"},
|
|
FilterDefault: true,
|
|
AllowedPrefixes: []string{"oJotS8XJ"},
|
|
BlockedPrefixes: []string{"consul.api.http", "cazlEhGn"},
|
|
MetricsPrefix: "ftO6DySn",
|
|
PrometheusRetentionTime: 15 * time.Second,
|
|
StatsdAddr: "drce87cy",
|
|
StatsiteAddr: "HpFwKB8R",
|
|
},
|
|
TLSCipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
|
|
TLSMinVersion: "pAOWafkR",
|
|
TLSPreferServerCipherSuites: true,
|
|
TaggedAddresses: map[string]string{
|
|
"7MYgHrYH": "dALJAhLD",
|
|
"h6DdBy6K": "ebrr9zZ8",
|
|
"lan": "17.99.29.16",
|
|
"lan_ipv4": "17.99.29.16",
|
|
"wan": "78.63.37.19",
|
|
"wan_ipv4": "78.63.37.19",
|
|
},
|
|
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",
|
|
VerifyIncoming: true,
|
|
VerifyIncomingHTTPS: true,
|
|
VerifyIncomingRPC: true,
|
|
VerifyOutgoing: true,
|
|
VerifyServerHostname: true,
|
|
Watches: []map[string]interface{}{
|
|
{
|
|
"type": "key",
|
|
"datacenter": "GyE6jpeW",
|
|
"key": "j9lF1Tve",
|
|
"handler": "90N7S4LN",
|
|
},
|
|
{
|
|
"type": "keyprefix",
|
|
"datacenter": "fYrl3F5d",
|
|
"key": "sl3Dffu7",
|
|
"args": []interface{}{"dltjDJ2a", "flEa7C2d"},
|
|
},
|
|
},
|
|
}
|
|
|
|
entFullRuntimeConfig(&want)
|
|
|
|
warns := []string{
|
|
`The 'acl_datacenter' field is deprecated. Use the 'primary_datacenter' field instead.`,
|
|
`bootstrap_expect > 0: expecting 53 servers`,
|
|
}
|
|
|
|
warns = append(warns, enterpriseConfigKeyWarnings...)
|
|
|
|
// ensure that all fields are set to unique non-zero values
|
|
// todo(fs): This currently fails since ServiceDefinition.Check is not used
|
|
// todo(fs): not sure on how to work around this. Possible options are:
|
|
// todo(fs): * move first check into the Check field
|
|
// todo(fs): * ignore the Check field
|
|
// todo(fs): both feel like a hack
|
|
if err := nonZero("RuntimeConfig", nil, want); err != nil {
|
|
t.Log(err)
|
|
}
|
|
|
|
for format, data := range src {
|
|
t.Run(format, func(t *testing.T) {
|
|
// parse the flags since this is the only way we can set the
|
|
// DevMode flag
|
|
var flags BuilderOpts
|
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
|
AddFlags(fs, &flags)
|
|
if err := fs.Parse(flagSrc); err != nil {
|
|
t.Fatalf("ParseFlags: %s", err)
|
|
}
|
|
require.Len(t, fs.Args(), 0)
|
|
|
|
b, err := NewBuilder(flags)
|
|
if err != nil {
|
|
t.Fatalf("NewBuilder: %s", err)
|
|
}
|
|
b.Sources = append(b.Sources, FileSource{Name: "full." + format, Data: data, Format: format})
|
|
b.Tail = append(b.Tail, tail[format]...)
|
|
b.Tail = append(b.Tail, VersionSource("JNtPSav3", "R909Hblt", "ZT1JOQLn"))
|
|
|
|
// construct the runtime config
|
|
rt, err := b.Build()
|
|
if err != nil {
|
|
t.Fatalf("Build: %s", err)
|
|
}
|
|
|
|
require.Equal(t, want, rt)
|
|
|
|
// at this point we have confirmed that the parsing worked
|
|
// for all fields but the validation will fail since certain
|
|
// combinations are not allowed. Since it is not possible to have
|
|
// all fields with non-zero values and to have a valid configuration
|
|
// we are patching a handful of safe fields to make validation pass.
|
|
rt.Bootstrap = false
|
|
rt.DevMode = false
|
|
rt.UIConfig.Enabled = false
|
|
rt.SegmentName = ""
|
|
rt.Segments = nil
|
|
|
|
// validate the runtime config
|
|
if err := b.Validate(rt); err != nil {
|
|
t.Fatalf("Validate: %s", err)
|
|
}
|
|
|
|
// check the warnings
|
|
require.ElementsMatch(t, warns, b.Warnings, "Warnings: %#v", b.Warnings)
|
|
})
|
|
}
|
|
}
|
|
|
|
// nonZero verifies recursively that all fields are set to unique,
|
|
// non-zero and non-nil values.
|
|
//
|
|
// struct: check all fields recursively
|
|
// slice: check len > 0 and all values recursively
|
|
// ptr: check not nil
|
|
// bool: check not zero (cannot check uniqueness)
|
|
// string, int, uint: check not zero and unique
|
|
// other: error
|
|
func nonZero(name string, uniq map[interface{}]string, v interface{}) error {
|
|
if v == nil {
|
|
return fmt.Errorf("%q is nil", name)
|
|
}
|
|
|
|
if uniq == nil {
|
|
uniq = map[interface{}]string{}
|
|
}
|
|
|
|
isUnique := func(v interface{}) error {
|
|
if other := uniq[v]; other != "" {
|
|
return fmt.Errorf("%q and %q both use value %q", name, other, v)
|
|
}
|
|
uniq[v] = name
|
|
return nil
|
|
}
|
|
|
|
val, typ := reflect.ValueOf(v), reflect.TypeOf(v)
|
|
// fmt.Printf("%s: %T\n", name, v)
|
|
switch typ.Kind() {
|
|
case reflect.Struct:
|
|
for i := 0; i < typ.NumField(); i++ {
|
|
f := typ.Field(i)
|
|
fieldname := fmt.Sprintf("%s.%s", name, f.Name)
|
|
err := nonZero(fieldname, uniq, val.Field(i).Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
case reflect.Slice:
|
|
if val.Len() == 0 {
|
|
return fmt.Errorf("%q is empty slice", name)
|
|
}
|
|
for i := 0; i < val.Len(); i++ {
|
|
elemname := fmt.Sprintf("%s[%d]", name, i)
|
|
err := nonZero(elemname, uniq, val.Index(i).Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
case reflect.Map:
|
|
if val.Len() == 0 {
|
|
return fmt.Errorf("%q is empty map", name)
|
|
}
|
|
for _, key := range val.MapKeys() {
|
|
keyname := fmt.Sprintf("%s[%s]", name, key.String())
|
|
if err := nonZero(keyname, uniq, key.Interface()); err != nil {
|
|
if strings.Contains(err.Error(), "is zero value") {
|
|
return fmt.Errorf("%q has zero value map key", name)
|
|
}
|
|
return err
|
|
}
|
|
if err := nonZero(keyname, uniq, val.MapIndex(key).Interface()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
case reflect.Bool:
|
|
if val.Bool() != true {
|
|
return fmt.Errorf("%q is zero value", name)
|
|
}
|
|
// do not test bool for uniqueness since there are only two values
|
|
|
|
case reflect.String:
|
|
if val.Len() == 0 {
|
|
return fmt.Errorf("%q is zero value", name)
|
|
}
|
|
return isUnique(v)
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
if val.Int() == 0 {
|
|
return fmt.Errorf("%q is zero value", name)
|
|
}
|
|
return isUnique(v)
|
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
if val.Uint() == 0 {
|
|
return fmt.Errorf("%q is zero value", name)
|
|
}
|
|
return isUnique(v)
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
if val.Float() == 0 {
|
|
return fmt.Errorf("%q is zero value", name)
|
|
}
|
|
return isUnique(v)
|
|
|
|
case reflect.Ptr:
|
|
if val.IsNil() {
|
|
return fmt.Errorf("%q is nil", name)
|
|
}
|
|
return nonZero("*"+name, uniq, val.Elem().Interface())
|
|
|
|
default:
|
|
return fmt.Errorf("%T is not supported", v)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestNonZero(t *testing.T) {
|
|
var empty string
|
|
|
|
tests := []struct {
|
|
desc string
|
|
v interface{}
|
|
err error
|
|
}{
|
|
{"nil", nil, errors.New(`"x" is nil`)},
|
|
{"zero bool", false, errors.New(`"x" is zero value`)},
|
|
{"zero string", "", errors.New(`"x" is zero value`)},
|
|
{"zero int", int(0), errors.New(`"x" is zero value`)},
|
|
{"zero int8", int8(0), errors.New(`"x" is zero value`)},
|
|
{"zero int16", int16(0), errors.New(`"x" is zero value`)},
|
|
{"zero int32", int32(0), errors.New(`"x" is zero value`)},
|
|
{"zero int64", int64(0), errors.New(`"x" is zero value`)},
|
|
{"zero uint", uint(0), errors.New(`"x" is zero value`)},
|
|
{"zero uint8", uint8(0), errors.New(`"x" is zero value`)},
|
|
{"zero uint16", uint16(0), errors.New(`"x" is zero value`)},
|
|
{"zero uint32", uint32(0), errors.New(`"x" is zero value`)},
|
|
{"zero uint64", uint64(0), errors.New(`"x" is zero value`)},
|
|
{"zero float32", float32(0), errors.New(`"x" is zero value`)},
|
|
{"zero float64", float64(0), errors.New(`"x" is zero value`)},
|
|
{"ptr to zero value", &empty, errors.New(`"*x" is zero value`)},
|
|
{"empty slice", []string{}, errors.New(`"x" is empty slice`)},
|
|
{"slice with zero value", []string{""}, errors.New(`"x[0]" is zero value`)},
|
|
{"empty map", map[string]string{}, errors.New(`"x" is empty map`)},
|
|
{"map with zero value key", map[string]string{"": "y"}, errors.New(`"x" has zero value map key`)},
|
|
{"map with zero value elem", map[string]string{"y": ""}, errors.New(`"x[y]" is zero value`)},
|
|
{"struct with nil field", struct{ Y *int }{}, errors.New(`"x.Y" is nil`)},
|
|
{"struct with zero value field", struct{ Y string }{}, errors.New(`"x.Y" is zero value`)},
|
|
{"struct with empty array", struct{ Y []string }{}, errors.New(`"x.Y" is empty slice`)},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
if got, want := nonZero("x", nil, tt.v), tt.err; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("got error %v want %v", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigDecodeBytes(t *testing.T) {
|
|
t.Parallel()
|
|
// Test with some input
|
|
src := []byte("abc")
|
|
key := base64.StdEncoding.EncodeToString(src)
|
|
|
|
result, err := decodeBytes(key)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if !bytes.Equal(src, result) {
|
|
t.Fatalf("bad: %#v", result)
|
|
}
|
|
|
|
// Test with no input
|
|
result, err = decodeBytes("")
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if len(result) > 0 {
|
|
t.Fatalf("bad: %#v", result)
|
|
}
|
|
}
|
|
|
|
func parseCIDR(t *testing.T, cidr string) *net.IPNet {
|
|
_, x, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
t.Fatalf("CIDRParse: %v", err)
|
|
}
|
|
return x
|
|
}
|
|
|
|
func TestSanitize(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
BindAddr: &net.IPAddr{IP: net.ParseIP("127.0.0.1")},
|
|
CheckOutputMaxSize: checks.DefaultBufSize,
|
|
SerfAdvertiseAddrLAN: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
DNSAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
&net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
},
|
|
DNSSOA: RuntimeSOAConfig{Refresh: 3600, Retry: 600, Expire: 86400, Minttl: 0},
|
|
AllowWriteHTTPFrom: []*net.IPNet{
|
|
parseCIDR(t, "127.0.0.0/8"),
|
|
parseCIDR(t, "::1/128"),
|
|
},
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
&net.UnixAddr{Name: "/var/run/foo"},
|
|
},
|
|
Cache: cache.Options{
|
|
EntryFetchMaxBurst: 42,
|
|
EntryFetchRate: 0.334,
|
|
},
|
|
ConsulCoordinateUpdatePeriod: 15 * time.Second,
|
|
RetryJoinLAN: []string{
|
|
"foo=bar key=baz secret=boom bang=bar",
|
|
},
|
|
RetryJoinWAN: []string{
|
|
"wan_foo=bar wan_key=baz wan_secret=boom wan_bang=bar",
|
|
},
|
|
PrimaryGateways: []string{
|
|
"pmgw_foo=bar pmgw_key=baz pmgw_secret=boom pmgw_bang=bar",
|
|
},
|
|
Services: []*structs.ServiceDefinition{
|
|
{
|
|
Name: "foo",
|
|
Token: "bar",
|
|
Check: structs.CheckType{
|
|
Name: "blurb",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
},
|
|
Weights: &structs.Weights{
|
|
Passing: 67,
|
|
Warning: 3,
|
|
},
|
|
},
|
|
},
|
|
Checks: []*structs.CheckDefinition{
|
|
{
|
|
Name: "zoo",
|
|
Token: "zope",
|
|
OutputMaxSize: checks.DefaultBufSize,
|
|
},
|
|
},
|
|
KVMaxValueSize: 1234567800000000,
|
|
SerfAllowedCIDRsLAN: []net.IPNet{
|
|
*parseCIDR(t, "192.168.1.0/24"),
|
|
*parseCIDR(t, "127.0.0.0/8"),
|
|
},
|
|
TxnMaxReqLen: 5678000000000000,
|
|
}
|
|
|
|
rtJSON := `{
|
|
"ACLTokens": {
|
|
` + entTokenConfigSanitize + `
|
|
"ACLAgentMasterToken": "hidden",
|
|
"ACLAgentToken": "hidden",
|
|
"ACLDefaultToken": "hidden",
|
|
"ACLReplicationToken": "hidden",
|
|
"DataDir": "",
|
|
"EnablePersistence": false
|
|
},
|
|
"ACLDatacenter": "",
|
|
"ACLDefaultPolicy": "",
|
|
"ACLDisabledTTL": "0s",
|
|
"ACLDownPolicy": "",
|
|
"ACLEnableKeyListPolicy": false,
|
|
"ACLMasterToken": "hidden",
|
|
"ACLPolicyTTL": "0s",
|
|
"ACLRoleTTL": "0s",
|
|
"ACLTokenReplication": false,
|
|
"ACLTokenTTL": "0s",
|
|
"ACLsEnabled": false,
|
|
"AEInterval": "0s",
|
|
"AdvertiseAddrLAN": "",
|
|
"AdvertiseAddrWAN": "",
|
|
"AutopilotCleanupDeadServers": false,
|
|
"AutopilotDisableUpgradeMigration": false,
|
|
"AutopilotLastContactThreshold": "0s",
|
|
"AutopilotMaxTrailingLogs": 0,
|
|
"AutopilotMinQuorum": 0,
|
|
"AutopilotRedundancyZoneTag": "",
|
|
"AutopilotServerStabilizationTime": "0s",
|
|
"AutopilotUpgradeVersionTag": "",
|
|
"BindAddr": "127.0.0.1",
|
|
"Bootstrap": false,
|
|
"BootstrapExpect": 0,
|
|
"Cache": {
|
|
"EntryFetchMaxBurst": 42,
|
|
"EntryFetchRate": 0.334
|
|
},
|
|
"CAFile": "",
|
|
"CAPath": "",
|
|
"CertFile": "",
|
|
"CheckDeregisterIntervalMin": "0s",
|
|
"CheckOutputMaxSize": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"CheckReapInterval": "0s",
|
|
"CheckUpdateInterval": "0s",
|
|
"Checks": [{
|
|
"AliasNode": "",
|
|
"AliasService": "",
|
|
"DeregisterCriticalServiceAfter": "0s",
|
|
"DockerContainerID": "",
|
|
"EnterpriseMeta": ` + entMetaJSON + `,
|
|
"SuccessBeforePassing": 0,
|
|
"FailuresBeforeCritical": 0,
|
|
"GRPC": "",
|
|
"GRPCUseTLS": false,
|
|
"HTTP": "",
|
|
"Header": {},
|
|
"ID": "",
|
|
"Interval": "0s",
|
|
"Method": "",
|
|
"Body": "",
|
|
"Name": "zoo",
|
|
"Notes": "",
|
|
"OutputMaxSize": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"ScriptArgs": [],
|
|
"ServiceID": "",
|
|
"Shell": "",
|
|
"Status": "",
|
|
"TCP": "",
|
|
"TLSSkipVerify": false,
|
|
"TTL": "0s",
|
|
"Timeout": "0s",
|
|
"Token": "hidden"
|
|
}],
|
|
"ClientAddrs": [],
|
|
"ConfigEntryBootstrap": [],
|
|
"AutoEncryptTLS": false,
|
|
"AutoEncryptDNSSAN": [],
|
|
"AutoEncryptIPSAN": [],
|
|
"AutoEncryptAllowTLS": false,
|
|
"ConnectCAConfig": {},
|
|
"ConnectCAProvider": "",
|
|
"ConnectEnabled": false,
|
|
"ConnectMeshGatewayWANFederationEnabled": false,
|
|
"ConnectSidecarMaxPort": 0,
|
|
"ConnectSidecarMinPort": 0,
|
|
"ConnectTestCALeafRootChangeSpread": "0s",
|
|
"ConsulCoordinateUpdateBatchSize": 0,
|
|
"ConsulCoordinateUpdateMaxBatches": 0,
|
|
"ConsulCoordinateUpdatePeriod": "15s",
|
|
"ConsulRaftElectionTimeout": "0s",
|
|
"CheckOutputMaxSize": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"ConsulRaftHeartbeatTimeout": "0s",
|
|
"ConsulRaftLeaderLeaseTimeout": "0s",
|
|
"GossipLANGossipInterval": "0s",
|
|
"GossipLANGossipNodes": 0,
|
|
"GossipLANProbeInterval": "0s",
|
|
"GossipLANProbeTimeout": "0s",
|
|
"GossipLANRetransmitMult": 0,
|
|
"GossipLANSuspicionMult": 0,
|
|
"GossipWANGossipInterval": "0s",
|
|
"GossipWANGossipNodes": 0,
|
|
"GossipWANProbeInterval": "0s",
|
|
"GossipWANProbeTimeout": "0s",
|
|
"GossipWANRetransmitMult": 0,
|
|
"GossipWANSuspicionMult": 0,
|
|
"ConsulServerHealthInterval": "0s",
|
|
"DNSARecordLimit": 0,
|
|
"DNSAddrs": [
|
|
"tcp://1.2.3.4:5678",
|
|
"udp://1.2.3.4:5678"
|
|
],
|
|
"DNSAllowStale": false,
|
|
"DNSDisableCompression": false,
|
|
"DNSDomain": "",
|
|
"DNSAltDomain": "",
|
|
"DNSEnableTruncate": false,
|
|
"DNSMaxStale": "0s",
|
|
"DNSNodeMetaTXT": false,
|
|
"DNSNodeTTL": "0s",
|
|
"DNSOnlyPassing": false,
|
|
"DNSPort": 0,
|
|
"DNSRecursorTimeout": "0s",
|
|
"DNSRecursors": [],
|
|
"DNSServiceTTL": {},
|
|
"DNSSOA": {
|
|
"Refresh": 3600,
|
|
"Retry": 600,
|
|
"Expire": 86400,
|
|
"Minttl": 0
|
|
},
|
|
"DNSUDPAnswerLimit": 0,
|
|
"DNSUseCache": false,
|
|
"DNSCacheMaxAge": "0s",
|
|
"DataDir": "",
|
|
"Datacenter": "",
|
|
"DefaultQueryTime": "0s",
|
|
"DevMode": false,
|
|
"DisableAnonymousSignature": false,
|
|
"DisableCoordinates": false,
|
|
"DisableHTTPUnprintableCharFilter": false,
|
|
"DisableHostNodeID": false,
|
|
"DisableKeyringFile": false,
|
|
"DisableRemoteExec": false,
|
|
"DisableUpdateCheck": false,
|
|
"DiscardCheckOutput": false,
|
|
"DiscoveryMaxStale": "0s",
|
|
"EnableAgentTLSForChecks": false,
|
|
"EnableDebug": false,
|
|
"EnableCentralServiceConfig": false,
|
|
"EnableLocalScriptChecks": false,
|
|
"EnableRemoteScriptChecks": false,
|
|
"EncryptKey": "hidden",
|
|
"EncryptVerifyIncoming": false,
|
|
"EncryptVerifyOutgoing": false,
|
|
"EnterpriseRuntimeConfig": ` + entRuntimeConfigSanitize + `,
|
|
"ExposeMaxPort": 0,
|
|
"ExposeMinPort": 0,
|
|
"GRPCAddrs": [],
|
|
"GRPCPort": 0,
|
|
"HTTPAddrs": [
|
|
"tcp://1.2.3.4:5678",
|
|
"unix:///var/run/foo"
|
|
],
|
|
"HTTPBlockEndpoints": [],
|
|
"HTTPMaxConnsPerClient": 0,
|
|
"HTTPPort": 0,
|
|
"HTTPResponseHeaders": {},
|
|
"HTTPUseCache": false,
|
|
"HTTPSAddrs": [],
|
|
"HTTPSHandshakeTimeout": "0s",
|
|
"HTTPSPort": 0,
|
|
"KeyFile": "hidden",
|
|
"KVMaxValueSize": 1234567800000000,
|
|
"LeaveDrainTime": "0s",
|
|
"LeaveOnTerm": false,
|
|
"Logging": {
|
|
"EnableSyslog": false,
|
|
"LogLevel": "",
|
|
"LogJSON": false,
|
|
"LogFilePath": "",
|
|
"LogRotateBytes": 0,
|
|
"LogRotateDuration": "0s",
|
|
"LogRotateMaxFiles": 0,
|
|
"Name": "",
|
|
"SyslogFacility": ""
|
|
},
|
|
"MaxQueryTime": "0s",
|
|
"NodeID": "",
|
|
"NodeMeta": {},
|
|
"NodeName": "",
|
|
"NonVotingServer": false,
|
|
"PidFile": "",
|
|
"PrimaryDatacenter": "",
|
|
"PrimaryGateways": [
|
|
"pmgw_foo=bar pmgw_key=baz pmgw_secret=boom pmgw_bang=bar"
|
|
],
|
|
"PrimaryGatewaysInterval": "0s",
|
|
"RPCAdvertiseAddr": "",
|
|
"RPCBindAddr": "",
|
|
"RPCHandshakeTimeout": "0s",
|
|
"RPCHoldTimeout": "0s",
|
|
"RPCMaxBurst": 0,
|
|
"RPCMaxConnsPerClient": 0,
|
|
"RPCProtocol": 0,
|
|
"RPCRateLimit": 0,
|
|
"RaftProtocol": 0,
|
|
"RaftSnapshotInterval": "0s",
|
|
"RaftSnapshotThreshold": 0,
|
|
"RaftTrailingLogs": 0,
|
|
"ReconnectTimeoutLAN": "0s",
|
|
"ReconnectTimeoutWAN": "0s",
|
|
"RejoinAfterLeave": false,
|
|
"RetryJoinIntervalLAN": "0s",
|
|
"RetryJoinIntervalWAN": "0s",
|
|
"RetryJoinLAN": [
|
|
"foo=bar key=hidden secret=hidden bang=bar"
|
|
],
|
|
"RetryJoinMaxAttemptsLAN": 0,
|
|
"RetryJoinMaxAttemptsWAN": 0,
|
|
"RetryJoinWAN": [
|
|
"wan_foo=bar wan_key=hidden wan_secret=hidden wan_bang=bar"
|
|
],
|
|
"Revision": "",
|
|
"SegmentLimit": 0,
|
|
"SegmentName": "",
|
|
"SegmentNameLimit": 0,
|
|
"Segments": [],
|
|
"SerfAdvertiseAddrLAN": "tcp://1.2.3.4:5678",
|
|
"SerfAdvertiseAddrWAN": "",
|
|
"SerfAllowedCIDRsLAN": ["192.168.1.0/24", "127.0.0.0/8"],
|
|
"SerfAllowedCIDRsWAN": [],
|
|
"SerfBindAddrLAN": "",
|
|
"SerfBindAddrWAN": "",
|
|
"SerfPortLAN": 0,
|
|
"SerfPortWAN": 0,
|
|
"ServerMode": false,
|
|
"ServerName": "",
|
|
"ServerPort": 0,
|
|
"Services": [{
|
|
"Address": "",
|
|
"Check": {
|
|
"AliasNode": "",
|
|
"AliasService": "",
|
|
"CheckID": "",
|
|
"DeregisterCriticalServiceAfter": "0s",
|
|
"DockerContainerID": "",
|
|
"SuccessBeforePassing": 0,
|
|
"FailuresBeforeCritical": 0,
|
|
"GRPC": "",
|
|
"GRPCUseTLS": false,
|
|
"HTTP": "",
|
|
"Header": {},
|
|
"Interval": "0s",
|
|
"Method": "",
|
|
"Body": "",
|
|
"Name": "blurb",
|
|
"Notes": "",
|
|
"OutputMaxSize": ` + strconv.Itoa(checks.DefaultBufSize) + `,
|
|
"ProxyGRPC": "",
|
|
"ProxyHTTP": "",
|
|
"ScriptArgs": [],
|
|
"Shell": "",
|
|
"Status": "",
|
|
"TCP": "",
|
|
"TLSSkipVerify": false,
|
|
"TTL": "0s",
|
|
"Timeout": "0s"
|
|
},
|
|
"Checks": [],
|
|
"Connect": null,
|
|
"EnableTagOverride": false,
|
|
"EnterpriseMeta": ` + entMetaJSON + `,
|
|
"ID": "",
|
|
"Kind": "",
|
|
"Meta": {},
|
|
"Name": "foo",
|
|
"Port": 0,
|
|
"Proxy": null,
|
|
"TaggedAddresses": {},
|
|
"Tags": [],
|
|
"Token": "hidden",
|
|
"Weights": {
|
|
"Passing": 67,
|
|
"Warning": 3
|
|
}
|
|
}],
|
|
"SessionTTLMin": "0s",
|
|
"SkipLeaveOnInt": false,
|
|
"StartJoinAddrsLAN": [],
|
|
"StartJoinAddrsWAN": [],
|
|
"SyncCoordinateIntervalMin": "0s",
|
|
"SyncCoordinateRateTarget": 0,
|
|
"TLSCipherSuites": [],
|
|
"TLSMinVersion": "",
|
|
"TLSPreferServerCipherSuites": false,
|
|
"TaggedAddresses": {},
|
|
"Telemetry": {
|
|
"AllowedPrefixes": [],
|
|
"BlockedPrefixes": [],
|
|
"CirconusAPIApp": "",
|
|
"CirconusAPIToken": "hidden",
|
|
"CirconusAPIURL": "",
|
|
"CirconusBrokerID": "",
|
|
"CirconusBrokerSelectTag": "",
|
|
"CirconusCheckDisplayName": "",
|
|
"CirconusCheckForceMetricActivation": "",
|
|
"CirconusCheckID": "",
|
|
"CirconusCheckInstanceID": "",
|
|
"CirconusCheckSearchTag": "",
|
|
"CirconusCheckTags": "",
|
|
"CirconusSubmissionInterval": "",
|
|
"CirconusSubmissionURL": "",
|
|
"Disable": false,
|
|
"DisableHostname": false,
|
|
"DogstatsdAddr": "",
|
|
"DogstatsdTags": [],
|
|
"FilterDefault": false,
|
|
"MetricsPrefix": "",
|
|
"PrometheusRetentionTime": "0s",
|
|
"StatsdAddr": "",
|
|
"StatsiteAddr": ""
|
|
},
|
|
"TranslateWANAddrs": false,
|
|
"TxnMaxReqLen": 5678000000000000,
|
|
"UIConfig": {
|
|
"ContentPath": "",
|
|
"Dir": "",
|
|
"Enabled": false,
|
|
"MetricsProvider": "",
|
|
"MetricsProviderFiles": [],
|
|
"MetricsProviderOptionsJSON": "",
|
|
"MetricsProxy": {
|
|
"AddHeaders": [],
|
|
"BaseURL": ""
|
|
},
|
|
"DashboardURLTemplates": {}
|
|
},
|
|
"UnixSocketGroup": "",
|
|
"UnixSocketMode": "",
|
|
"UnixSocketUser": "",
|
|
"VerifyIncoming": false,
|
|
"VerifyIncomingHTTPS": false,
|
|
"VerifyIncomingRPC": false,
|
|
"VerifyOutgoing": false,
|
|
"VerifyServerHostname": false,
|
|
"Version": "",
|
|
"VersionPrerelease": "",
|
|
"Watches": [],
|
|
"AllowWriteHTTPFrom": [
|
|
"127.0.0.0/8",
|
|
"::1/128"
|
|
],
|
|
"AutoConfig": {
|
|
"Authorizer": {
|
|
"Enabled": false,
|
|
"AllowReuse": false,
|
|
"AuthMethod": {
|
|
"ACLAuthMethodEnterpriseFields": {},
|
|
"Config": {},
|
|
"Description": "",
|
|
"DisplayName": "",
|
|
"EnterpriseMeta": {},
|
|
"MaxTokenTTL": "0s",
|
|
"Name": "",
|
|
"RaftIndex": {
|
|
"CreateIndex": 0,
|
|
"ModifyIndex": 0
|
|
},
|
|
"Type": "",
|
|
"TokenLocality": ""
|
|
},
|
|
"ClaimAssertions": []
|
|
},
|
|
"Enabled": false,
|
|
"DNSSANs": [],
|
|
"IntroToken": "hidden",
|
|
"IntroTokenFile": "",
|
|
"IPSANs": [],
|
|
"ServerAddresses": []
|
|
}
|
|
}`
|
|
b, err := json.MarshalIndent(rt.Sanitized(), "", " ")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
require.JSONEq(t, rtJSON, string(b))
|
|
}
|
|
|
|
func TestRuntime_apiAddresses(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5678},
|
|
&net.UnixAddr{Name: "/var/run/foo"},
|
|
},
|
|
HTTPSAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678},
|
|
}}
|
|
|
|
unixAddrs, httpAddrs, httpsAddrs := rt.apiAddresses(1)
|
|
|
|
require.Len(t, unixAddrs, 1)
|
|
require.Len(t, httpAddrs, 1)
|
|
require.Len(t, httpsAddrs, 1)
|
|
|
|
require.Equal(t, "/var/run/foo", unixAddrs[0])
|
|
require.Equal(t, "198.18.0.1:5678", httpAddrs[0])
|
|
require.Equal(t, "198.18.0.2:5678", httpsAddrs[0])
|
|
}
|
|
|
|
func TestRuntime_APIConfigHTTPS(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5678},
|
|
&net.UnixAddr{Name: "/var/run/foo"},
|
|
},
|
|
HTTPSAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678},
|
|
},
|
|
Datacenter: "dc-test",
|
|
CAFile: "/etc/consul/ca.crt",
|
|
CAPath: "/etc/consul/ca.dir",
|
|
CertFile: "/etc/consul/server.crt",
|
|
KeyFile: "/etc/consul/ssl/server.key",
|
|
VerifyOutgoing: false,
|
|
}
|
|
|
|
cfg, err := rt.APIConfig(false)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "198.18.0.2:5678", cfg.Address)
|
|
require.Equal(t, "https", cfg.Scheme)
|
|
require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile)
|
|
require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath)
|
|
require.Equal(t, "", cfg.TLSConfig.CertFile)
|
|
require.Equal(t, "", cfg.TLSConfig.KeyFile)
|
|
require.Equal(t, rt.Datacenter, cfg.Datacenter)
|
|
require.Equal(t, true, cfg.TLSConfig.InsecureSkipVerify)
|
|
|
|
rt.VerifyOutgoing = true
|
|
cfg, err = rt.APIConfig(true)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "198.18.0.2:5678", cfg.Address)
|
|
require.Equal(t, "https", cfg.Scheme)
|
|
require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile)
|
|
require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath)
|
|
require.Equal(t, rt.CertFile, cfg.TLSConfig.CertFile)
|
|
require.Equal(t, rt.KeyFile, cfg.TLSConfig.KeyFile)
|
|
require.Equal(t, rt.Datacenter, cfg.Datacenter)
|
|
require.Equal(t, false, cfg.TLSConfig.InsecureSkipVerify)
|
|
}
|
|
|
|
func TestRuntime_APIConfigHTTP(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.UnixAddr{Name: "/var/run/foo"},
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5678},
|
|
},
|
|
Datacenter: "dc-test",
|
|
}
|
|
|
|
cfg, err := rt.APIConfig(false)
|
|
require.NoError(t, err)
|
|
require.Equal(t, rt.Datacenter, cfg.Datacenter)
|
|
require.Equal(t, "198.18.0.1:5678", cfg.Address)
|
|
require.Equal(t, "http", cfg.Scheme)
|
|
require.Equal(t, "", cfg.TLSConfig.CAFile)
|
|
require.Equal(t, "", cfg.TLSConfig.CAPath)
|
|
require.Equal(t, "", cfg.TLSConfig.CertFile)
|
|
require.Equal(t, "", cfg.TLSConfig.KeyFile)
|
|
}
|
|
|
|
func TestRuntime_APIConfigUNIX(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.UnixAddr{Name: "/var/run/foo"},
|
|
},
|
|
Datacenter: "dc-test",
|
|
}
|
|
|
|
cfg, err := rt.APIConfig(false)
|
|
require.NoError(t, err)
|
|
require.Equal(t, rt.Datacenter, cfg.Datacenter)
|
|
require.Equal(t, "unix:///var/run/foo", cfg.Address)
|
|
require.Equal(t, "http", cfg.Scheme)
|
|
require.Equal(t, "", cfg.TLSConfig.CAFile)
|
|
require.Equal(t, "", cfg.TLSConfig.CAPath)
|
|
require.Equal(t, "", cfg.TLSConfig.CertFile)
|
|
require.Equal(t, "", cfg.TLSConfig.KeyFile)
|
|
}
|
|
|
|
func TestRuntime_APIConfigANYAddrV4(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 5678},
|
|
},
|
|
Datacenter: "dc-test",
|
|
}
|
|
|
|
cfg, err := rt.APIConfig(false)
|
|
require.NoError(t, err)
|
|
require.Equal(t, rt.Datacenter, cfg.Datacenter)
|
|
require.Equal(t, "127.0.0.1:5678", cfg.Address)
|
|
require.Equal(t, "http", cfg.Scheme)
|
|
require.Equal(t, "", cfg.TLSConfig.CAFile)
|
|
require.Equal(t, "", cfg.TLSConfig.CAPath)
|
|
require.Equal(t, "", cfg.TLSConfig.CertFile)
|
|
require.Equal(t, "", cfg.TLSConfig.KeyFile)
|
|
}
|
|
|
|
func TestRuntime_APIConfigANYAddrV6(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("::"), Port: 5678},
|
|
},
|
|
Datacenter: "dc-test",
|
|
}
|
|
|
|
cfg, err := rt.APIConfig(false)
|
|
require.NoError(t, err)
|
|
require.Equal(t, rt.Datacenter, cfg.Datacenter)
|
|
require.Equal(t, "[::1]:5678", cfg.Address)
|
|
require.Equal(t, "http", cfg.Scheme)
|
|
require.Equal(t, "", cfg.TLSConfig.CAFile)
|
|
require.Equal(t, "", cfg.TLSConfig.CAPath)
|
|
require.Equal(t, "", cfg.TLSConfig.CertFile)
|
|
require.Equal(t, "", cfg.TLSConfig.KeyFile)
|
|
}
|
|
|
|
func TestRuntime_ClientAddress(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("::"), Port: 5678},
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5679},
|
|
&net.UnixAddr{Name: "/var/run/foo", Net: "unix"},
|
|
},
|
|
HTTPSAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("::"), Port: 5688},
|
|
&net.TCPAddr{IP: net.ParseIP("198.18.0.1"), Port: 5689},
|
|
},
|
|
}
|
|
|
|
unix, http, https := rt.ClientAddress()
|
|
|
|
require.Equal(t, "unix:///var/run/foo", unix)
|
|
require.Equal(t, "198.18.0.1:5679", http)
|
|
require.Equal(t, "198.18.0.1:5689", https)
|
|
}
|
|
|
|
func TestRuntime_ClientAddressAnyV4(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 5678},
|
|
&net.UnixAddr{Name: "/var/run/foo", Net: "unix"},
|
|
},
|
|
HTTPSAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 5688},
|
|
},
|
|
}
|
|
|
|
unix, http, https := rt.ClientAddress()
|
|
|
|
require.Equal(t, "unix:///var/run/foo", unix)
|
|
require.Equal(t, "127.0.0.1:5678", http)
|
|
require.Equal(t, "127.0.0.1:5688", https)
|
|
}
|
|
|
|
func TestRuntime_ClientAddressAnyV6(t *testing.T) {
|
|
rt := RuntimeConfig{
|
|
HTTPAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("::"), Port: 5678},
|
|
&net.UnixAddr{Name: "/var/run/foo", Net: "unix"},
|
|
},
|
|
HTTPSAddrs: []net.Addr{
|
|
&net.TCPAddr{IP: net.ParseIP("::"), Port: 5688},
|
|
},
|
|
}
|
|
|
|
unix, http, https := rt.ClientAddress()
|
|
|
|
require.Equal(t, "unix:///var/run/foo", unix)
|
|
require.Equal(t, "[::1]:5678", http)
|
|
require.Equal(t, "[::1]:5688", https)
|
|
}
|
|
|
|
func TestRuntime_ToTLSUtilConfig(t *testing.T) {
|
|
c := &RuntimeConfig{
|
|
VerifyIncoming: true,
|
|
VerifyIncomingRPC: true,
|
|
VerifyIncomingHTTPS: true,
|
|
VerifyOutgoing: true,
|
|
VerifyServerHostname: true,
|
|
CAFile: "a",
|
|
CAPath: "b",
|
|
CertFile: "c",
|
|
KeyFile: "d",
|
|
NodeName: "e",
|
|
ServerName: "f",
|
|
DNSDomain: "g",
|
|
TLSMinVersion: "tls12",
|
|
TLSCipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
|
|
TLSPreferServerCipherSuites: true,
|
|
EnableAgentTLSForChecks: true,
|
|
AutoEncryptTLS: true,
|
|
}
|
|
r := c.ToTLSUtilConfig()
|
|
require.True(t, r.VerifyIncoming)
|
|
require.True(t, r.VerifyIncomingRPC)
|
|
require.True(t, r.VerifyIncomingHTTPS)
|
|
require.True(t, r.VerifyOutgoing)
|
|
require.True(t, r.EnableAgentTLSForChecks)
|
|
require.True(t, r.AutoTLS)
|
|
require.True(t, r.VerifyServerHostname)
|
|
require.True(t, r.PreferServerCipherSuites)
|
|
require.Equal(t, "a", r.CAFile)
|
|
require.Equal(t, "b", r.CAPath)
|
|
require.Equal(t, "c", r.CertFile)
|
|
require.Equal(t, "d", r.KeyFile)
|
|
require.Equal(t, "e", r.NodeName)
|
|
require.Equal(t, "f", r.ServerName)
|
|
require.Equal(t, "g", r.Domain)
|
|
require.Equal(t, "tls12", r.TLSMinVersion)
|
|
require.Equal(t, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, r.CipherSuites)
|
|
}
|
|
|
|
func TestRuntime_ToTLSUtilConfig_AutoConfig(t *testing.T) {
|
|
c := &RuntimeConfig{
|
|
VerifyIncoming: true,
|
|
VerifyIncomingRPC: true,
|
|
VerifyIncomingHTTPS: true,
|
|
VerifyOutgoing: true,
|
|
VerifyServerHostname: true,
|
|
CAFile: "a",
|
|
CAPath: "b",
|
|
CertFile: "c",
|
|
KeyFile: "d",
|
|
NodeName: "e",
|
|
ServerName: "f",
|
|
DNSDomain: "g",
|
|
TLSMinVersion: "tls12",
|
|
TLSCipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
|
|
TLSPreferServerCipherSuites: true,
|
|
EnableAgentTLSForChecks: true,
|
|
AutoConfig: AutoConfig{Enabled: true},
|
|
}
|
|
r := c.ToTLSUtilConfig()
|
|
require.True(t, r.VerifyIncoming)
|
|
require.True(t, r.VerifyIncomingRPC)
|
|
require.True(t, r.VerifyIncomingHTTPS)
|
|
require.True(t, r.VerifyOutgoing)
|
|
require.True(t, r.EnableAgentTLSForChecks)
|
|
require.True(t, r.AutoTLS)
|
|
require.True(t, r.VerifyServerHostname)
|
|
require.True(t, r.PreferServerCipherSuites)
|
|
require.Equal(t, "a", r.CAFile)
|
|
require.Equal(t, "b", r.CAPath)
|
|
require.Equal(t, "c", r.CertFile)
|
|
require.Equal(t, "d", r.KeyFile)
|
|
require.Equal(t, "e", r.NodeName)
|
|
require.Equal(t, "f", r.ServerName)
|
|
require.Equal(t, "g", r.Domain)
|
|
require.Equal(t, "tls12", r.TLSMinVersion)
|
|
require.Equal(t, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, r.CipherSuites)
|
|
}
|
|
|
|
func Test_UIPathBuilder(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
path string
|
|
expected string
|
|
}{
|
|
{
|
|
"Letters only string",
|
|
"hello",
|
|
"/hello/",
|
|
},
|
|
{
|
|
"Alphanumeric",
|
|
"Hello1",
|
|
"/Hello1/",
|
|
},
|
|
{
|
|
"Hyphen and underscore",
|
|
"-_",
|
|
"/-_/",
|
|
},
|
|
{
|
|
"Many slashes",
|
|
"/hello/ui/1/",
|
|
"/hello/ui/1/",
|
|
},
|
|
}
|
|
|
|
for _, tt := range cases {
|
|
actual := UIPathBuilder(tt.path)
|
|
require.Equal(t, tt.expected, actual)
|
|
|
|
}
|
|
}
|
|
|
|
func splitIPPort(hostport string) (net.IP, int) {
|
|
h, p, err := net.SplitHostPort(hostport)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
port, err := strconv.Atoi(p)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return net.ParseIP(h), port
|
|
}
|
|
|
|
func ipAddr(addr string) *net.IPAddr {
|
|
return &net.IPAddr{IP: net.ParseIP(addr)}
|
|
}
|
|
|
|
func tcpAddr(addr string) *net.TCPAddr {
|
|
ip, port := splitIPPort(addr)
|
|
return &net.TCPAddr{IP: ip, Port: port}
|
|
}
|
|
|
|
func udpAddr(addr string) *net.UDPAddr {
|
|
ip, port := splitIPPort(addr)
|
|
return &net.UDPAddr{IP: ip, Port: port}
|
|
}
|
|
|
|
func unixAddr(addr string) *net.UnixAddr {
|
|
if !strings.HasPrefix(addr, "unix://") {
|
|
panic("not a unix socket addr: " + addr)
|
|
}
|
|
return &net.UnixAddr{Net: "unix", Name: addr[len("unix://"):]}
|
|
}
|
|
|
|
func writeFile(path string, data []byte) {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
|
|
panic(err)
|
|
}
|
|
if err := ioutil.WriteFile(path, data, 0640); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func cleanDir(path string) {
|
|
root := path
|
|
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
if path == root {
|
|
return nil
|
|
}
|
|
return os.RemoveAll(path)
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func randomString(n int) string {
|
|
s := ""
|
|
for ; n > 0; n-- {
|
|
s += "x"
|
|
}
|
|
return s
|
|
}
|
|
|
|
func metaPairs(n int, format string) string {
|
|
var s []string
|
|
for i := 0; i < n; i++ {
|
|
switch format {
|
|
case "json":
|
|
s = append(s, fmt.Sprintf(`"%d":"%d"`, i, i))
|
|
case "hcl":
|
|
s = append(s, fmt.Sprintf(`"%d"="%d"`, i, i))
|
|
default:
|
|
panic("invalid format: " + format)
|
|
}
|
|
}
|
|
switch format {
|
|
case "json":
|
|
return strings.Join(s, ",")
|
|
case "hcl":
|
|
return strings.Join(s, " ")
|
|
default:
|
|
panic("invalid format: " + format)
|
|
}
|
|
}
|
|
|
|
func TestConnectCAConfiguration(t *testing.T) {
|
|
type testCase struct {
|
|
config RuntimeConfig
|
|
expected *structs.CAConfiguration
|
|
err string
|
|
}
|
|
|
|
cases := map[string]testCase{
|
|
"defaults": {
|
|
config: RuntimeConfig{
|
|
ConnectEnabled: true,
|
|
},
|
|
expected: &structs.CAConfiguration{
|
|
Provider: "consul",
|
|
Config: map[string]interface{}{
|
|
"RotationPeriod": "2160h",
|
|
"LeafCertTTL": "72h",
|
|
"IntermediateCertTTL": "8760h", // 365 * 24h
|
|
},
|
|
},
|
|
},
|
|
"cluster-id-override": {
|
|
config: RuntimeConfig{
|
|
ConnectEnabled: true,
|
|
ConnectCAConfig: map[string]interface{}{
|
|
"cluster_id": "adfe7697-09b4-413a-ac0a-fa81ed3a3001",
|
|
},
|
|
},
|
|
expected: &structs.CAConfiguration{
|
|
Provider: "consul",
|
|
ClusterID: "adfe7697-09b4-413a-ac0a-fa81ed3a3001",
|
|
Config: map[string]interface{}{
|
|
"RotationPeriod": "2160h",
|
|
"LeafCertTTL": "72h",
|
|
"IntermediateCertTTL": "8760h", // 365 * 24h
|
|
"cluster_id": "adfe7697-09b4-413a-ac0a-fa81ed3a3001",
|
|
},
|
|
},
|
|
},
|
|
"cluster-id-non-uuid": {
|
|
config: RuntimeConfig{
|
|
ConnectEnabled: true,
|
|
ConnectCAConfig: map[string]interface{}{
|
|
"cluster_id": "foo",
|
|
},
|
|
},
|
|
err: "cluster_id was supplied but was not a valid UUID",
|
|
},
|
|
"provider-override": {
|
|
config: RuntimeConfig{
|
|
ConnectEnabled: true,
|
|
ConnectCAProvider: "vault",
|
|
},
|
|
expected: &structs.CAConfiguration{
|
|
Provider: "vault",
|
|
Config: map[string]interface{}{
|
|
"RotationPeriod": "2160h",
|
|
"LeafCertTTL": "72h",
|
|
"IntermediateCertTTL": "8760h", // 365 * 24h
|
|
},
|
|
},
|
|
},
|
|
"other-config": {
|
|
config: RuntimeConfig{
|
|
ConnectEnabled: true,
|
|
ConnectCAConfig: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
},
|
|
expected: &structs.CAConfiguration{
|
|
Provider: "consul",
|
|
Config: map[string]interface{}{
|
|
"RotationPeriod": "2160h",
|
|
"LeafCertTTL": "72h",
|
|
"IntermediateCertTTL": "8760h", // 365 * 24h
|
|
"foo": "bar",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for name, tcase := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
actual, err := tcase.config.ConnectCAConfiguration()
|
|
if tcase.err != "" {
|
|
testutil.RequireErrorContains(t, err, tcase.err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.Equal(t, tcase.expected, actual)
|
|
}
|
|
})
|
|
}
|
|
}
|