forked from hashicorp/nomad
/
consul.go
294 lines (260 loc) · 8.45 KB
/
consul.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
package config
import (
"net/http"
"strings"
"time"
consul "github.com/hashicorp/consul/api"
"github.com/hashicorp/nomad/helper"
)
// ConsulConfig contains the configuration information necessary to
// communicate with a Consul Agent in order to:
//
// - Register services and their checks with Consul
//
// - Bootstrap this Nomad Client with the list of Nomad Servers registered
// with Consul
//
// Both the Agent and the executor need to be able to import ConsulConfig.
type ConsulConfig struct {
// ServerServiceName is the name of the service that Nomad uses to register
// servers with Consul
ServerServiceName string `hcl:"server_service_name"`
// ServerHTTPCheckName is the name of the health check that Nomad uses
// to register the server HTTP health check with Consul
ServerHTTPCheckName string `hcl:"server_http_check_name"`
// ServerSerfCheckName is the name of the health check that Nomad uses
// to register the server Serf health check with Consul
ServerSerfCheckName string `hcl:"server_serf_check_name"`
// ServerRPCCheckName is the name of the health check that Nomad uses
// to register the server RPC health check with Consul
ServerRPCCheckName string `hcl:"server_rpc_check_name"`
// ClientServiceName is the name of the service that Nomad uses to register
// clients with Consul
ClientServiceName string `hcl:"client_service_name"`
// ClientHTTPCheckName is the name of the health check that Nomad uses
// to register the client HTTP health check with Consul
ClientHTTPCheckName string `hcl:"client_http_check_name"`
// Tags are optional service tags that get registered with the service
// in Consul
Tags []string `hcl:"tags"`
// AutoAdvertise determines if this Nomad Agent will advertise its
// services via Consul. When true, Nomad Agent will register
// services with Consul.
AutoAdvertise *bool `hcl:"auto_advertise"`
// ChecksUseAdvertise specifies that Consul checks should use advertise
// address instead of bind address
ChecksUseAdvertise *bool `hcl:"checks_use_advertise"`
// Addr is the HTTP endpoint address of the local Consul agent
//
// Uses Consul's default and env var.
Addr string `hcl:"address"`
// GRPCAddr is the gRPC endpoint address of the local Consul agent
GRPCAddr string `hcl:"grpc_address"`
// Timeout is used by Consul HTTP Client
Timeout time.Duration
TimeoutHCL string `hcl:"timeout" json:"-"`
// Token is used to provide a per-request ACL token. This options overrides
// the agent's default token
Token string `hcl:"token"`
// Auth is the information to use for http access to Consul agent
Auth string `hcl:"auth"`
// EnableSSL sets the transport scheme to talk to the Consul agent as https
//
// Uses Consul's default and env var.
EnableSSL *bool `hcl:"ssl"`
// VerifySSL enables or disables SSL verification when the transport scheme
// for the consul api client is https
//
// Uses Consul's default and env var.
VerifySSL *bool `hcl:"verify_ssl"`
// CAFile is the path to the ca certificate used for Consul communication.
//
// Uses Consul's default and env var.
CAFile string `hcl:"ca_file"`
// CertFile is the path to the certificate for Consul communication
CertFile string `hcl:"cert_file"`
// KeyFile is the path to the private key for Consul communication
KeyFile string `hcl:"key_file"`
// ServerAutoJoin enables Nomad servers to find peers by querying Consul and
// joining them
ServerAutoJoin *bool `hcl:"server_auto_join"`
// ClientAutoJoin enables Nomad servers to find addresses of Nomad servers
// and register with them
ClientAutoJoin *bool `hcl:"client_auto_join"`
// ExtraKeysHCL is used by hcl to surface unexpected keys
ExtraKeysHCL []string `hcl:",unusedKeys" json:"-"`
}
// DefaultConsulConfig() returns the canonical defaults for the Nomad
// `consul` configuration. Uses Consul's default configuration which reads
// environment variables.
func DefaultConsulConfig() *ConsulConfig {
def := consul.DefaultConfig()
return &ConsulConfig{
ServerServiceName: "nomad",
ServerHTTPCheckName: "Nomad Server HTTP Check",
ServerSerfCheckName: "Nomad Server Serf Check",
ServerRPCCheckName: "Nomad Server RPC Check",
ClientServiceName: "nomad-client",
ClientHTTPCheckName: "Nomad Client HTTP Check",
AutoAdvertise: helper.BoolToPtr(true),
ChecksUseAdvertise: helper.BoolToPtr(false),
ServerAutoJoin: helper.BoolToPtr(true),
ClientAutoJoin: helper.BoolToPtr(true),
Timeout: 5 * time.Second,
// From Consul api package defaults
Addr: def.Address,
EnableSSL: helper.BoolToPtr(def.Scheme == "https"),
VerifySSL: helper.BoolToPtr(!def.TLSConfig.InsecureSkipVerify),
CAFile: def.TLSConfig.CAFile,
}
}
// Merge merges two Consul Configurations together.
func (a *ConsulConfig) Merge(b *ConsulConfig) *ConsulConfig {
result := a.Copy()
if b.ServerServiceName != "" {
result.ServerServiceName = b.ServerServiceName
}
if b.ServerHTTPCheckName != "" {
result.ServerHTTPCheckName = b.ServerHTTPCheckName
}
if b.ServerSerfCheckName != "" {
result.ServerSerfCheckName = b.ServerSerfCheckName
}
if b.ServerRPCCheckName != "" {
result.ServerRPCCheckName = b.ServerRPCCheckName
}
if b.ClientServiceName != "" {
result.ClientServiceName = b.ClientServiceName
}
if b.ClientHTTPCheckName != "" {
result.ClientHTTPCheckName = b.ClientHTTPCheckName
}
result.Tags = append(result.Tags, b.Tags...)
if b.AutoAdvertise != nil {
result.AutoAdvertise = helper.BoolToPtr(*b.AutoAdvertise)
}
if b.Addr != "" {
result.Addr = b.Addr
}
if b.GRPCAddr != "" {
result.GRPCAddr = b.GRPCAddr
}
if b.Timeout != 0 {
result.Timeout = b.Timeout
}
if b.TimeoutHCL != "" {
result.TimeoutHCL = b.TimeoutHCL
}
if b.Token != "" {
result.Token = b.Token
}
if b.Auth != "" {
result.Auth = b.Auth
}
if b.EnableSSL != nil {
result.EnableSSL = helper.BoolToPtr(*b.EnableSSL)
}
if b.VerifySSL != nil {
result.VerifySSL = helper.BoolToPtr(*b.VerifySSL)
}
if b.CAFile != "" {
result.CAFile = b.CAFile
}
if b.CertFile != "" {
result.CertFile = b.CertFile
}
if b.KeyFile != "" {
result.KeyFile = b.KeyFile
}
if b.ServerAutoJoin != nil {
result.ServerAutoJoin = helper.BoolToPtr(*b.ServerAutoJoin)
}
if b.ClientAutoJoin != nil {
result.ClientAutoJoin = helper.BoolToPtr(*b.ClientAutoJoin)
}
if b.ChecksUseAdvertise != nil {
result.ChecksUseAdvertise = helper.BoolToPtr(*b.ChecksUseAdvertise)
}
return result
}
// ApiConfig returns a usable Consul config that can be passed directly to
// hashicorp/consul/api. NOTE: datacenter is not set
func (c *ConsulConfig) ApiConfig() (*consul.Config, error) {
// Get the default config from consul to reuse things like the default
// http.Transport.
config := consul.DefaultConfig()
if c.Addr != "" {
config.Address = c.Addr
}
if c.Token != "" {
config.Token = c.Token
}
if c.Timeout != 0 {
// Create a custom Client to set the timeout
if config.HttpClient == nil {
config.HttpClient = &http.Client{}
}
config.HttpClient.Timeout = c.Timeout
config.HttpClient.Transport = config.Transport
}
if c.Auth != "" {
var username, password string
if strings.Contains(c.Auth, ":") {
split := strings.SplitN(c.Auth, ":", 2)
username = split[0]
password = split[1]
} else {
username = c.Auth
}
config.HttpAuth = &consul.HttpBasicAuth{
Username: username,
Password: password,
}
}
if c.EnableSSL != nil && *c.EnableSSL {
config.Scheme = "https"
config.TLSConfig = consul.TLSConfig{
Address: config.Address,
CAFile: c.CAFile,
CertFile: c.CertFile,
KeyFile: c.KeyFile,
}
if c.VerifySSL != nil {
config.TLSConfig.InsecureSkipVerify = !*c.VerifySSL
}
tlsConfig, err := consul.SetupTLSConfig(&config.TLSConfig)
if err != nil {
return nil, err
}
config.Transport.TLSClientConfig = tlsConfig
}
return config, nil
}
// Copy returns a copy of this Consul config.
func (c *ConsulConfig) Copy() *ConsulConfig {
if c == nil {
return nil
}
nc := new(ConsulConfig)
*nc = *c
// Copy the bools
if nc.AutoAdvertise != nil {
nc.AutoAdvertise = helper.BoolToPtr(*nc.AutoAdvertise)
}
if nc.ChecksUseAdvertise != nil {
nc.ChecksUseAdvertise = helper.BoolToPtr(*nc.ChecksUseAdvertise)
}
if nc.EnableSSL != nil {
nc.EnableSSL = helper.BoolToPtr(*nc.EnableSSL)
}
if nc.VerifySSL != nil {
nc.VerifySSL = helper.BoolToPtr(*nc.VerifySSL)
}
if nc.ServerAutoJoin != nil {
nc.ServerAutoJoin = helper.BoolToPtr(*nc.ServerAutoJoin)
}
if nc.ClientAutoJoin != nil {
nc.ClientAutoJoin = helper.BoolToPtr(*nc.ClientAutoJoin)
}
return nc
}