Various refactoring to clean up code organization
Brought to you by: Dept of 2nd thoughts before pushing enter on `git push`
This commit is contained in:
parent
53f9cea87c
commit
60006f550f
|
@ -203,9 +203,6 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
|
||||
if envAA := os.Getenv("VAULT_ADVERTISE_ADDR"); envAA != "" {
|
||||
coreConfig.AdvertiseAddr = envAA
|
||||
if consulBackend, ok := (backend).(*physical.ConsulBackend); ok {
|
||||
consulBackend.UpdateAdvertiseAddr(envAA)
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to detect the advertise address, if possible
|
||||
|
@ -223,9 +220,6 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
c.Ui.Error("Failed to detect advertise address.")
|
||||
} else {
|
||||
coreConfig.AdvertiseAddr = advertise
|
||||
if consulBackend, ok := (backend).(*physical.ConsulBackend); ok {
|
||||
consulBackend.UpdateAdvertiseAddr(advertise)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,6 +290,11 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
if coreConfig.HAPhysical != nil {
|
||||
sd, ok := coreConfig.HAPhysical.(physical.ServiceDiscovery)
|
||||
if ok {
|
||||
if err := sd.UpdateAdvertiseAddr(coreConfig.AdvertiseAddr); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error configuring service discovery: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := sd.RunServiceDiscovery(c.ShutdownCh); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing service discovery: %v", err))
|
||||
return 1
|
||||
|
|
|
@ -44,21 +44,23 @@ const (
|
|||
// prefix within Consul. It is used for most production situations as
|
||||
// it allows Vault to run on multiple machines in a highly-available manner.
|
||||
type ConsulBackend struct {
|
||||
path string
|
||||
client *api.Client
|
||||
kv *api.KV
|
||||
permitPool *PermitPool
|
||||
serviceLock sync.RWMutex
|
||||
service *api.AgentServiceRegistration
|
||||
sealedCheck *api.AgentCheckRegistration
|
||||
advertiseAddr string
|
||||
consulClientConf *api.Config
|
||||
serviceName string
|
||||
running bool
|
||||
active bool
|
||||
sealed bool
|
||||
checkTimeout time.Duration
|
||||
checkTimer *time.Timer
|
||||
path string
|
||||
client *api.Client
|
||||
kv *api.KV
|
||||
permitPool *PermitPool
|
||||
serviceLock sync.RWMutex
|
||||
service *api.AgentServiceRegistration
|
||||
sealedCheck *api.AgentCheckRegistration
|
||||
advertiseHost string
|
||||
advertisePort int
|
||||
consulClientConf *api.Config
|
||||
serviceName string
|
||||
running bool
|
||||
active bool
|
||||
sealed bool
|
||||
disableRegistration bool
|
||||
checkTimeout time.Duration
|
||||
checkTimer *time.Timer
|
||||
}
|
||||
|
||||
// newConsulBackend constructs a Consul backend using the given API client
|
||||
|
@ -78,6 +80,17 @@ func newConsulBackend(conf map[string]string) (Backend, error) {
|
|||
path = strings.TrimPrefix(path, "/")
|
||||
}
|
||||
|
||||
// Allow admins to disable consul integration
|
||||
disableReg, ok := conf["disable_registration"]
|
||||
var disableRegistration bool
|
||||
if ok && disableReg != "" {
|
||||
b, err := strconv.ParseBool(disableReg)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed parsing disable_registration parameter: {{err}}", err)
|
||||
}
|
||||
disableRegistration = b
|
||||
}
|
||||
|
||||
// Get the service name to advertise in Consul
|
||||
service, ok := conf["service"]
|
||||
if !ok {
|
||||
|
@ -141,14 +154,15 @@ func newConsulBackend(conf map[string]string) (Backend, error) {
|
|||
|
||||
// Setup the backend
|
||||
c := &ConsulBackend{
|
||||
path: path,
|
||||
client: client,
|
||||
kv: client.KV(),
|
||||
permitPool: NewPermitPool(maxParInt),
|
||||
consulClientConf: consulConf,
|
||||
serviceName: service,
|
||||
checkTimeout: checkTimeout,
|
||||
checkTimer: time.NewTimer(checkTimeout),
|
||||
path: path,
|
||||
client: client,
|
||||
kv: client.KV(),
|
||||
permitPool: NewPermitPool(maxParInt),
|
||||
consulClientConf: consulConf,
|
||||
serviceName: service,
|
||||
checkTimeout: checkTimeout,
|
||||
checkTimer: time.NewTimer(checkTimeout),
|
||||
disableRegistration: disableRegistration,
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
@ -160,21 +174,13 @@ func (c *ConsulBackend) UpdateAdvertiseAddr(addr string) error {
|
|||
return fmt.Errorf("service registration unable to update advertise address, backend already running")
|
||||
}
|
||||
|
||||
url, err := url.Parse(addr)
|
||||
host, port, err := parseAdvertiseAddr(addr)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf(`updating advertise address failed to parse URL "%v": {{err}}`, addr), err)
|
||||
return errwrap.Wrapf(fmt.Sprintf(`failed to parse advertise address "%v": {{err}}`, addr), err)
|
||||
}
|
||||
|
||||
_, portStr, err := net.SplitHostPort(url.Host)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf(`updating advertise address failed to find a host:port in advertise address "%v": {{err}}`, url.Host), err)
|
||||
}
|
||||
_, err = strconv.ParseInt(portStr, 10, 0)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf(`updating advertise address failed to parse port "%v": {{err}}`, portStr), err)
|
||||
}
|
||||
|
||||
c.advertiseAddr = addr
|
||||
c.advertiseHost = host
|
||||
c.advertisePort = int(port)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -197,10 +203,12 @@ func (c *ConsulBackend) AdvertiseActive(active bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
c.service.Tags = serviceTags(active)
|
||||
agent := c.client.Agent()
|
||||
if err := agent.ServiceRegister(c.service); err != nil {
|
||||
return errwrap.Wrapf("service registration failed: {{err}}", err)
|
||||
if !c.disableRegistration {
|
||||
c.service.Tags = serviceTags(active)
|
||||
agent := c.client.Agent()
|
||||
if err := agent.ServiceRegister(c.service); err != nil {
|
||||
return errwrap.Wrapf("service registration failed: {{err}}", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Save a cached copy of the active state: no way to query Core
|
||||
|
@ -219,8 +227,10 @@ func (c *ConsulBackend) AdvertiseSealed(sealed bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Push a TTL check immediately to update the state
|
||||
c.runCheck()
|
||||
if !c.disableRegistration {
|
||||
// Push a TTL check immediately to update the state
|
||||
c.runCheck()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -229,35 +239,22 @@ func (c *ConsulBackend) RunServiceDiscovery(shutdownCh ShutdownChannel) (err err
|
|||
c.serviceLock.Lock()
|
||||
defer c.serviceLock.Unlock()
|
||||
|
||||
if c.disableRegistration {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.running {
|
||||
return fmt.Errorf("service registration routine already running")
|
||||
}
|
||||
|
||||
url, err := url.Parse(c.advertiseAddr)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf(`service registration failed to parse URL "%v": {{err}}`, c.advertiseAddr), err)
|
||||
}
|
||||
|
||||
host, portStr, err := net.SplitHostPort(url.Host)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf(`service registration failed to find a host:port in advertise address "%v": {{err}}`, url.Host), err)
|
||||
}
|
||||
port, err := strconv.ParseInt(portStr, 10, 0)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf(fmt.Sprintf(`service registration failed to parse port "%v": {{err}}`, portStr), err)
|
||||
}
|
||||
|
||||
serviceID, err := c.serviceID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serviceID := c.serviceID()
|
||||
|
||||
c.service = &api.AgentServiceRegistration{
|
||||
ID: serviceID,
|
||||
Name: c.serviceName,
|
||||
Tags: serviceTags(c.active),
|
||||
Port: int(port),
|
||||
Address: host,
|
||||
Port: c.advertisePort,
|
||||
Address: c.advertiseHost,
|
||||
EnableTagOverride: false,
|
||||
}
|
||||
|
||||
|
@ -351,22 +348,31 @@ func (c *ConsulBackend) checkID() string {
|
|||
|
||||
// serviceID returns the Vault ServiceID for use in Consul. Assume at least
|
||||
// a read lock is held.
|
||||
func (c *ConsulBackend) serviceID() (string, error) {
|
||||
url, err := url.Parse(c.advertiseAddr)
|
||||
if err != nil {
|
||||
return "", errwrap.Wrapf(fmt.Sprintf(`service registration failed to parse URL "%v": {{err}}`, c.advertiseAddr), err)
|
||||
func (c *ConsulBackend) serviceID() string {
|
||||
return fmt.Sprintf("%s:%s:%d", c.serviceName, c.advertiseHost, c.advertisePort)
|
||||
}
|
||||
|
||||
func parseAdvertiseAddr(addr string) (host string, port int, err error) {
|
||||
if addr == "" {
|
||||
return "", -1, fmt.Errorf("advertise address must not be empty")
|
||||
}
|
||||
|
||||
host, portStr, err := net.SplitHostPort(url.Host)
|
||||
url, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return "", errwrap.Wrapf(fmt.Sprintf(`service registration failed to find a host:port in advertise address "%v": {{err}}`, url.Host), err)
|
||||
}
|
||||
port, err := strconv.ParseInt(portStr, 10, 0)
|
||||
if err != nil {
|
||||
return "", errwrap.Wrapf(fmt.Sprintf(`service registration failed to parse port "%v": {{err}}`, portStr), err)
|
||||
return "", -2, errwrap.Wrapf(fmt.Sprintf(`failed to parse advertise URL "%v": {{err}}`, addr), err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s:%s:%d", c.serviceName, host, int(port)), nil
|
||||
var portStr string
|
||||
host, portStr, err = net.SplitHostPort(url.Host)
|
||||
if err != nil {
|
||||
return "", -3, errwrap.Wrapf(fmt.Sprintf(`failed to find a host:port in advertise address "%v": {{err}}`, url.Host), err)
|
||||
}
|
||||
portNum, err := strconv.ParseInt(portStr, 10, 0)
|
||||
if err != nil || portNum < 1 || portNum > 65535 {
|
||||
return "", -4, errwrap.Wrapf(fmt.Sprintf(`failed to parse valid port "%v": {{err}}`, portStr), err)
|
||||
}
|
||||
|
||||
return host, int(portNum), nil
|
||||
}
|
||||
|
||||
func setupTLSConfig(conf map[string]string) (*tls.Config, error) {
|
||||
|
|
|
@ -86,67 +86,81 @@ func testConsul_testConsulBackend(t *testing.T) {
|
|||
|
||||
func TestConsul_newConsulBackend(t *testing.T) {
|
||||
tests := []struct {
|
||||
Name string
|
||||
Config map[string]string
|
||||
Fail bool
|
||||
checkTimeout time.Duration
|
||||
path string
|
||||
service string
|
||||
address string
|
||||
scheme string
|
||||
token string
|
||||
max_parallel int
|
||||
name string
|
||||
consulConfig map[string]string
|
||||
fail bool
|
||||
advertiseAddr string
|
||||
checkTimeout time.Duration
|
||||
path string
|
||||
service string
|
||||
address string
|
||||
scheme string
|
||||
token string
|
||||
max_parallel int
|
||||
disableReg bool
|
||||
}{
|
||||
{
|
||||
Name: "Valid default config",
|
||||
Config: map[string]string{},
|
||||
checkTimeout: 5 * time.Second,
|
||||
path: "vault",
|
||||
service: "vault",
|
||||
address: "127.0.0.1",
|
||||
scheme: "http",
|
||||
token: "",
|
||||
max_parallel: 4,
|
||||
name: "Valid default config",
|
||||
consulConfig: map[string]string{},
|
||||
checkTimeout: 5 * time.Second,
|
||||
advertiseAddr: "http://127.0.0.1:8200",
|
||||
path: "vault/",
|
||||
service: "vault",
|
||||
address: "127.0.0.1:8500",
|
||||
scheme: "http",
|
||||
token: "",
|
||||
max_parallel: 4,
|
||||
disableReg: false,
|
||||
},
|
||||
{
|
||||
Name: "Valid modified config",
|
||||
Config: map[string]string{
|
||||
"path": "seaTech/",
|
||||
"service": "astronomy",
|
||||
"check_timeout": "6s",
|
||||
"address": "127.0.0.2",
|
||||
"scheme": "https",
|
||||
"token": "deadbeef-cafeefac-deadc0de-feedface",
|
||||
"max_parallel": "4",
|
||||
name: "Valid modified config",
|
||||
consulConfig: map[string]string{
|
||||
"path": "seaTech/",
|
||||
"service": "astronomy",
|
||||
"advertiseAddr": "http://127.0.0.2:8200",
|
||||
"check_timeout": "6s",
|
||||
"address": "127.0.0.2",
|
||||
"scheme": "https",
|
||||
"token": "deadbeef-cafeefac-deadc0de-feedface",
|
||||
"max_parallel": "4",
|
||||
"disable_registration": "false",
|
||||
},
|
||||
checkTimeout: 6 * time.Second,
|
||||
path: "seaTech/",
|
||||
service: "astronomy",
|
||||
address: "127.0.0.2",
|
||||
scheme: "https",
|
||||
token: "deadbeef-cafeefac-deadc0de-feedface",
|
||||
max_parallel: 4,
|
||||
checkTimeout: 6 * time.Second,
|
||||
path: "seaTech/",
|
||||
service: "astronomy",
|
||||
advertiseAddr: "http://127.0.0.2:8200",
|
||||
address: "127.0.0.2",
|
||||
scheme: "https",
|
||||
token: "deadbeef-cafeefac-deadc0de-feedface",
|
||||
max_parallel: 4,
|
||||
},
|
||||
{
|
||||
Name: "check timeout too short",
|
||||
Fail: true,
|
||||
Config: map[string]string{
|
||||
name: "check timeout too short",
|
||||
fail: true,
|
||||
consulConfig: map[string]string{
|
||||
"check_timeout": "99ms",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
be, err := newConsulBackend(test.Config)
|
||||
if test.Fail && err == nil {
|
||||
t.Fatalf("Expected config %s to fail", test.Name)
|
||||
} else if !test.Fail && err != nil {
|
||||
t.Fatalf("Expected config %s to not fail: %v", test.Name, err)
|
||||
be, err := newConsulBackend(test.consulConfig)
|
||||
if test.fail {
|
||||
if err == nil {
|
||||
t.Fatalf(`Expected config "%s" to fail`, test.name)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else if !test.fail && err != nil {
|
||||
t.Fatalf("Expected config %s to not fail: %v", test.name, err)
|
||||
}
|
||||
|
||||
c, ok := be.(*ConsulBackend)
|
||||
if !ok {
|
||||
t.Fatalf("Expected ConsulBackend")
|
||||
t.Fatalf("Expected ConsulBackend: %s", test.name)
|
||||
}
|
||||
if err := c.UpdateAdvertiseAddr(test.advertiseAddr); err != nil {
|
||||
t.Fatalf("bad: %v", err)
|
||||
}
|
||||
|
||||
if test.checkTimeout != c.checkTimeout {
|
||||
|
@ -154,7 +168,7 @@ func TestConsul_newConsulBackend(t *testing.T) {
|
|||
}
|
||||
|
||||
if test.path != c.path {
|
||||
t.Errorf("bad: %v != %v", test.path, c.path)
|
||||
t.Errorf("bad: %s %v != %v", test.name, test.path, c.path)
|
||||
}
|
||||
|
||||
if test.service != c.serviceName {
|
||||
|
@ -162,7 +176,7 @@ func TestConsul_newConsulBackend(t *testing.T) {
|
|||
}
|
||||
|
||||
if test.address != c.consulClientConf.Address {
|
||||
t.Errorf("bad: %v != %v", test.address, c.consulClientConf.Address)
|
||||
t.Errorf("bad: %s %v != %v", test.name, test.address, c.consulClientConf.Address)
|
||||
}
|
||||
|
||||
if test.scheme != c.consulClientConf.Scheme {
|
||||
|
@ -206,14 +220,20 @@ func TestConsul_serviceTags(t *testing.T) {
|
|||
func TestConsul_UpdateAdvertiseAddr(t *testing.T) {
|
||||
tests := []struct {
|
||||
addr string
|
||||
host string
|
||||
port int
|
||||
pass bool
|
||||
}{
|
||||
{
|
||||
addr: "http://127.0.0.1:8200/",
|
||||
host: "127.0.0.1",
|
||||
port: 8200,
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
addr: "http://127.0.0.1:8200",
|
||||
host: "127.0.0.1",
|
||||
port: 8200,
|
||||
pass: true,
|
||||
},
|
||||
{
|
||||
|
@ -244,8 +264,12 @@ func TestConsul_UpdateAdvertiseAddr(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
if c.advertiseAddr != test.addr {
|
||||
t.Fatalf("bad: %v != %v", c.advertiseAddr, test.addr)
|
||||
if c.advertiseHost != test.host {
|
||||
t.Fatalf("bad: %v != %v", c.advertiseHost, test.host)
|
||||
}
|
||||
|
||||
if c.advertisePort != test.port {
|
||||
t.Fatalf("bad: %v != %v", c.advertisePort, test.port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -330,21 +354,25 @@ func TestConsul_checkID(t *testing.T) {
|
|||
|
||||
func TestConsul_serviceID(t *testing.T) {
|
||||
passingTests := []struct {
|
||||
name string
|
||||
advertiseAddr string
|
||||
serviceName string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "valid host w/o slash",
|
||||
advertiseAddr: "http://127.0.0.1:8200",
|
||||
serviceName: "sea-tech-astronomy",
|
||||
expected: "sea-tech-astronomy:127.0.0.1:8200",
|
||||
},
|
||||
{
|
||||
name: "valid host w/ slash",
|
||||
advertiseAddr: "http://127.0.0.1:8200/",
|
||||
serviceName: "sea-tech-astronomy",
|
||||
expected: "sea-tech-astronomy:127.0.0.1:8200",
|
||||
},
|
||||
{
|
||||
name: "valid https host w/ slash",
|
||||
advertiseAddr: "https://127.0.0.1:8200/",
|
||||
serviceName: "sea-tech-astronomy",
|
||||
expected: "sea-tech-astronomy:127.0.0.1:8200",
|
||||
|
@ -357,14 +385,10 @@ func TestConsul_serviceID(t *testing.T) {
|
|||
})
|
||||
|
||||
if err := c.UpdateAdvertiseAddr(test.advertiseAddr); err != nil {
|
||||
t.Fatalf("bad: %v", err)
|
||||
}
|
||||
|
||||
serviceID, err := c.serviceID()
|
||||
if err != nil {
|
||||
t.Fatalf("bad: %v", err)
|
||||
t.Fatalf("bad: %s %v", test.name, err)
|
||||
}
|
||||
|
||||
serviceID := c.serviceID()
|
||||
if serviceID != test.expected {
|
||||
t.Fatalf("bad: %v != %v", serviceID, test.expected)
|
||||
}
|
||||
|
|
|
@ -43,11 +43,6 @@ type HABackend interface {
|
|||
type AdvertiseDetect interface {
|
||||
// DetectHostAddr is used to detect the host address
|
||||
DetectHostAddr() (string, error)
|
||||
|
||||
// UpdateAdvertiseAddr allows for a non-Running backend to update the
|
||||
// advertise address. HABackends may want to present a different
|
||||
// address that wasn't available when a Backend was created.
|
||||
UpdateAdvertiseAddr(addr string) error
|
||||
}
|
||||
|
||||
// ServiceDiscovery is an optional interface that an HABackend can implement.
|
||||
|
@ -65,6 +60,11 @@ type ServiceDiscovery interface {
|
|||
// Run executes any background service discovery tasks until the
|
||||
// shutdown channel is closed.
|
||||
RunServiceDiscovery(ShutdownChannel) error
|
||||
|
||||
// UpdateAdvertiseAddr allows for a non-Running backend to update the
|
||||
// advertise address. HABackends may want to present a different
|
||||
// address that wasn't available when a Backend was created.
|
||||
UpdateAdvertiseAddr(addr string) error
|
||||
}
|
||||
|
||||
type Lock interface {
|
||||
|
|
|
@ -200,6 +200,9 @@ For Consul, the following options are supported:
|
|||
|
||||
* `scheme` (optional) - "http" or "https" for talking to Consul.
|
||||
|
||||
* `disable_registration` (optional) - If true, then Vault will not register
|
||||
itself with Vault. Defaults to "false".
|
||||
|
||||
* `token` (optional) - An access token to use to write data to Consul.
|
||||
|
||||
* `max_parallel` (optional) - The maximum number of connections to Consul;
|
||||
|
|
Loading…
Reference in New Issue