1package config
2
3import (
4	"fmt"
5	"strconv"
6
7	"github.com/hashicorp/consul/agent/consul"
8	"github.com/hashicorp/consul/version"
9)
10
11func DefaultRPCProtocol() (int, error) {
12	src := DefaultSource()
13	c, err := Parse(src.Data, src.Format)
14	if err != nil {
15		return 0, fmt.Errorf("Error parsing default config: %s", err)
16	}
17	if c.RPCProtocol == nil {
18		return 0, fmt.Errorf("No default RPC protocol set")
19	}
20	return *c.RPCProtocol, nil
21}
22
23// DefaultSource is the default agent configuration.
24// This needs to be merged first in the head.
25// todo(fs): The values are sourced from multiple sources.
26// todo(fs): IMO, this should be the definitive default for all configurable values
27// todo(fs): and whatever is in here should clobber every default value. Hence, no sourcing.
28func DefaultSource() Source {
29	cfg := consul.DefaultConfig()
30	serfLAN := cfg.SerfLANConfig.MemberlistConfig
31	serfWAN := cfg.SerfWANConfig.MemberlistConfig
32
33	return Source{
34		Name:   "default",
35		Format: "hcl",
36		Data: `
37		acl_default_policy = "allow"
38		acl_down_policy = "extend-cache"
39		acl_enforce_version_8 = true
40		acl_ttl = "30s"
41		bind_addr = "0.0.0.0"
42		bootstrap = false
43		bootstrap_expect = 0
44		check_update_interval = "5m"
45		client_addr = "127.0.0.1"
46		datacenter = "` + consul.DefaultDC + `"
47		disable_coordinates = false
48		disable_host_node_id = true
49		disable_remote_exec = true
50		domain = "consul."
51		encrypt_verify_incoming = true
52		encrypt_verify_outgoing = true
53		log_level = "INFO"
54		protocol =  2
55		retry_interval = "30s"
56		retry_interval_wan = "30s"
57		server = false
58		syslog_facility = "LOCAL0"
59		tls_min_version = "tls10"
60
61		// TODO (slackpad) - Until #3744 is done, we need to keep these
62		// in sync with agent/consul/config.go.
63		autopilot = {
64			cleanup_dead_servers = true
65			last_contact_threshold = "200ms"
66			max_trailing_logs = 250
67			server_stabilization_time = "10s"
68		}
69		gossip_lan = {
70			gossip_interval = "` + serfLAN.GossipInterval.String() + `"
71			gossip_nodes = ` + strconv.Itoa(serfLAN.GossipNodes) + `
72			retransmit_mult = ` + strconv.Itoa(serfLAN.RetransmitMult) + `
73			probe_interval = "` + serfLAN.ProbeInterval.String() + `"
74			probe_timeout = "` + serfLAN.ProbeTimeout.String() + `"
75			suspicion_mult = ` + strconv.Itoa(serfLAN.SuspicionMult) + `
76		}
77		gossip_wan = {
78			gossip_interval = "` + serfWAN.GossipInterval.String() + `"
79			gossip_nodes = ` + strconv.Itoa(serfLAN.GossipNodes) + `
80			retransmit_mult = ` + strconv.Itoa(serfLAN.RetransmitMult) + `
81			probe_interval = "` + serfWAN.ProbeInterval.String() + `"
82			probe_timeout = "` + serfWAN.ProbeTimeout.String() + `"
83			suspicion_mult = ` + strconv.Itoa(serfWAN.SuspicionMult) + `
84		}
85		dns_config = {
86			allow_stale = true
87			a_record_limit = 0
88			udp_answer_limit = 3
89			max_stale = "87600h"
90			recursor_timeout = "2s"
91		}
92		limits = {
93			rpc_rate = -1
94			rpc_max_burst = 1000
95		}
96		performance = {
97			leave_drain_time = "5s"
98			raft_multiplier = ` + strconv.Itoa(int(consul.DefaultRaftMultiplier)) + `
99			rpc_hold_timeout = "7s"
100		}
101		ports = {
102			dns = 8600
103			http = 8500
104			https = -1
105			grpc = -1
106			serf_lan = ` + strconv.Itoa(consul.DefaultLANSerfPort) + `
107			serf_wan = ` + strconv.Itoa(consul.DefaultWANSerfPort) + `
108			server = ` + strconv.Itoa(consul.DefaultRPCPort) + `
109			proxy_min_port = 20000
110			proxy_max_port = 20255
111			sidecar_min_port = 21000
112			sidecar_max_port = 21255
113		}
114		telemetry = {
115			metrics_prefix = "consul"
116			filter_default = true
117		}
118
119	`,
120	}
121}
122
123// DevSource is the additional default configuration for dev mode.
124// This should be merged in the head after the default configuration.
125func DevSource() Source {
126	return Source{
127		Name:   "dev",
128		Format: "hcl",
129		Data: `
130		bind_addr = "127.0.0.1"
131		disable_anonymous_signature = true
132		disable_keyring_file = true
133		enable_debug = true
134		ui = true
135		log_level = "DEBUG"
136		server = true
137
138		gossip_lan = {
139			gossip_interval = "100ms"
140			probe_interval = "100ms"
141			probe_timeout = "100ms"
142			suspicion_mult = 3
143		}
144		gossip_wan = {
145			gossip_interval = "100ms"
146			probe_interval = "100ms"
147			probe_timeout = "100ms"
148			suspicion_mult = 3
149		}
150		connect = {
151			enabled = true
152		}
153		performance = {
154			raft_multiplier = 1
155		}
156		ports = {
157			grpc = 8502
158		}
159	`,
160	}
161}
162
163// NonUserSource contains the values the user cannot configure.
164// This needs to be merged in the tail.
165func NonUserSource() Source {
166	return Source{
167		Name:   "non-user",
168		Format: "hcl",
169		Data: `
170		acl_disabled_ttl = "120s"
171		check_deregister_interval_min = "1m"
172		check_reap_interval = "30s"
173		ae_interval = "1m"
174		sync_coordinate_rate_target = 64
175		sync_coordinate_interval_min = "15s"
176
177		# segment_limit is the maximum number of network segments that may be declared.
178		segment_limit = 64
179
180		# SegmentNameLimit is the maximum segment name length.
181		segment_name_limit = 64
182	`,
183	}
184}
185
186// VersionSource creates a config source for the version parameters.
187// This should be merged in the tail since these values are not
188// user configurable.
189func VersionSource(rev, ver, verPre string) Source {
190	return Source{
191		Name:   "version",
192		Format: "hcl",
193		Data:   fmt.Sprintf(`revision = %q version = %q version_prerelease = %q`, rev, ver, verPre),
194	}
195}
196
197// DefaultVersionSource returns the version config source for the embedded
198// version numbers.
199func DefaultVersionSource() Source {
200	return VersionSource(version.GitCommit, version.Version, version.VersionPrerelease)
201}
202
203// DefaultConsulSource returns the default configuration for the consul agent.
204// This should be merged in the tail since these values are not user configurable.
205func DefaultConsulSource() Source {
206	cfg := consul.DefaultConfig()
207	raft := cfg.RaftConfig
208	return Source{
209		Name:   "consul",
210		Format: "hcl",
211		Data: `
212		consul = {
213			coordinate = {
214				update_batch_size = ` + strconv.Itoa(cfg.CoordinateUpdateBatchSize) + `
215				update_max_batches = ` + strconv.Itoa(cfg.CoordinateUpdateMaxBatches) + `
216				update_period = "` + cfg.CoordinateUpdatePeriod.String() + `"
217			}
218			raft = {
219				election_timeout = "` + raft.ElectionTimeout.String() + `"
220				heartbeat_timeout = "` + raft.HeartbeatTimeout.String() + `"
221				leader_lease_timeout = "` + raft.LeaderLeaseTimeout.String() + `"
222			}
223			server = {
224				health_interval = "` + cfg.ServerHealthInterval.String() + `"
225			}
226		}
227	`,
228	}
229}
230
231// DevConsulSource returns the consul agent configuration for the dev mode.
232// This should be merged in the tail after the DefaultConsulSource.
233func DevConsulSource() Source {
234	return Source{
235		Name:   "consul-dev",
236		Format: "hcl",
237		Data: `
238		consul = {
239			coordinate = {
240				update_period = "100ms"
241			}
242			raft = {
243				election_timeout = "52ms"
244				heartbeat_timeout = "35ms"
245				leader_lease_timeout = "20ms"
246			}
247			server = {
248				health_interval = "10ms"
249			}
250		}
251	`,
252	}
253}
254
255func DefaultRuntimeConfig(hcl string) *RuntimeConfig {
256	b, err := NewBuilder(Flags{HCL: []string{hcl}})
257	if err != nil {
258		panic(err)
259	}
260	rt, err := b.BuildAndValidate()
261	if err != nil {
262		panic(err)
263	}
264	return &rt
265}
266