open-nomad/nomad/structs/config/consul.go

191 lines
4.9 KiB
Go

package config
import (
"crypto/tls"
"fmt"
"net/http"
"strings"
"time"
consul "github.com/hashicorp/consul/api"
)
// 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 `mapstructure:"server_service_name"`
// ClientServiceName is the name of the service that Nomad uses to register
// clients with Consul
ClientServiceName string `mapstructure:"client_service_name"`
// AutoAdvertise determines if this Nomad Agent will advertise its
// services via Consul. When true, Nomad Agent will register
// services with Consul.
AutoAdvertise bool `mapstructure:"auto_advertise"`
// Addr is the address of the local Consul agent
Addr string `mapstructure:"address"`
// Timeout is used by Consul HTTP Client
Timeout time.Duration `mapstructure:"timeout"`
// Token is used to provide a per-request ACL token. This options overrides
// the agent's default token
Token string `mapstructure:"token"`
// Auth is the information to use for http access to Consul agent
Auth string `mapstructure:"auth"`
// EnableSSL sets the transport scheme to talk to the Consul agent as https
EnableSSL bool `mapstructure:"ssl"`
// VerifySSL enables or disables SSL verification when the transport scheme
// for the consul api client is https
VerifySSL bool `mapstructure:"verify_ssl"`
// CAFile is the path to the ca certificate used for Consul communication
CAFile string `mapstructure:"ca_file"`
// CertFile is the path to the certificate for Consul communication
CertFile string `mapstructure:"cert_file"`
// KeyFile is the path to the private key for Consul communication
KeyFile string `mapstructure:"key_file"`
// ServerAutoJoin enables Nomad servers to find peers by querying Consul and
// joining them
ServerAutoJoin bool `mapstructure:"server_auto_join"`
// ClientAutoJoin enables Nomad servers to find addresses of Nomad servers
// and register with them
ClientAutoJoin bool `mapstructure:"client_auto_join"`
}
// DefaultConsulConfig() returns the canonical defaults for the Nomad
// `consul` configuration.
func DefaultConsulConfig() *ConsulConfig {
return &ConsulConfig{
ServerServiceName: "nomad",
ClientServiceName: "nomad-client",
AutoAdvertise: true,
ServerAutoJoin: true,
ClientAutoJoin: true,
Timeout: 5 * time.Second,
}
}
// Merge merges two Consul Configurations together.
func (a *ConsulConfig) Merge(b *ConsulConfig) *ConsulConfig {
result := *a
if b.ServerServiceName != "" {
result.ServerServiceName = b.ServerServiceName
}
if b.ClientServiceName != "" {
result.ClientServiceName = b.ClientServiceName
}
if b.AutoAdvertise {
result.AutoAdvertise = true
}
if b.Addr != "" {
result.Addr = b.Addr
}
if b.Timeout != 0 {
result.Timeout = b.Timeout
}
if b.Token != "" {
result.Token = b.Token
}
if b.Auth != "" {
result.Auth = b.Auth
}
if b.EnableSSL {
result.EnableSSL = true
}
if b.VerifySSL {
result.VerifySSL = true
}
if b.CAFile != "" {
result.CAFile = b.CAFile
}
if b.CertFile != "" {
result.CertFile = b.CertFile
}
if b.KeyFile != "" {
result.KeyFile = b.KeyFile
}
if b.ServerAutoJoin {
result.ServerAutoJoin = true
}
if b.ClientAutoJoin {
result.ClientAutoJoin = true
}
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) {
config := consul.DefaultConfig()
if c.Addr != "" {
config.Address = c.Addr
}
if c.Token != "" {
config.Token = c.Token
}
if c.Timeout != 0 {
config.HttpClient.Timeout = c.Timeout
}
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 {
config.Scheme = "https"
tlsConfig := consul.TLSConfig{
Address: config.Address,
CAFile: c.CAFile,
CertFile: c.CertFile,
KeyFile: c.KeyFile,
InsecureSkipVerify: !c.VerifySSL,
}
tlsClientCfg, err := consul.SetupTLSConfig(&tlsConfig)
if err != nil {
return nil, fmt.Errorf("error creating tls client config for consul: %v", err)
}
config.HttpClient.Transport = &http.Transport{
TLSClientConfig: tlsClientCfg,
}
}
if c.EnableSSL && !c.VerifySSL {
config.HttpClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}
return config, nil
}