Allow separate HA physical backend.
With no separate backend specified, HA will be attempted on the normal physical backend. Fixes #395.
This commit is contained in:
parent
546b3add9c
commit
ced0835574
|
@ -39,12 +39,13 @@ type ServerCommand struct {
|
|||
}
|
||||
|
||||
func (c *ServerCommand) Run(args []string) int {
|
||||
var dev bool
|
||||
var dev, verifyOnly bool
|
||||
var configPath []string
|
||||
var logLevel string
|
||||
flags := c.Meta.FlagSet("server", FlagSetDefault)
|
||||
flags.BoolVar(&dev, "dev", false, "")
|
||||
flags.StringVar(&logLevel, "log-level", "info", "")
|
||||
flags.BoolVar(&verifyOnly, "verify-only", false, "")
|
||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
flags.Var((*sliceflag.StringFlag)(&configPath), "config", "config")
|
||||
if err := flags.Parse(args); err != nil {
|
||||
|
@ -113,22 +114,47 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
var advertiseAddr string = config.Backend.AdvertiseAddr
|
||||
|
||||
// Note that "habackend" is a backend that *may* support HA;
|
||||
// it defaults to the same backend as normal operations
|
||||
var habackend physical.Backend = backend
|
||||
|
||||
// Initialize the separate HA physical backend, if it exists
|
||||
if config.HABackend != nil {
|
||||
habackend, err = physical.NewBackend(
|
||||
config.HABackend.Type, config.HABackend.Config)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error initializing backend of type %s: %s",
|
||||
config.HABackend.Type, err))
|
||||
return 1
|
||||
}
|
||||
if _, ok := habackend.(physical.HABackend); !ok {
|
||||
c.Ui.Error("Specified HA backend does not support HA")
|
||||
return 1
|
||||
}
|
||||
|
||||
advertiseAddr = config.HABackend.AdvertiseAddr
|
||||
}
|
||||
|
||||
// Attempt to detect the advertise address possible
|
||||
if detect, ok := backend.(physical.AdvertiseDetect); ok && config.Backend.AdvertiseAddr == "" {
|
||||
if detect, ok := habackend.(physical.AdvertiseDetect); ok && advertiseAddr == "" {
|
||||
advertise, err := c.detectAdvertise(detect, config)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error detecting advertise address: %s", err))
|
||||
} else if advertise == "" {
|
||||
c.Ui.Error("Failed to detect advertise address.")
|
||||
} else {
|
||||
config.Backend.AdvertiseAddr = advertise
|
||||
advertiseAddr = advertise
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the core
|
||||
core, err := vault.NewCore(&vault.CoreConfig{
|
||||
AdvertiseAddr: config.Backend.AdvertiseAddr,
|
||||
AdvertiseAddr: advertiseAddr,
|
||||
Physical: backend,
|
||||
HAPhysical: habackend,
|
||||
AuditBackends: c.AuditBackends,
|
||||
CredentialBackends: c.CredentialBackends,
|
||||
LogicalBackends: c.LogicalBackends,
|
||||
|
@ -186,11 +212,17 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
mlock.Supported(), !config.DisableMlock)
|
||||
infoKeys = append(infoKeys, "log level", "mlock", "backend")
|
||||
|
||||
// If the backend supports HA, then note it
|
||||
if _, ok := backend.(physical.HABackend); ok {
|
||||
info["backend"] += " (HA available)"
|
||||
info["advertise address"] = config.Backend.AdvertiseAddr
|
||||
infoKeys = append(infoKeys, "advertise address")
|
||||
if config.HABackend != nil {
|
||||
info["HA backend"] = config.HABackend.Type
|
||||
info["advertise address"] = advertiseAddr
|
||||
infoKeys = append(infoKeys, "HA backend", "advertise address")
|
||||
} else {
|
||||
// If the backend supports HA, then note it
|
||||
if _, ok := habackend.(physical.HABackend); ok {
|
||||
info["backend"] += " (HA available)"
|
||||
info["advertise address"] = advertiseAddr
|
||||
infoKeys = append(infoKeys, "advertise address")
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the telemetry
|
||||
|
@ -225,6 +257,10 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
lns = append(lns, ln)
|
||||
}
|
||||
|
||||
if verifyOnly {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Initialize the HTTP server
|
||||
server := &http.Server{}
|
||||
server.Handler = vaulthttp.Handler(core)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
type Config struct {
|
||||
Listeners []*Listener `hcl:"-"`
|
||||
Backend *Backend `hcl:"-"`
|
||||
HABackend *Backend `hcl:"-"`
|
||||
|
||||
DisableCache bool `hcl:"disable_cache"`
|
||||
DisableMlock bool `hcl:"disable_mlock"`
|
||||
|
@ -191,6 +192,12 @@ func LoadConfigFile(path string) (*Config, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
if objs := obj.Get("ha_backend", false); objs != nil {
|
||||
result.HABackend, err = loadBackend(objs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// A little hacky but upgrades the old stats config directives to the new way
|
||||
if result.Telemetry == nil {
|
||||
|
|
|
@ -30,6 +30,14 @@ func TestLoadConfigFile(t *testing.T) {
|
|||
},
|
||||
},
|
||||
|
||||
HABackend: &Backend{
|
||||
Type: "consul",
|
||||
AdvertiseAddr: "snafu",
|
||||
Config: map[string]string{
|
||||
"bar": "baz",
|
||||
},
|
||||
},
|
||||
|
||||
Telemetry: &Telemetry{
|
||||
StatsdAddr: "bar",
|
||||
StatsiteAddr: "foo",
|
||||
|
@ -111,6 +119,13 @@ func TestLoadConfigFile_json2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
|
||||
HABackend: &Backend{
|
||||
Type: "consul",
|
||||
Config: map[string]string{
|
||||
"bar": "baz",
|
||||
},
|
||||
},
|
||||
|
||||
Telemetry: &Telemetry{
|
||||
StatsiteAddr: "foo",
|
||||
StatsdAddr: "bar",
|
||||
|
|
|
@ -12,5 +12,10 @@ backend "consul" {
|
|||
advertise_addr = "foo"
|
||||
}
|
||||
|
||||
ha_backend "consul" {
|
||||
bar = "baz"
|
||||
advertise_addr = "snafu"
|
||||
}
|
||||
|
||||
max_lease_ttl = "10h"
|
||||
default_lease_ttl = "10h"
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
}
|
||||
},
|
||||
|
||||
"ha_backend": {
|
||||
"consul": {
|
||||
"bar": "baz"
|
||||
}
|
||||
},
|
||||
|
||||
"telemetry": {
|
||||
"statsd_address": "bar",
|
||||
"statsite_address": "foo",
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
basehcl = `
|
||||
disable_mlock = true
|
||||
|
||||
listener "tcp" {
|
||||
address = "127.0.0.1:8200"
|
||||
tls_disable = "true"
|
||||
}
|
||||
`
|
||||
|
||||
consulhcl = `
|
||||
backend "consul" {
|
||||
prefix = "foo/"
|
||||
advertise_addr = "http://127.0.0.1:8200"
|
||||
}
|
||||
`
|
||||
haconsulhcl = `
|
||||
ha_backend "consul" {
|
||||
prefix = "bar/"
|
||||
advertise_addr = "http://127.0.0.1:8200"
|
||||
}
|
||||
`
|
||||
|
||||
badhaconsulhcl = `
|
||||
ha_backend "file" {
|
||||
path = "/dev/null"
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
func TestServer_GoodSeparateHA(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &ServerCommand{
|
||||
Meta: Meta{
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
tmpfile, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating temp dir: %v", err)
|
||||
}
|
||||
|
||||
tmpfile.WriteString(basehcl + consulhcl + haconsulhcl)
|
||||
tmpfile.Close()
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
args := []string{"-config", tmpfile.Name(), "-verify-only", "true"}
|
||||
|
||||
if code := c.Run(args); code != 0 {
|
||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_BadSeparateHA(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &ServerCommand{
|
||||
Meta: Meta{
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
tmpfile, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating temp dir: %v", err)
|
||||
}
|
||||
|
||||
tmpfile.WriteString(basehcl + consulhcl + badhaconsulhcl)
|
||||
tmpfile.Close()
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
args := []string{"-config", tmpfile.Name()}
|
||||
|
||||
if code := c.Run(args); code == 0 {
|
||||
t.Fatalf("bad: should have gotten an error on a bad HA config")
|
||||
}
|
||||
}
|
|
@ -69,9 +69,11 @@ func TestLogical_StandbyRedirect(t *testing.T) {
|
|||
defer ln2.Close()
|
||||
|
||||
// Create an HA Vault
|
||||
inm := physical.NewInmemHA()
|
||||
inm := physical.NewInmem()
|
||||
inmha := physical.NewInmemHA()
|
||||
conf := &vault.CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: addr1,
|
||||
DisableMlock: true,
|
||||
}
|
||||
|
@ -87,6 +89,7 @@ func TestLogical_StandbyRedirect(t *testing.T) {
|
|||
// Create a second HA Vault
|
||||
conf2 := &vault.CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: addr2,
|
||||
DisableMlock: true,
|
||||
}
|
||||
|
|
|
@ -273,20 +273,26 @@ type CoreConfig struct {
|
|||
CredentialBackends map[string]logical.Factory
|
||||
AuditBackends map[string]audit.Factory
|
||||
Physical physical.Backend
|
||||
Logger *log.Logger
|
||||
DisableCache bool // Disables the LRU cache on the physical backend
|
||||
DisableMlock bool // Disables mlock syscall
|
||||
CacheSize int // Custom cache size of zero for default
|
||||
AdvertiseAddr string // Set as the leader address for HA
|
||||
DefaultLeaseTTL time.Duration
|
||||
MaxLeaseTTL time.Duration
|
||||
|
||||
// Defaults to the same backend as Physical. This is not a backend that
|
||||
// necessarily supports HA; it is merely the one that will be attempted
|
||||
// for HA operations
|
||||
HAPhysical physical.Backend
|
||||
|
||||
Logger *log.Logger
|
||||
DisableCache bool // Disables the LRU cache on the physical backend
|
||||
DisableMlock bool // Disables mlock syscall
|
||||
CacheSize int // Custom cache size of zero for default
|
||||
AdvertiseAddr string // Set as the leader address for HA
|
||||
DefaultLeaseTTL time.Duration
|
||||
MaxLeaseTTL time.Duration
|
||||
}
|
||||
|
||||
// NewCore is used to construct a new core
|
||||
func NewCore(conf *CoreConfig) (*Core, error) {
|
||||
// Check if this backend supports an HA configuraiton
|
||||
var haBackend physical.HABackend
|
||||
if ha, ok := conf.Physical.(physical.HABackend); ok {
|
||||
if ha, ok := conf.HAPhysical.(physical.HABackend); ok {
|
||||
haBackend = ha
|
||||
}
|
||||
if haBackend != nil && conf.AdvertiseAddr == "" {
|
||||
|
|
|
@ -1110,10 +1110,12 @@ func TestCore_LimitedUseToken(t *testing.T) {
|
|||
|
||||
func TestCore_CleanLeaderPrefix(t *testing.T) {
|
||||
// Create the first core and initialize it
|
||||
inm := physical.NewInmemHA()
|
||||
inm := physical.NewInmem()
|
||||
inmha := physical.NewInmemHA()
|
||||
advertiseOriginal := "http://127.0.0.1:8200"
|
||||
core, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -1172,6 +1174,7 @@ func TestCore_CleanLeaderPrefix(t *testing.T) {
|
|||
advertiseOriginal2 := "http://127.0.0.1:8500"
|
||||
core2, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal2,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -1256,10 +1259,12 @@ func TestCore_CleanLeaderPrefix(t *testing.T) {
|
|||
|
||||
func TestCore_Standby(t *testing.T) {
|
||||
// Create the first core and initialize it
|
||||
inm := physical.NewInmemHA()
|
||||
inm := physical.NewInmem()
|
||||
inmha := physical.NewInmemHA()
|
||||
advertiseOriginal := "http://127.0.0.1:8200"
|
||||
core, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -1313,6 +1318,7 @@ func TestCore_Standby(t *testing.T) {
|
|||
advertiseOriginal2 := "http://127.0.0.1:8500"
|
||||
core2, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal2,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -2003,10 +2009,12 @@ func testWaitActive(t *testing.T, core *Core) {
|
|||
|
||||
func TestCore_Standby_Rotate(t *testing.T) {
|
||||
// Create the first core and initialize it
|
||||
inm := physical.NewInmemHA()
|
||||
inm := physical.NewInmem()
|
||||
inmha := physical.NewInmemHA()
|
||||
advertiseOriginal := "http://127.0.0.1:8200"
|
||||
core, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -2025,6 +2033,7 @@ func TestCore_Standby_Rotate(t *testing.T) {
|
|||
advertiseOriginal2 := "http://127.0.0.1:8500"
|
||||
core2, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal2,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -2074,10 +2083,12 @@ func TestCore_Standby_Rotate(t *testing.T) {
|
|||
|
||||
func TestCore_Standby_Rekey(t *testing.T) {
|
||||
// Create the first core and initialize it
|
||||
inm := physical.NewInmemHA()
|
||||
inm := physical.NewInmem()
|
||||
inmha := physical.NewInmemHA()
|
||||
advertiseOriginal := "http://127.0.0.1:8200"
|
||||
core, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
@ -2096,6 +2107,7 @@ func TestCore_Standby_Rekey(t *testing.T) {
|
|||
advertiseOriginal2 := "http://127.0.0.1:8500"
|
||||
core2, err := NewCore(&CoreConfig{
|
||||
Physical: inm,
|
||||
HAPhysical: inmha,
|
||||
AdvertiseAddr: advertiseOriginal2,
|
||||
DisableMlock: true,
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue