mirror of https://github.com/status-im/consul.git
1680 lines
44 KiB
Go
1680 lines
44 KiB
Go
package agent
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"encoding/base64"
|
|
"errors"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
"github.com/hashicorp/consul/testutil"
|
|
"github.com/pascaldekloe/goe/verify"
|
|
)
|
|
|
|
func TestConfigEncryptBytes(t *testing.T) {
|
|
t.Parallel()
|
|
// Test with some input
|
|
src := []byte("abc")
|
|
c := &Config{
|
|
EncryptKey: base64.StdEncoding.EncodeToString(src),
|
|
}
|
|
|
|
result, err := c.EncryptBytes()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if !bytes.Equal(src, result) {
|
|
t.Fatalf("bad: %#v", result)
|
|
}
|
|
|
|
// Test with no input
|
|
c = &Config{}
|
|
result, err = c.EncryptBytes()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if len(result) > 0 {
|
|
t.Fatalf("bad: %#v", result)
|
|
}
|
|
}
|
|
|
|
func TestDecodeConfig(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
in string
|
|
c *Config
|
|
err error
|
|
parseTemplateErr error
|
|
}{
|
|
// special flows
|
|
{
|
|
in: `{"bad": "no way jose"}`,
|
|
err: errors.New("Config has invalid keys: bad"),
|
|
},
|
|
{
|
|
in: `{"advertise_addr":"unix:///path/to/file"}`,
|
|
parseTemplateErr: errors.New("Failed to parse Advertise address: unix:///path/to/file"),
|
|
c: &Config{AdvertiseAddr: "unix:///path/to/file"},
|
|
},
|
|
{
|
|
in: `{"advertise_addr_wan":"unix:///path/to/file"}`,
|
|
parseTemplateErr: errors.New("Failed to parse Advertise WAN address: unix:///path/to/file"),
|
|
c: &Config{AdvertiseAddrWan: "unix:///path/to/file"},
|
|
},
|
|
{
|
|
in: `{"addresses":{"http":"notunix://blah"}}`,
|
|
parseTemplateErr: errors.New("Failed to parse HTTP address, \"notunix://blah\" is not a valid IP address or socket"),
|
|
c: &Config{Addresses: AddressConfig{HTTP: "notunix://blah"}},
|
|
},
|
|
|
|
// happy flows in alphabetical order
|
|
{
|
|
in: `{"acl_agent_master_token":"a"}`,
|
|
c: &Config{ACLAgentMasterToken: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_agent_token":"a"}`,
|
|
c: &Config{ACLAgentToken: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_datacenter":"a"}`,
|
|
c: &Config{ACLDatacenter: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_default_policy":"a"}`,
|
|
c: &Config{ACLDefaultPolicy: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_down_policy":"a"}`,
|
|
c: &Config{ACLDownPolicy: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_enforce_version_8":true}`,
|
|
c: &Config{ACLEnforceVersion8: Bool(true)},
|
|
},
|
|
{
|
|
in: `{"acl_master_token":"a"}`,
|
|
c: &Config{ACLMasterToken: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_replication_token":"a"}`,
|
|
c: &Config{
|
|
EnableACLReplication: true,
|
|
ACLReplicationToken: "a",
|
|
},
|
|
},
|
|
{
|
|
in: `{"acl_token":"a"}`,
|
|
c: &Config{ACLToken: "a"},
|
|
},
|
|
{
|
|
in: `{"acl_ttl":"2s"}`,
|
|
c: &Config{ACLTTL: 2 * time.Second, ACLTTLRaw: "2s"},
|
|
},
|
|
{
|
|
in: `{"addresses":{"dns":"1.2.3.4"}}`,
|
|
c: &Config{Addresses: AddressConfig{DNS: "1.2.3.4"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"dns":"{{\"1.2.3.4\"}}"}}`,
|
|
c: &Config{Addresses: AddressConfig{DNS: "1.2.3.4"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"http":"1.2.3.4"}}`,
|
|
c: &Config{Addresses: AddressConfig{HTTP: "1.2.3.4"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"http":"unix:///var/foo/bar"}}`,
|
|
c: &Config{Addresses: AddressConfig{HTTP: "unix:///var/foo/bar"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"http":"{{\"1.2.3.4\"}}"}}`,
|
|
c: &Config{Addresses: AddressConfig{HTTP: "1.2.3.4"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"https":"1.2.3.4"}}`,
|
|
c: &Config{Addresses: AddressConfig{HTTPS: "1.2.3.4"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"https":"unix:///var/foo/bar"}}`,
|
|
c: &Config{Addresses: AddressConfig{HTTPS: "unix:///var/foo/bar"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"https":"{{\"1.2.3.4\"}}"}}`,
|
|
c: &Config{Addresses: AddressConfig{HTTPS: "1.2.3.4"}},
|
|
},
|
|
{
|
|
in: `{"addresses":{"rpc":"a"}}`,
|
|
c: &Config{Addresses: AddressConfig{RPC: "a"}},
|
|
},
|
|
{
|
|
in: `{"advertise_addr":"1.2.3.4"}`,
|
|
c: &Config{AdvertiseAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"advertise_addr":"{{\"1.2.3.4\"}}"}`,
|
|
c: &Config{AdvertiseAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"advertise_addr_wan":"1.2.3.4"}`,
|
|
c: &Config{AdvertiseAddrWan: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"advertise_addr_wan":"{{\"1.2.3.4\"}}"}`,
|
|
c: &Config{AdvertiseAddrWan: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"advertise_addrs":{"rpc":"1.2.3.4:5678"}}`,
|
|
c: &Config{
|
|
AdvertiseAddrs: AdvertiseAddrsConfig{
|
|
RPC: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
RPCRaw: "1.2.3.4:5678",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
in: `{"advertise_addrs":{"serf_lan":"1.2.3.4:5678"}}`,
|
|
c: &Config{
|
|
AdvertiseAddrs: AdvertiseAddrsConfig{
|
|
SerfLan: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
SerfLanRaw: "1.2.3.4:5678",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
in: `{"advertise_addrs":{"serf_wan":"1.2.3.4:5678"}}`,
|
|
c: &Config{
|
|
AdvertiseAddrs: AdvertiseAddrsConfig{
|
|
SerfWan: &net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 5678},
|
|
SerfWanRaw: "1.2.3.4:5678",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
in: `{"atlas_acl_token":"a"}`,
|
|
c: &Config{DeprecatedAtlasACLToken: "a"},
|
|
},
|
|
{
|
|
in: `{"atlas_endpoint":"a"}`,
|
|
c: &Config{DeprecatedAtlasEndpoint: "a"},
|
|
},
|
|
{
|
|
in: `{"atlas_infrastructure":"a"}`,
|
|
c: &Config{DeprecatedAtlasInfrastructure: "a"},
|
|
},
|
|
{
|
|
in: `{"atlas_join":true}`,
|
|
c: &Config{DeprecatedAtlasJoin: true},
|
|
},
|
|
{
|
|
in: `{"atlas_token":"a"}`,
|
|
c: &Config{DeprecatedAtlasToken: "a"},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"cleanup_dead_servers":true}}`,
|
|
c: &Config{Autopilot: Autopilot{CleanupDeadServers: Bool(true)}},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"disable_upgrade_migration":true}}`,
|
|
c: &Config{Autopilot: Autopilot{DisableUpgradeMigration: Bool(true)}},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"upgrade_version_tag":"rev"}}`,
|
|
c: &Config{Autopilot: Autopilot{UpgradeVersionTag: "rev"}},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"last_contact_threshold":"2s"}}`,
|
|
c: &Config{Autopilot: Autopilot{LastContactThreshold: Duration(2 * time.Second), LastContactThresholdRaw: "2s"}},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"max_trailing_logs":10}}`,
|
|
c: &Config{Autopilot: Autopilot{MaxTrailingLogs: Uint64(10)}},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"server_stabilization_time":"2s"}}`,
|
|
c: &Config{Autopilot: Autopilot{ServerStabilizationTime: Duration(2 * time.Second), ServerStabilizationTimeRaw: "2s"}},
|
|
},
|
|
{
|
|
in: `{"autopilot":{"cleanup_dead_servers":true}}`,
|
|
c: &Config{Autopilot: Autopilot{CleanupDeadServers: Bool(true)}},
|
|
},
|
|
{
|
|
in: `{"bind_addr":"1.2.3.4"}`,
|
|
c: &Config{BindAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"bind_addr":"{{\"1.2.3.4\"}}"}`,
|
|
c: &Config{BindAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"bootstrap":true}`,
|
|
c: &Config{Bootstrap: true},
|
|
},
|
|
{
|
|
in: `{"bootstrap_expect":3}`,
|
|
c: &Config{BootstrapExpect: 3},
|
|
},
|
|
{
|
|
in: `{"ca_file":"a"}`,
|
|
c: &Config{CAFile: "a"},
|
|
},
|
|
{
|
|
in: `{"ca_path":"a"}`,
|
|
c: &Config{CAPath: "a"},
|
|
},
|
|
{
|
|
in: `{"check_update_interval":"2s"}`,
|
|
c: &Config{CheckUpdateInterval: 2 * time.Second, CheckUpdateIntervalRaw: "2s"},
|
|
},
|
|
{
|
|
in: `{"cert_file":"a"}`,
|
|
c: &Config{CertFile: "a"},
|
|
},
|
|
{
|
|
in: `{"client_addr":"1.2.3.4"}`,
|
|
c: &Config{ClientAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"client_addr":"{{\"1.2.3.4\"}}"}`,
|
|
c: &Config{ClientAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"data_dir":"a"}`,
|
|
c: &Config{DataDir: "a"},
|
|
},
|
|
{
|
|
in: `{"datacenter":"a"}`,
|
|
c: &Config{Datacenter: "a"},
|
|
},
|
|
{
|
|
in: `{"disable_coordinates":true}`,
|
|
c: &Config{DisableCoordinates: true},
|
|
},
|
|
{
|
|
in: `{"disable_host_node_id":false}`,
|
|
c: &Config{DisableHostNodeID: Bool(false)},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"allow_stale":true}}`,
|
|
c: &Config{DNSConfig: DNSConfig{AllowStale: Bool(true)}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"disable_compression":true}}`,
|
|
c: &Config{DNSConfig: DNSConfig{DisableCompression: true}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"enable_truncate":true}}`,
|
|
c: &Config{DNSConfig: DNSConfig{EnableTruncate: true}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"max_stale":"2s"}}`,
|
|
c: &Config{DNSConfig: DNSConfig{MaxStale: 2 * time.Second, MaxStaleRaw: "2s"}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"node_ttl":"2s"}}`,
|
|
c: &Config{DNSConfig: DNSConfig{NodeTTL: 2 * time.Second, NodeTTLRaw: "2s"}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"only_passing":true}}`,
|
|
c: &Config{DNSConfig: DNSConfig{OnlyPassing: true}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"recursor_timeout":"2s"}}`,
|
|
c: &Config{DNSConfig: DNSConfig{RecursorTimeout: 2 * time.Second, RecursorTimeoutRaw: "2s"}},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"service_ttl":{"*":"2s","a":"456s"}}}`,
|
|
c: &Config{
|
|
DNSConfig: DNSConfig{
|
|
ServiceTTL: map[string]time.Duration{"*": 2 * time.Second, "a": 456 * time.Second},
|
|
ServiceTTLRaw: map[string]string{"*": "2s", "a": "456s"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
in: `{"dns_config":{"udp_answer_limit":123}}`,
|
|
c: &Config{DNSConfig: DNSConfig{UDPAnswerLimit: 123}},
|
|
},
|
|
{
|
|
in: `{"disable_anonymous_signature":true}`,
|
|
c: &Config{DisableAnonymousSignature: true},
|
|
},
|
|
{
|
|
in: `{"disable_remote_exec":false}`,
|
|
c: &Config{DisableRemoteExec: Bool(false)},
|
|
},
|
|
{
|
|
in: `{"disable_update_check":true}`,
|
|
c: &Config{DisableUpdateCheck: true},
|
|
},
|
|
{
|
|
in: `{"dogstatsd_addr":"a"}`,
|
|
c: &Config{Telemetry: Telemetry{DogStatsdAddr: "a"}},
|
|
},
|
|
{
|
|
in: `{"dogstatsd_tags":["a:b","c:d"]}`,
|
|
c: &Config{Telemetry: Telemetry{DogStatsdTags: []string{"a:b", "c:d"}}},
|
|
},
|
|
{
|
|
in: `{"domain":"a"}`,
|
|
c: &Config{Domain: "a"},
|
|
},
|
|
{
|
|
in: `{"enable_acl_replication":true}`,
|
|
c: &Config{EnableACLReplication: true},
|
|
},
|
|
{
|
|
in: `{"enable_debug":true}`,
|
|
c: &Config{EnableDebug: true},
|
|
},
|
|
{
|
|
in: `{"enable_syslog":true}`,
|
|
c: &Config{EnableSyslog: true},
|
|
},
|
|
{
|
|
in: `{"disable_keyring_file":true}`,
|
|
c: &Config{DisableKeyringFile: true},
|
|
},
|
|
{
|
|
in: `{"enable_script_checks":true}`,
|
|
c: &Config{EnableScriptChecks: true},
|
|
},
|
|
{
|
|
in: `{"encrypt_verify_incoming":true}`,
|
|
c: &Config{EncryptVerifyIncoming: Bool(true)},
|
|
},
|
|
{
|
|
in: `{"encrypt_verify_outgoing":true}`,
|
|
c: &Config{EncryptVerifyOutgoing: Bool(true)},
|
|
},
|
|
{
|
|
in: `{"http_config":{"block_endpoints":["a","b","c","d"]}}`,
|
|
c: &Config{HTTPConfig: HTTPConfig{BlockEndpoints: []string{"a", "b", "c", "d"}}},
|
|
},
|
|
{
|
|
in: `{"http_api_response_headers":{"a":"b","c":"d"}}`,
|
|
c: &Config{HTTPConfig: HTTPConfig{ResponseHeaders: map[string]string{"a": "b", "c": "d"}}},
|
|
},
|
|
{
|
|
in: `{"http_config":{"response_headers":{"a":"b","c":"d"}}}`,
|
|
c: &Config{HTTPConfig: HTTPConfig{ResponseHeaders: map[string]string{"a": "b", "c": "d"}}},
|
|
},
|
|
{
|
|
in: `{"key_file":"a"}`,
|
|
c: &Config{KeyFile: "a"},
|
|
},
|
|
{
|
|
in: `{"leave_on_terminate":true}`,
|
|
c: &Config{LeaveOnTerm: Bool(true)},
|
|
},
|
|
{
|
|
in: `{"log_level":"a"}`,
|
|
c: &Config{LogLevel: "a"},
|
|
},
|
|
{
|
|
in: `{"node_id":"a"}`,
|
|
c: &Config{NodeID: "a"},
|
|
},
|
|
{
|
|
in: `{"node_meta":{"a":"b","c":"d"}}`,
|
|
c: &Config{Meta: map[string]string{"a": "b", "c": "d"}},
|
|
},
|
|
{
|
|
in: `{"node_name":"a"}`,
|
|
c: &Config{NodeName: "a"},
|
|
},
|
|
{
|
|
in: `{"performance": { "raft_multiplier": 3 }}`,
|
|
c: &Config{Performance: Performance{RaftMultiplier: 3}},
|
|
},
|
|
{
|
|
in: `{"performance": { "raft_multiplier": 11 }}`,
|
|
err: errors.New("Performance.RaftMultiplier must be <= 10"),
|
|
},
|
|
{
|
|
in: `{"pid_file":"a"}`,
|
|
c: &Config{PidFile: "a"},
|
|
},
|
|
{
|
|
in: `{"ports":{"dns":1234}}`,
|
|
c: &Config{Ports: PortConfig{DNS: 1234}},
|
|
},
|
|
{
|
|
in: `{"ports":{"http":1234}}`,
|
|
c: &Config{Ports: PortConfig{HTTP: 1234}},
|
|
},
|
|
{
|
|
in: `{"ports":{"https":1234}}`,
|
|
c: &Config{Ports: PortConfig{HTTPS: 1234}},
|
|
},
|
|
{
|
|
in: `{"ports":{"serf_lan":1234}}`,
|
|
c: &Config{Ports: PortConfig{SerfLan: 1234}},
|
|
},
|
|
{
|
|
in: `{"ports":{"serf_wan":1234}}`,
|
|
c: &Config{Ports: PortConfig{SerfWan: 1234}},
|
|
},
|
|
{
|
|
in: `{"ports":{"server":1234}}`,
|
|
c: &Config{Ports: PortConfig{Server: 1234}},
|
|
},
|
|
{
|
|
in: `{"ports":{"rpc":1234}}`,
|
|
c: &Config{Ports: PortConfig{RPC: 1234}},
|
|
},
|
|
{
|
|
in: `{"raft_protocol":3}`,
|
|
c: &Config{RaftProtocol: 3},
|
|
},
|
|
{
|
|
in: `{"reconnect_timeout":"4h"}`,
|
|
err: errors.New("ReconnectTimeoutLan must be >= 8h0m0s"),
|
|
},
|
|
{
|
|
in: `{"reconnect_timeout":"8h"}`,
|
|
c: &Config{ReconnectTimeoutLan: 8 * time.Hour, ReconnectTimeoutLanRaw: "8h"},
|
|
},
|
|
{
|
|
in: `{"reconnect_timeout_wan":"4h"}`,
|
|
err: errors.New("ReconnectTimeoutWan must be >= 8h0m0s"),
|
|
},
|
|
{
|
|
in: `{"reconnect_timeout_wan":"8h"}`,
|
|
c: &Config{ReconnectTimeoutWan: 8 * time.Hour, ReconnectTimeoutWanRaw: "8h"},
|
|
},
|
|
{
|
|
in: `{"recursor":"a"}`,
|
|
c: &Config{DNSRecursor: "a", DNSRecursors: []string{"a"}},
|
|
},
|
|
{
|
|
in: `{"recursors":["a","b"]}`,
|
|
c: &Config{DNSRecursors: []string{"a", "b"}},
|
|
},
|
|
{
|
|
in: `{"rejoin_after_leave":true}`,
|
|
c: &Config{RejoinAfterLeave: true},
|
|
},
|
|
{
|
|
in: `{"retry_interval":"2s"}`,
|
|
c: &Config{RetryInterval: 2 * time.Second, RetryIntervalRaw: "2s"},
|
|
},
|
|
{
|
|
in: `{"retry_interval_wan":"2s"}`,
|
|
c: &Config{RetryIntervalWan: 2 * time.Second, RetryIntervalWanRaw: "2s"},
|
|
},
|
|
{
|
|
in: `{"retry_join":["a","b"]}`,
|
|
c: &Config{RetryJoin: []string{"a", "b"}},
|
|
},
|
|
// todo(fs): temporarily disabling tests after moving the code
|
|
// todo(fs): to patch the deprecated retry-join flags to command/agent.go
|
|
// todo(fs): where it cannot be tested.
|
|
// {
|
|
// in: `{"retry_join_azure":{"client_id":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=azure client_id=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_azure":{"tag_name":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=azure tag_name=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_azure":{"tag_value":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=azure tag_value=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_azure":{"secret_access_key":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=azure secret_access_key=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_azure":{"subscription_id":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=azure subscription_id=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_azure":{"tenant_id":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=azure tenant_id=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_ec2":{"access_key_id":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=aws access_key_id=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_ec2":{"region":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=aws region=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_ec2":{"tag_key":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=aws tag_key=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_ec2":{"tag_value":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=aws tag_value=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_ec2":{"secret_access_key":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=aws secret_access_key=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_gce":{"credentials_file":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=gce credentials_file=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_gce":{"project_name":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=gce project_name=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_gce":{"tag_value":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=gce tag_value=a"}},
|
|
// },
|
|
// {
|
|
// in: `{"retry_join_gce":{"zone_pattern":"a"}}`,
|
|
// c: &Config{RetryJoin: []string{"provider=gce zone_pattern=a"}},
|
|
// },
|
|
{
|
|
in: `{"retry_join_wan":["a","b"]}`,
|
|
c: &Config{RetryJoinWan: []string{"a", "b"}},
|
|
},
|
|
{
|
|
in: `{"retry_max":123}`,
|
|
c: &Config{RetryMaxAttempts: 123},
|
|
},
|
|
{
|
|
in: `{"retry_max_wan":123}`,
|
|
c: &Config{RetryMaxAttemptsWan: 123},
|
|
},
|
|
{
|
|
in: `{"segment":"thing"}`,
|
|
c: &Config{Segment: "thing"},
|
|
},
|
|
{
|
|
in: `{"segments":[{"name": "alpha", "bind": "127.0.0.1", "port": 1234, "advertise": "1.1.1.1"}]}`,
|
|
c: &Config{Segments: []NetworkSegment{{Name: "alpha", Bind: "127.0.0.1", Port: 1234, Advertise: "1.1.1.1"}}},
|
|
},
|
|
{
|
|
in: `{"serf_lan_bind":"1.2.3.4"}`,
|
|
c: &Config{SerfLanBindAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"serf_lan_bind":"unix:///var/foo/bar"}`,
|
|
c: &Config{SerfLanBindAddr: "unix:///var/foo/bar"},
|
|
parseTemplateErr: errors.New("Failed to parse Serf LAN address: unix:///var/foo/bar"),
|
|
},
|
|
{
|
|
in: `{"serf_lan_bind":"{{\"1.2.3.4\"}}"}`,
|
|
c: &Config{SerfLanBindAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"serf_wan_bind":"1.2.3.4"}`,
|
|
c: &Config{SerfWanBindAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"serf_wan_bind":"unix:///var/foo/bar"}`,
|
|
c: &Config{SerfWanBindAddr: "unix:///var/foo/bar"},
|
|
parseTemplateErr: errors.New("Failed to parse Serf WAN address: unix:///var/foo/bar"),
|
|
},
|
|
{
|
|
in: `{"serf_wan_bind":"{{\"1.2.3.4\"}}"}`,
|
|
c: &Config{SerfWanBindAddr: "1.2.3.4"},
|
|
},
|
|
{
|
|
in: `{"server":true}`,
|
|
c: &Config{Server: true},
|
|
},
|
|
{
|
|
in: `{"server_name":"a"}`,
|
|
c: &Config{ServerName: "a"},
|
|
},
|
|
{
|
|
in: `{"session_ttl_min":"2s"}`,
|
|
c: &Config{SessionTTLMin: 2 * time.Second, SessionTTLMinRaw: "2s"},
|
|
},
|
|
{
|
|
in: `{"skip_leave_on_interrupt":true}`,
|
|
c: &Config{SkipLeaveOnInt: Bool(true)},
|
|
},
|
|
{
|
|
in: `{"start_join":["a","b"]}`,
|
|
c: &Config{StartJoin: []string{"a", "b"}},
|
|
},
|
|
{
|
|
in: `{"start_join_wan":["a","b"]}`,
|
|
c: &Config{StartJoinWan: []string{"a", "b"}},
|
|
},
|
|
{
|
|
in: `{"statsd_addr":"a"}`,
|
|
c: &Config{Telemetry: Telemetry{StatsdAddr: "a"}},
|
|
},
|
|
{
|
|
in: `{"statsite_addr":"a"}`,
|
|
c: &Config{Telemetry: Telemetry{StatsiteAddr: "a"}},
|
|
},
|
|
{
|
|
in: `{"statsite_prefix":"a"}`,
|
|
c: &Config{Telemetry: Telemetry{StatsitePrefix: "a"}},
|
|
},
|
|
{
|
|
in: `{"syslog_facility":"a"}`,
|
|
c: &Config{SyslogFacility: "a"},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_api_app":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusAPIApp: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_api_token":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusAPIToken: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_api_url":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusAPIURL: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_broker_id":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusBrokerID: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_broker_select_tag":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusBrokerSelectTag: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_check_display_name":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckDisplayName: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_check_force_metric_activation":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckForceMetricActivation: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_check_id":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckID: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_check_instance_id":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckInstanceID: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_check_search_tag":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckSearchTag: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_check_tags":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckTags: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_submission_interval":"2s"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusSubmissionInterval: "2s"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"circonus_submission_url":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{CirconusCheckSubmissionURL: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"disable_hostname":true}}`,
|
|
c: &Config{Telemetry: Telemetry{DisableHostname: true}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"dogstatsd_addr":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{DogStatsdAddr: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"dogstatsd_tags":["a","b"]}}`,
|
|
c: &Config{Telemetry: Telemetry{DogStatsdTags: []string{"a", "b"}}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"filter_default":true}}`,
|
|
c: &Config{Telemetry: Telemetry{FilterDefault: Bool(true)}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"prefix_filter":["+consul.metric","-consul.othermetric"]}}`,
|
|
c: &Config{Telemetry: Telemetry{
|
|
PrefixFilter: []string{"+consul.metric", "-consul.othermetric"},
|
|
AllowedPrefixes: []string{"consul.metric"},
|
|
BlockedPrefixes: []string{"consul.othermetric"},
|
|
}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"statsd_address":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{StatsdAddr: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"statsite_address":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{StatsiteAddr: "a"}},
|
|
},
|
|
{
|
|
in: `{"telemetry":{"statsite_prefix":"a"}}`,
|
|
c: &Config{Telemetry: Telemetry{StatsitePrefix: "a"}},
|
|
},
|
|
{
|
|
in: `{"tls_cipher_suites":"TLS_RSA_WITH_AES_256_CBC_SHA"}`,
|
|
c: &Config{
|
|
TLSCipherSuites: []uint16{tls.TLS_RSA_WITH_AES_256_CBC_SHA},
|
|
TLSCipherSuitesRaw: "TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
},
|
|
},
|
|
{
|
|
in: `{"tls_min_version":"a"}`,
|
|
c: &Config{TLSMinVersion: "a"},
|
|
},
|
|
{
|
|
in: `{"tls_prefer_server_cipher_suites":true}`,
|
|
c: &Config{TLSPreferServerCipherSuites: true},
|
|
},
|
|
{
|
|
in: `{"translate_wan_addrs":true}`,
|
|
c: &Config{TranslateWanAddrs: true},
|
|
},
|
|
{
|
|
in: `{"ui":true}`,
|
|
c: &Config{EnableUI: true},
|
|
},
|
|
{
|
|
in: `{"ui_dir":"a"}`,
|
|
c: &Config{UIDir: "a"},
|
|
},
|
|
{
|
|
in: `{"unix_sockets":{"user":"a"}}`,
|
|
c: &Config{UnixSockets: UnixSocketConfig{UnixSocketPermissions{Usr: "a"}}},
|
|
},
|
|
{
|
|
in: `{"unix_sockets":{"group":"a"}}`,
|
|
c: &Config{UnixSockets: UnixSocketConfig{UnixSocketPermissions{Grp: "a"}}},
|
|
},
|
|
{
|
|
in: `{"unix_sockets":{"mode":"a"}}`,
|
|
c: &Config{UnixSockets: UnixSocketConfig{UnixSocketPermissions{Perms: "a"}}},
|
|
},
|
|
{
|
|
in: `{"verify_incoming":true}`,
|
|
c: &Config{VerifyIncoming: true},
|
|
},
|
|
{
|
|
in: `{"verify_incoming_https":true}`,
|
|
c: &Config{VerifyIncomingHTTPS: true},
|
|
},
|
|
{
|
|
in: `{"verify_incoming_rpc":true}`,
|
|
c: &Config{VerifyIncomingRPC: true},
|
|
},
|
|
{
|
|
in: `{"verify_outgoing":true}`,
|
|
c: &Config{VerifyOutgoing: true},
|
|
},
|
|
{
|
|
in: `{"verify_server_hostname":true}`,
|
|
c: &Config{VerifyServerHostname: true},
|
|
},
|
|
{
|
|
in: `{"watches":[{"type":"a","prefix":"b","handler":"c"}]}`,
|
|
c: &Config{
|
|
Watches: []map[string]interface{}{
|
|
map[string]interface{}{
|
|
"type": "a",
|
|
"prefix": "b",
|
|
"handler": "c",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
// complex flows
|
|
{
|
|
desc: "single service with check",
|
|
in: `{
|
|
"service": {
|
|
"ID": "a",
|
|
"Name": "b",
|
|
"Tags": ["c", "d"],
|
|
"Address": "e",
|
|
"Token": "f",
|
|
"Port": 123,
|
|
"EnableTagOverride": true,
|
|
"Check": {
|
|
"CheckID": "g",
|
|
"Name": "h",
|
|
"Status": "i",
|
|
"Notes": "j",
|
|
"Script": "k",
|
|
"HTTP": "l",
|
|
"Header": {"a":["b"], "c":["d", "e"]},
|
|
"Method": "x",
|
|
"TCP": "m",
|
|
"DockerContainerID": "n",
|
|
"Shell": "o",
|
|
"TLSSkipVerify": true,
|
|
"Interval": "2s",
|
|
"Timeout": "3s",
|
|
"TTL": "4s",
|
|
"DeregisterCriticalServiceAfter": "5s"
|
|
}
|
|
}
|
|
}`,
|
|
c: &Config{
|
|
Services: []*structs.ServiceDefinition{
|
|
&structs.ServiceDefinition{
|
|
ID: "a",
|
|
Name: "b",
|
|
Tags: []string{"c", "d"},
|
|
Address: "e",
|
|
Port: 123,
|
|
Token: "f",
|
|
EnableTagOverride: true,
|
|
Check: structs.CheckType{
|
|
CheckID: "g",
|
|
Name: "h",
|
|
Status: "i",
|
|
Notes: "j",
|
|
Script: "k",
|
|
HTTP: "l",
|
|
Header: map[string][]string{"a": []string{"b"}, "c": []string{"d", "e"}},
|
|
Method: "x",
|
|
TCP: "m",
|
|
DockerContainerID: "n",
|
|
Shell: "o",
|
|
TLSSkipVerify: true,
|
|
Interval: 2 * time.Second,
|
|
Timeout: 3 * time.Second,
|
|
TTL: 4 * time.Second,
|
|
DeregisterCriticalServiceAfter: 5 * time.Second,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "single service with multiple checks",
|
|
in: `{
|
|
"service": {
|
|
"ID": "a",
|
|
"Name": "b",
|
|
"Tags": ["c", "d"],
|
|
"Address": "e",
|
|
"Token": "f",
|
|
"Port": 123,
|
|
"EnableTagOverride": true,
|
|
"Checks": [
|
|
{
|
|
"CheckID": "g",
|
|
"Name": "h",
|
|
"Status": "i",
|
|
"Notes": "j",
|
|
"Script": "k",
|
|
"HTTP": "l",
|
|
"Header": {"a":["b"], "c":["d", "e"]},
|
|
"Method": "x",
|
|
"TCP": "m",
|
|
"DockerContainerID": "n",
|
|
"Shell": "o",
|
|
"TLSSkipVerify": true,
|
|
"Interval": "2s",
|
|
"Timeout": "3s",
|
|
"TTL": "4s",
|
|
"DeregisterCriticalServiceAfter": "5s"
|
|
},
|
|
{
|
|
"CheckID": "gg",
|
|
"Name": "hh",
|
|
"Status": "ii",
|
|
"Notes": "jj",
|
|
"Script": "kk",
|
|
"HTTP": "ll",
|
|
"Header": {"aa":["bb"], "cc":["dd", "ee"]},
|
|
"Method": "xx",
|
|
"TCP": "mm",
|
|
"DockerContainerID": "nn",
|
|
"Shell": "oo",
|
|
"TLSSkipVerify": false,
|
|
"Interval": "22s",
|
|
"Timeout": "33s",
|
|
"TTL": "44s",
|
|
"DeregisterCriticalServiceAfter": "55s"
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
c: &Config{
|
|
Services: []*structs.ServiceDefinition{
|
|
&structs.ServiceDefinition{
|
|
ID: "a",
|
|
Name: "b",
|
|
Tags: []string{"c", "d"},
|
|
Address: "e",
|
|
Port: 123,
|
|
Token: "f",
|
|
EnableTagOverride: true,
|
|
Checks: []*structs.CheckType{
|
|
{
|
|
CheckID: "g",
|
|
Name: "h",
|
|
Status: "i",
|
|
Notes: "j",
|
|
Script: "k",
|
|
HTTP: "l",
|
|
Header: map[string][]string{"a": []string{"b"}, "c": []string{"d", "e"}},
|
|
Method: "x",
|
|
TCP: "m",
|
|
DockerContainerID: "n",
|
|
Shell: "o",
|
|
TLSSkipVerify: true,
|
|
Interval: 2 * time.Second,
|
|
Timeout: 3 * time.Second,
|
|
TTL: 4 * time.Second,
|
|
DeregisterCriticalServiceAfter: 5 * time.Second,
|
|
},
|
|
{
|
|
CheckID: "gg",
|
|
Name: "hh",
|
|
Status: "ii",
|
|
Notes: "jj",
|
|
Script: "kk",
|
|
HTTP: "ll",
|
|
Header: map[string][]string{"aa": []string{"bb"}, "cc": []string{"dd", "ee"}},
|
|
Method: "xx",
|
|
TCP: "mm",
|
|
DockerContainerID: "nn",
|
|
Shell: "oo",
|
|
TLSSkipVerify: false,
|
|
Interval: 22 * time.Second,
|
|
Timeout: 33 * time.Second,
|
|
TTL: 44 * time.Second,
|
|
DeregisterCriticalServiceAfter: 55 * time.Second,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "multiple services with check",
|
|
in: `{
|
|
"services": [
|
|
{
|
|
"ID": "a",
|
|
"Name": "b",
|
|
"Tags": ["c", "d"],
|
|
"Address": "e",
|
|
"Token": "f",
|
|
"Port": 123,
|
|
"EnableTagOverride": true,
|
|
"Check": {
|
|
"CheckID": "g",
|
|
"Name": "h",
|
|
"Status": "i",
|
|
"Notes": "j",
|
|
"Script": "k",
|
|
"HTTP": "l",
|
|
"Header": {"a":["b"], "c":["d", "e"]},
|
|
"Method": "x",
|
|
"TCP": "m",
|
|
"DockerContainerID": "n",
|
|
"Shell": "o",
|
|
"TLSSkipVerify": true,
|
|
"Interval": "2s",
|
|
"Timeout": "3s",
|
|
"TTL": "4s",
|
|
"DeregisterCriticalServiceAfter": "5s"
|
|
}
|
|
},
|
|
{
|
|
"ID": "aa",
|
|
"Name": "bb",
|
|
"Tags": ["cc", "dd"],
|
|
"Address": "ee",
|
|
"Token": "ff",
|
|
"Port": 246,
|
|
"EnableTagOverride": false,
|
|
"Check": {
|
|
"CheckID": "gg",
|
|
"Name": "hh",
|
|
"Status": "ii",
|
|
"Notes": "jj",
|
|
"Script": "kk",
|
|
"HTTP": "ll",
|
|
"Header": {"aa":["bb"], "cc":["dd", "ee"]},
|
|
"Method": "xx",
|
|
"TCP": "mm",
|
|
"DockerContainerID": "nn",
|
|
"Shell": "oo",
|
|
"TLSSkipVerify": false,
|
|
"Interval": "22s",
|
|
"Timeout": "33s",
|
|
"TTL": "44s",
|
|
"DeregisterCriticalServiceAfter": "55s"
|
|
}
|
|
}
|
|
]
|
|
}`,
|
|
c: &Config{
|
|
Services: []*structs.ServiceDefinition{
|
|
&structs.ServiceDefinition{
|
|
ID: "a",
|
|
Name: "b",
|
|
Tags: []string{"c", "d"},
|
|
Address: "e",
|
|
Port: 123,
|
|
Token: "f",
|
|
EnableTagOverride: true,
|
|
Check: structs.CheckType{
|
|
CheckID: "g",
|
|
Name: "h",
|
|
Status: "i",
|
|
Notes: "j",
|
|
Script: "k",
|
|
HTTP: "l",
|
|
Header: map[string][]string{"a": []string{"b"}, "c": []string{"d", "e"}},
|
|
Method: "x",
|
|
TCP: "m",
|
|
DockerContainerID: "n",
|
|
Shell: "o",
|
|
TLSSkipVerify: true,
|
|
Interval: 2 * time.Second,
|
|
Timeout: 3 * time.Second,
|
|
TTL: 4 * time.Second,
|
|
DeregisterCriticalServiceAfter: 5 * time.Second,
|
|
},
|
|
},
|
|
&structs.ServiceDefinition{
|
|
ID: "aa",
|
|
Name: "bb",
|
|
Tags: []string{"cc", "dd"},
|
|
Address: "ee",
|
|
Port: 246,
|
|
Token: "ff",
|
|
EnableTagOverride: false,
|
|
Check: structs.CheckType{
|
|
CheckID: "gg",
|
|
Name: "hh",
|
|
Status: "ii",
|
|
Notes: "jj",
|
|
Script: "kk",
|
|
HTTP: "ll",
|
|
Header: map[string][]string{"aa": []string{"bb"}, "cc": []string{"dd", "ee"}},
|
|
Method: "xx",
|
|
TCP: "mm",
|
|
DockerContainerID: "nn",
|
|
Shell: "oo",
|
|
TLSSkipVerify: false,
|
|
Interval: 22 * time.Second,
|
|
Timeout: 33 * time.Second,
|
|
TTL: 44 * time.Second,
|
|
DeregisterCriticalServiceAfter: 55 * time.Second,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
{
|
|
desc: "single check",
|
|
in: `{
|
|
"check": {
|
|
"id": "a",
|
|
"name": "b",
|
|
"notes": "c",
|
|
"service_id": "x",
|
|
"token": "y",
|
|
"status": "z",
|
|
"script": "d",
|
|
"shell": "e",
|
|
"http": "f",
|
|
"Header": {"a":["b"], "c":["d", "e"]},
|
|
"Method": "x",
|
|
"tcp": "g",
|
|
"docker_container_id": "h",
|
|
"tls_skip_verify": true,
|
|
"interval": "2s",
|
|
"timeout": "3s",
|
|
"ttl": "4s",
|
|
"deregister_critical_service_after": "5s"
|
|
}
|
|
}`,
|
|
c: &Config{
|
|
Checks: []*structs.CheckDefinition{
|
|
&structs.CheckDefinition{
|
|
ID: "a",
|
|
Name: "b",
|
|
Notes: "c",
|
|
ServiceID: "x",
|
|
Token: "y",
|
|
Status: "z",
|
|
Script: "d",
|
|
Shell: "e",
|
|
HTTP: "f",
|
|
Header: map[string][]string{"a": []string{"b"}, "c": []string{"d", "e"}},
|
|
Method: "x",
|
|
TCP: "g",
|
|
DockerContainerID: "h",
|
|
TLSSkipVerify: true,
|
|
Interval: 2 * time.Second,
|
|
Timeout: 3 * time.Second,
|
|
TTL: 4 * time.Second,
|
|
DeregisterCriticalServiceAfter: 5 * time.Second,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "multiple checks",
|
|
in: `{
|
|
"checks": [
|
|
{
|
|
"id": "a",
|
|
"name": "b",
|
|
"notes": "c",
|
|
"service_id": "d",
|
|
"token": "e",
|
|
"status": "f",
|
|
"script": "g",
|
|
"shell": "h",
|
|
"http": "i",
|
|
"Header": {"a":["b"], "c":["d", "e"]},
|
|
"Method": "x",
|
|
"tcp": "j",
|
|
"docker_container_id": "k",
|
|
"tls_skip_verify": true,
|
|
"interval": "2s",
|
|
"timeout": "3s",
|
|
"ttl": "4s",
|
|
"deregister_critical_service_after": "5s"
|
|
},
|
|
{
|
|
"id": "aa",
|
|
"name": "bb",
|
|
"notes": "cc",
|
|
"service_id": "dd",
|
|
"token": "ee",
|
|
"status": "ff",
|
|
"script": "gg",
|
|
"shell": "hh",
|
|
"http": "ii",
|
|
"Header": {"aa":["bb"], "cc":["dd", "ee"]},
|
|
"Method": "xx",
|
|
"tcp": "jj",
|
|
"docker_container_id": "kk",
|
|
"tls_skip_verify": false,
|
|
"interval": "22s",
|
|
"timeout": "33s",
|
|
"ttl": "44s",
|
|
"deregister_critical_service_after": "55s"
|
|
}
|
|
]
|
|
}`,
|
|
c: &Config{
|
|
Checks: []*structs.CheckDefinition{
|
|
&structs.CheckDefinition{
|
|
ID: "a",
|
|
Name: "b",
|
|
Notes: "c",
|
|
ServiceID: "d",
|
|
Token: "e",
|
|
Status: "f",
|
|
Script: "g",
|
|
Shell: "h",
|
|
HTTP: "i",
|
|
Header: map[string][]string{"a": []string{"b"}, "c": []string{"d", "e"}},
|
|
Method: "x",
|
|
TCP: "j",
|
|
DockerContainerID: "k",
|
|
TLSSkipVerify: true,
|
|
Interval: 2 * time.Second,
|
|
Timeout: 3 * time.Second,
|
|
TTL: 4 * time.Second,
|
|
DeregisterCriticalServiceAfter: 5 * time.Second,
|
|
},
|
|
&structs.CheckDefinition{
|
|
ID: "aa",
|
|
Name: "bb",
|
|
Notes: "cc",
|
|
ServiceID: "dd",
|
|
Token: "ee",
|
|
Status: "ff",
|
|
Script: "gg",
|
|
Shell: "hh",
|
|
HTTP: "ii",
|
|
Header: map[string][]string{"aa": []string{"bb"}, "cc": []string{"dd", "ee"}},
|
|
Method: "xx",
|
|
TCP: "jj",
|
|
DockerContainerID: "kk",
|
|
TLSSkipVerify: false,
|
|
Interval: 22 * time.Second,
|
|
Timeout: 33 * time.Second,
|
|
TTL: 44 * time.Second,
|
|
DeregisterCriticalServiceAfter: 55 * time.Second,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
desc := tt.desc
|
|
if desc == "" {
|
|
desc = tt.in
|
|
}
|
|
t.Run(desc, func(t *testing.T) {
|
|
c, err := DecodeConfig(strings.NewReader(tt.in))
|
|
if got, want := err, tt.err; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("got error %v want %v", got, want)
|
|
}
|
|
err = c.ResolveTmplAddrs()
|
|
if got, want := err, tt.parseTemplateErr; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("got error %v on ResolveTmplAddrs, expected %v", err, want)
|
|
}
|
|
got, want := c, tt.c
|
|
verify.Values(t, "", got, want)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecodeConfig_VerifyUniqueListeners(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
desc string
|
|
in string
|
|
err error
|
|
}{
|
|
{
|
|
"http_dns1",
|
|
`{"addresses": {"http": "0.0.0.0", "dns": "127.0.0.1"}, "ports": {"dns": 8000}}`,
|
|
nil,
|
|
},
|
|
{
|
|
"http_dns IP identical",
|
|
`{"addresses": {"http": "0.0.0.0", "dns": "0.0.0.0"}, "ports": {"http": 8000, "dns": 8000}}`,
|
|
errors.New("HTTP address already configured for DNS"),
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
c, err := DecodeConfig(strings.NewReader(tt.in))
|
|
if err != nil {
|
|
t.Fatalf("got error %v want nil", err)
|
|
}
|
|
|
|
err = c.VerifyUniqueListeners()
|
|
if got, want := err, tt.err; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("got error %v want %v", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecodeConfig_ValidateSegments(t *testing.T) {
|
|
t.Parallel()
|
|
serverWithSegment := &Config{Segment: "asfd", Server: true}
|
|
if err := ValidateSegments(serverWithSegment); !strings.Contains(err.Error(), "can only be set on clients") {
|
|
t.Fatalf("bad: %v", err)
|
|
}
|
|
|
|
clientWithSegments := &Config{
|
|
Segments: []NetworkSegment{{Name: "asdf"}},
|
|
}
|
|
if err := ValidateSegments(clientWithSegments); !strings.Contains(err.Error(), "Cannot define segments on clients") {
|
|
t.Fatalf("bad: %v", err)
|
|
}
|
|
|
|
tooManySegments := &Config{Server: true}
|
|
for i := 0; i < SegmentLimit+1; i++ {
|
|
tooManySegments.Segments = append(tooManySegments.Segments, NetworkSegment{})
|
|
}
|
|
if err := ValidateSegments(tooManySegments); !strings.Contains(err.Error(), "Cannot exceed network segment limit") {
|
|
t.Fatalf("bad: %v", err)
|
|
}
|
|
|
|
segmentNameTooLong := &Config{
|
|
Segments: []NetworkSegment{{Name: strings.Repeat("a", SegmentNameLimit+1)}},
|
|
Server: true,
|
|
}
|
|
if err := ValidateSegments(segmentNameTooLong); !strings.Contains(err.Error(), "exceeds maximum length") {
|
|
t.Fatalf("bad: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDefaultConfig(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// ACL flag for Consul version 0.8 features (broken out since we will
|
|
// eventually remove this).
|
|
config := DefaultConfig()
|
|
if *config.ACLEnforceVersion8 != true {
|
|
t.Fatalf("bad: %#v", config)
|
|
}
|
|
|
|
// Remote exec is disabled by default.
|
|
if *config.DisableRemoteExec != true {
|
|
t.Fatalf("bad: %#v", config)
|
|
}
|
|
}
|
|
|
|
func TestMergeConfig(t *testing.T) {
|
|
t.Parallel()
|
|
a := &Config{
|
|
Bootstrap: false,
|
|
BootstrapExpect: 0,
|
|
Datacenter: "dc1",
|
|
DataDir: "/tmp/foo",
|
|
Domain: "basic",
|
|
LogLevel: "debug",
|
|
NodeID: "bar",
|
|
NodeName: "foo",
|
|
ClientAddr: "127.0.0.1",
|
|
BindAddr: "127.0.0.1",
|
|
AdvertiseAddr: "127.0.0.1",
|
|
Server: false,
|
|
LeaveOnTerm: new(bool),
|
|
SkipLeaveOnInt: new(bool),
|
|
EnableDebug: false,
|
|
CheckUpdateIntervalRaw: "8m",
|
|
RetryIntervalRaw: "10s",
|
|
RetryIntervalWanRaw: "10s",
|
|
DeprecatedRetryJoinEC2: RetryJoinEC2{
|
|
Region: "us-east-1",
|
|
TagKey: "Key1",
|
|
TagValue: "Value1",
|
|
AccessKeyID: "nope",
|
|
SecretAccessKey: "nope",
|
|
},
|
|
Telemetry: Telemetry{
|
|
DisableHostname: false,
|
|
StatsdAddr: "nope",
|
|
StatsiteAddr: "nope",
|
|
StatsitePrefix: "nope",
|
|
DogStatsdAddr: "nope",
|
|
DogStatsdTags: []string{"nope"},
|
|
},
|
|
Meta: map[string]string{
|
|
"key": "value1",
|
|
},
|
|
}
|
|
|
|
b := &Config{
|
|
Performance: Performance{
|
|
RaftMultiplier: 99,
|
|
},
|
|
Bootstrap: true,
|
|
BootstrapExpect: 3,
|
|
Datacenter: "dc2",
|
|
DataDir: "/tmp/bar",
|
|
DNSRecursors: []string{"127.0.0.2:1001"},
|
|
DNSConfig: DNSConfig{
|
|
AllowStale: Bool(false),
|
|
EnableTruncate: true,
|
|
DisableCompression: true,
|
|
MaxStale: 30 * time.Second,
|
|
NodeTTL: 10 * time.Second,
|
|
ServiceTTL: map[string]time.Duration{
|
|
"api": 10 * time.Second,
|
|
},
|
|
UDPAnswerLimit: 4,
|
|
RecursorTimeout: 30 * time.Second,
|
|
},
|
|
Domain: "other",
|
|
LogLevel: "info",
|
|
NodeID: "bar",
|
|
DisableHostNodeID: Bool(false),
|
|
NodeName: "baz",
|
|
ClientAddr: "127.0.0.2",
|
|
BindAddr: "127.0.0.2",
|
|
AdvertiseAddr: "127.0.0.2",
|
|
AdvertiseAddrWan: "127.0.0.2",
|
|
Ports: PortConfig{
|
|
DNS: 1,
|
|
HTTP: 2,
|
|
SerfLan: 4,
|
|
SerfWan: 5,
|
|
Server: 6,
|
|
HTTPS: 7,
|
|
},
|
|
Addresses: AddressConfig{
|
|
DNS: "127.0.0.1",
|
|
HTTP: "127.0.0.2",
|
|
HTTPS: "127.0.0.4",
|
|
},
|
|
Segment: "alpha",
|
|
Segments: []NetworkSegment{
|
|
{
|
|
Name: "alpha",
|
|
Bind: "127.0.0.1",
|
|
Port: 1234,
|
|
Advertise: "127.0.0.2",
|
|
},
|
|
},
|
|
Server: true,
|
|
LeaveOnTerm: Bool(true),
|
|
SkipLeaveOnInt: Bool(true),
|
|
RaftProtocol: 3,
|
|
Autopilot: Autopilot{
|
|
CleanupDeadServers: Bool(true),
|
|
LastContactThreshold: Duration(time.Duration(10)),
|
|
MaxTrailingLogs: Uint64(10),
|
|
ServerStabilizationTime: Duration(time.Duration(100)),
|
|
},
|
|
EnableDebug: true,
|
|
VerifyIncoming: true,
|
|
VerifyOutgoing: true,
|
|
CAFile: "test/ca.pem",
|
|
CertFile: "test/cert.pem",
|
|
KeyFile: "test/key.pem",
|
|
TLSMinVersion: "tls12",
|
|
Checks: []*structs.CheckDefinition{nil},
|
|
Services: []*structs.ServiceDefinition{nil},
|
|
StartJoin: []string{"1.1.1.1"},
|
|
StartJoinWan: []string{"1.1.1.1"},
|
|
EnableUI: true,
|
|
UIDir: "/opt/consul-ui",
|
|
EnableSyslog: true,
|
|
RejoinAfterLeave: true,
|
|
RetryJoin: []string{"1.1.1.1"},
|
|
RetryIntervalRaw: "10s",
|
|
RetryInterval: 10 * time.Second,
|
|
RetryJoinWan: []string{"1.1.1.1"},
|
|
RetryIntervalWanRaw: "10s",
|
|
RetryIntervalWan: 10 * time.Second,
|
|
ReconnectTimeoutLanRaw: "24h",
|
|
ReconnectTimeoutLan: 24 * time.Hour,
|
|
ReconnectTimeoutWanRaw: "36h",
|
|
ReconnectTimeoutWan: 36 * time.Hour,
|
|
EnableScriptChecks: true,
|
|
CheckUpdateInterval: 8 * time.Minute,
|
|
CheckUpdateIntervalRaw: "8m",
|
|
ACLToken: "1111",
|
|
ACLAgentMasterToken: "2222",
|
|
ACLAgentToken: "3333",
|
|
ACLMasterToken: "4444",
|
|
ACLDatacenter: "dc2",
|
|
ACLTTL: 15 * time.Second,
|
|
ACLTTLRaw: "15s",
|
|
ACLDownPolicy: "deny",
|
|
ACLDefaultPolicy: "deny",
|
|
ACLReplicationToken: "8765309",
|
|
ACLEnforceVersion8: Bool(true),
|
|
Watches: []map[string]interface{}{
|
|
map[string]interface{}{
|
|
"type": "keyprefix",
|
|
"prefix": "foo/",
|
|
"handler": "foobar",
|
|
},
|
|
},
|
|
DisableRemoteExec: Bool(true),
|
|
Telemetry: Telemetry{
|
|
StatsiteAddr: "127.0.0.1:7250",
|
|
StatsitePrefix: "stats_prefix",
|
|
StatsdAddr: "127.0.0.1:7251",
|
|
DisableHostname: true,
|
|
DogStatsdAddr: "127.0.0.1:7254",
|
|
DogStatsdTags: []string{"tag_1:val_1", "tag_2:val_2"},
|
|
},
|
|
Meta: map[string]string{
|
|
"key": "value2",
|
|
},
|
|
DisableUpdateCheck: true,
|
|
DisableAnonymousSignature: true,
|
|
HTTPConfig: HTTPConfig{
|
|
BlockEndpoints: []string{
|
|
"/v1/agent/self",
|
|
"/v1/acl",
|
|
},
|
|
ResponseHeaders: map[string]string{
|
|
"Access-Control-Allow-Origin": "*",
|
|
},
|
|
},
|
|
UnixSockets: UnixSocketConfig{
|
|
UnixSocketPermissions{
|
|
Usr: "500",
|
|
Grp: "500",
|
|
Perms: "0700",
|
|
},
|
|
},
|
|
DeprecatedRetryJoinEC2: RetryJoinEC2{
|
|
Region: "us-east-2",
|
|
TagKey: "Key2",
|
|
TagValue: "Value2",
|
|
AccessKeyID: "foo",
|
|
SecretAccessKey: "bar",
|
|
},
|
|
SessionTTLMinRaw: "1000s",
|
|
SessionTTLMin: 1000 * time.Second,
|
|
AdvertiseAddrs: AdvertiseAddrsConfig{
|
|
SerfLan: &net.TCPAddr{},
|
|
SerfLanRaw: "127.0.0.5:1231",
|
|
SerfWan: &net.TCPAddr{},
|
|
SerfWanRaw: "127.0.0.5:1232",
|
|
RPC: &net.TCPAddr{},
|
|
RPCRaw: "127.0.0.5:1233",
|
|
},
|
|
}
|
|
|
|
c := MergeConfig(a, b)
|
|
|
|
if !reflect.DeepEqual(c, b) {
|
|
t.Fatalf("should be equal %#v %#v", c, b)
|
|
}
|
|
}
|
|
|
|
func TestReadConfigPaths_badPath(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := ReadConfigPaths([]string{"/i/shouldnt/exist/ever/rainbows"})
|
|
if err == nil {
|
|
t.Fatal("should have err")
|
|
}
|
|
}
|
|
|
|
func TestReadConfigPaths_file(t *testing.T) {
|
|
t.Parallel()
|
|
tf := testutil.TempFile(t, "consul")
|
|
tf.Write([]byte(`{"node_name":"bar"}`))
|
|
tf.Close()
|
|
defer os.Remove(tf.Name())
|
|
|
|
config, err := ReadConfigPaths([]string{tf.Name()})
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if config.NodeName != "bar" {
|
|
t.Fatalf("bad: %#v", config)
|
|
}
|
|
}
|
|
|
|
func TestReadConfigPaths_dir(t *testing.T) {
|
|
t.Parallel()
|
|
td := testutil.TempDir(t, "consul")
|
|
defer os.RemoveAll(td)
|
|
|
|
err := ioutil.WriteFile(filepath.Join(td, "a.json"),
|
|
[]byte(`{"node_name": "bar"}`), 0644)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
err = ioutil.WriteFile(filepath.Join(td, "b.json"),
|
|
[]byte(`{"node_name": "baz"}`), 0644)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
// A non-json file, shouldn't be read
|
|
err = ioutil.WriteFile(filepath.Join(td, "c"),
|
|
[]byte(`{"node_name": "bad"}`), 0644)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
// An empty file shouldn't be read
|
|
err = ioutil.WriteFile(filepath.Join(td, "d.json"),
|
|
[]byte{}, 0664)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
config, err := ReadConfigPaths([]string{td})
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if config.NodeName != "baz" {
|
|
t.Fatalf("bad: %#v", config)
|
|
}
|
|
}
|
|
|
|
func TestUnixSockets(t *testing.T) {
|
|
t.Parallel()
|
|
if p := socketPath("unix:///path/to/socket"); p != "/path/to/socket" {
|
|
t.Fatalf("bad: %q", p)
|
|
}
|
|
if p := socketPath("notunix://blah"); p != "" {
|
|
t.Fatalf("bad: %q", p)
|
|
}
|
|
}
|
|
|
|
func TestCheckDefinitionToCheckType(t *testing.T) {
|
|
t.Parallel()
|
|
got := &structs.CheckDefinition{
|
|
ID: "id",
|
|
Name: "name",
|
|
Status: "green",
|
|
Notes: "notes",
|
|
|
|
ServiceID: "svcid",
|
|
Token: "tok",
|
|
Script: "/bin/foo",
|
|
HTTP: "someurl",
|
|
TCP: "host:port",
|
|
Interval: 1 * time.Second,
|
|
DockerContainerID: "abc123",
|
|
Shell: "/bin/ksh",
|
|
TLSSkipVerify: true,
|
|
Timeout: 2 * time.Second,
|
|
TTL: 3 * time.Second,
|
|
DeregisterCriticalServiceAfter: 4 * time.Second,
|
|
}
|
|
want := &structs.CheckType{
|
|
CheckID: "id",
|
|
Name: "name",
|
|
Status: "green",
|
|
Notes: "notes",
|
|
|
|
Script: "/bin/foo",
|
|
HTTP: "someurl",
|
|
TCP: "host:port",
|
|
Interval: 1 * time.Second,
|
|
DockerContainerID: "abc123",
|
|
Shell: "/bin/ksh",
|
|
TLSSkipVerify: true,
|
|
Timeout: 2 * time.Second,
|
|
TTL: 3 * time.Second,
|
|
DeregisterCriticalServiceAfter: 4 * time.Second,
|
|
}
|
|
verify.Values(t, "", got.CheckType(), want)
|
|
}
|