From 55cf44bc91039ea94785bd125a5879e4901fad90 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 02:25:33 -0400 Subject: [PATCH 1/7] Storing local and global cluster name/id to storage and returning them in health status --- command/server.go | 4 ++ command/server/config.go | 10 +++ http/sys_health.go | 54 +++++++++++++--- http/sys_health_test.go | 16 +++++ http/sys_seal_test.go | 2 - vault/cluster.go | 135 +++++++++++++++++++++++++++++++++++++++ vault/cluster_test.go | 22 +++++++ vault/core.go | 86 ++++++++++++++++++------- 8 files changed, 293 insertions(+), 36 deletions(-) create mode 100644 vault/cluster.go create mode 100644 vault/cluster_test.go diff --git a/command/server.go b/command/server.go index 39a1f1753e..0275104420 100644 --- a/command/server.go +++ b/command/server.go @@ -187,6 +187,10 @@ func (c *ServerCommand) Run(args []string) int { DisableMlock: config.DisableMlock, MaxLeaseTTL: config.MaxLeaseTTL, DefaultLeaseTTL: config.DefaultLeaseTTL, + LocalClusterName: config.LocalClusterName, + LocalClusterID: config.LocalClusterID, + GlobalClusterName: config.GlobalClusterName, + GlobalClusterID: config.GlobalClusterID, } // Initialize the separate HA physical backend, if it exists diff --git a/command/server/config.go b/command/server/config.go index 5eef8abb6b..0943e038d2 100644 --- a/command/server/config.go +++ b/command/server/config.go @@ -33,6 +33,12 @@ type Config struct { MaxLeaseTTLRaw string `hcl:"max_lease_ttl"` DefaultLeaseTTL time.Duration `hcl:"-"` DefaultLeaseTTLRaw string `hcl:"default_lease_ttl"` + + LocalClusterName string `hcl:"local_cluster_name"` + LocalClusterID string `hcl:"local_cluster_id"` + + GlobalClusterName string `hcl:"global_cluster_name"` + GlobalClusterID string `hcl:"global_cluster_id"` } // DevConfig is a Config that is used for dev mode of Vault. @@ -277,6 +283,10 @@ func ParseConfig(d string) (*Config, error) { "telemetry", "default_lease_ttl", "max_lease_ttl", + "local_cluster_name", + "local_cluster_id", + "global_cluster_name", + "global_cluster_id", // TODO: Remove in 0.6.0 // Deprecated keys diff --git a/http/sys_health.go b/http/sys_health.go index 440985305f..df046ddf04 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -114,21 +114,55 @@ func getSysHealth(core *vault.Core, r *http.Request) (int, *HealthResponse, erro code = standbyCode } + // Fetch the local cluster name and identifier + var localClusterName, localClusterID string + localCluster, err := core.Cluster(true) + + // Don't set the cluster details in the health status when Vault is sealed + if err != nil && err.Error() != "Vault is sealed" { + return http.StatusInternalServerError, nil, err + } + if localCluster != nil { + localClusterName = localCluster.Name + localClusterID = localCluster.ID + } + + // Fetch the global cluster name and identifier + var globalClusterName, globalClusterID string + globalCluster, err := core.Cluster(false) + + // Don't set the cluster details in the health status when Vault is sealed + if err != nil && err.Error() != "Vault is sealed" { + return http.StatusInternalServerError, nil, err + } + if globalCluster != nil { + globalClusterName = globalCluster.Name + globalClusterID = globalCluster.ID + } + // Format the body body := &HealthResponse{ - Initialized: init, - Sealed: sealed, - Standby: standby, - ServerTimeUTC: time.Now().UTC().Unix(), - Version: version.GetVersion().String(), + Initialized: init, + Sealed: sealed, + Standby: standby, + ServerTimeUTC: time.Now().UTC().Unix(), + Version: version.GetVersion().String(), + LocalClusterName: localClusterName, + LocalClusterID: localClusterID, + GlobalClusterName: globalClusterName, + GlobalClusterID: globalClusterID, } return code, body, nil } type HealthResponse struct { - Initialized bool `json:"initialized"` - Sealed bool `json:"sealed"` - Standby bool `json:"standby"` - ServerTimeUTC int64 `json:"server_time_utc"` - Version string `json:"version"` + Initialized bool `json:"initialized"` + Sealed bool `json:"sealed"` + Standby bool `json:"standby"` + ServerTimeUTC int64 `json:"server_time_utc"` + Version string `json:"version"` + LocalClusterName string `json:"local_cluster_name"` + LocalClusterID string `json:"local_cluster_id"` + GlobalClusterName string `json:"global_cluster_name"` + GlobalClusterID string `json:"global_cluster_id"` } diff --git a/http/sys_health_test.go b/http/sys_health_test.go index 711acdf021..a27254083f 100644 --- a/http/sys_health_test.go +++ b/http/sys_health_test.go @@ -31,6 +31,10 @@ func TestSysHealth_get(t *testing.T) { testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] + expected["local_cluster_name"] = actual["local_cluster_name"] + expected["local_cluster_id"] = actual["local_cluster_id"] + expected["global_cluster_name"] = actual["global_cluster_name"] + expected["global_cluster_id"] = actual["global_cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } @@ -52,6 +56,10 @@ func TestSysHealth_get(t *testing.T) { testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] + expected["local_cluster_name"] = actual["local_cluster_name"] + expected["local_cluster_id"] = actual["local_cluster_id"] + expected["global_cluster_name"] = actual["global_cluster_name"] + expected["global_cluster_id"] = actual["global_cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } @@ -82,6 +90,10 @@ func TestSysHealth_customcodes(t *testing.T) { expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] + expected["local_cluster_name"] = actual["local_cluster_name"] + expected["local_cluster_id"] = actual["local_cluster_id"] + expected["global_cluster_name"] = actual["global_cluster_name"] + expected["global_cluster_id"] = actual["global_cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } @@ -107,6 +119,10 @@ func TestSysHealth_customcodes(t *testing.T) { testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] + expected["local_cluster_name"] = actual["local_cluster_name"] + expected["local_cluster_id"] = actual["local_cluster_id"] + expected["global_cluster_name"] = actual["global_cluster_name"] + expected["global_cluster_id"] = actual["global_cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } diff --git a/http/sys_seal_test.go b/http/sys_seal_test.go index 6c702a3ec4..bc044c918f 100644 --- a/http/sys_seal_test.go +++ b/http/sys_seal_test.go @@ -3,7 +3,6 @@ package http import ( "encoding/hex" "encoding/json" - "log" "net/http" "reflect" "strconv" @@ -173,7 +172,6 @@ func TestSysUnseal_Reset(t *testing.T) { if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected:\n%#v\nactual:\n%#v\n", expected, actual) } - log.Printf("reached here\n") } resp = testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ diff --git a/vault/cluster.go b/vault/cluster.go new file mode 100644 index 0000000000..c838a747d8 --- /dev/null +++ b/vault/cluster.go @@ -0,0 +1,135 @@ +package vault + +import ( + "encoding/json" + "fmt" + + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/vault/helper/jsonutil" +) + +const ( + // Storage path where the local cluster name and identifier are stored + coreClusterLocalPath = "core/cluster/local" + + // Storage path where the global cluster name and identifier are stored + coreClusterGlobalPath = "core/cluster/global" +) + +// Structure representing the storage entry that holds cluster information +type Cluster struct { + // Name of the cluster + Name string `json:"name" structs:"name" mapstructure:"name"` + + // Identifier of the cluster + ID string `json:"id" structs:"id" mapstructure:"id"` +} + +// Cluster fetches the details of either local or global cluster based on the +// input. This method errors out when Vault is sealed. +func (c *Core) Cluster(isLocal bool) (*Cluster, error) { + var key string + if isLocal { + key = coreClusterLocalPath + } else { + key = coreClusterGlobalPath + } + + // Fetch the storage entry. This call fails when Vault is sealed. + entry, err := c.barrier.Get(key) + if err != nil { + return nil, err + } + if entry == nil { + return nil, nil + } + + // Decode the cluster information + var cluster Cluster + if err = jsonutil.DecodeJSON(entry.Value, &cluster); err != nil { + return nil, fmt.Errorf("failed to decode cluster details: %v", err) + } + + return &cluster, nil +} + +// setupCluster creates storage entries for holding Vault cluster information. +// Entries will be created only if they are not already present. +func (c *Core) setupCluster() error { + // Create or store a local name and local cluster ID, if not already stored + if err := c.setCluster(true, c.localClusterName, c.localClusterID); err != nil { + return err + } + + // Create or store a global name and global cluster ID, if not already stored + if err := c.setCluster(false, c.globalClusterName, c.globalClusterID); err != nil { + return err + } + return nil +} + +// setCluster creates a local or global storage index for a set of cluster +// information. If cluster name or cluster ID is not supplied, this method will +// auto-generate them respectively. +func (c *Core) setCluster(isLocal bool, clusterName, clusterID string) error { + // Check if storage index is already present or not + cluster, err := c.Cluster(isLocal) + if err != nil { + c.logger.Printf("[ERR] core: failed to get cluster details: %v", err) + return err + } + if cluster != nil { + // If index is already present, don't update it + return nil + } + + // If clusterName is not supplied, generate one + if clusterName == "" { + clusterNameBytes, err := uuid.GenerateRandomBytes(4) + if err != nil { + c.logger.Printf("[ERR] core: failed to generate cluster name: %v", err) + return err + } + prefix := "vault-" + if isLocal { + prefix += "local-" + } else { + prefix += "global-" + } + clusterName = fmt.Sprintf("%s%08x", prefix, clusterNameBytes) + } + + // If clusterName is not supplied, generate one + if clusterID == "" { + var err error + clusterID, err = uuid.GenerateUUID() + if err != nil { + c.logger.Printf("[ERR] core: failed to generate cluster identifier: %v", err) + return err + } + } + + // Encode the cluster information into as a JSON string + rawCluster, err := json.Marshal(&Cluster{ + Name: clusterName, + ID: clusterID, + }) + if err != nil { + c.logger.Printf("[ERR] core: failed to encode cluster details: %v", err) + return err + } + + // Determine the storage path + var key string + if isLocal { + key = coreClusterLocalPath + } else { + key = coreClusterGlobalPath + } + + // Store it + return c.barrier.Put(&Entry{ + Key: key, + Value: rawCluster, + }) +} diff --git a/vault/cluster_test.go b/vault/cluster_test.go new file mode 100644 index 0000000000..c2c63b1f1b --- /dev/null +++ b/vault/cluster_test.go @@ -0,0 +1,22 @@ +package vault + +import "testing" + +func TestCluster(t *testing.T) { + c, _, _ := TestCoreUnsealed(t) + cluster, err := c.Cluster(true) + if err != nil { + t.Fatal(err) + } + if cluster == nil || cluster.Name == "" || cluster.ID == "" { + t.Fatalf("local cluster information missing: cluster:%#v", cluster) + } + + cluster, err = c.Cluster(false) + if err != nil { + t.Fatal(err) + } + if cluster == nil || cluster.Name == "" || cluster.ID == "" { + t.Fatalf("global cluster information missing: cluster:%#v", cluster) + } +} diff --git a/vault/core.go b/vault/core.go index 0dc6d6edb7..a57aa463a6 100644 --- a/vault/core.go +++ b/vault/core.go @@ -218,23 +218,54 @@ type Core struct { // cachingDisabled indicates whether caches are disabled cachingDisabled bool + + localClusterName string + localClusterID string + + globalClusterName string + globalClusterID string } // CoreConfig is used to parameterize a core type CoreConfig struct { - LogicalBackends map[string]logical.Factory - CredentialBackends map[string]logical.Factory - AuditBackends map[string]audit.Factory - Physical physical.Backend - HAPhysical physical.HABackend // May be nil, which disables HA operations - Seal Seal - 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 + LogicalBackends map[string]logical.Factory `json:"logical_backends" structs:"logical_backends" mapstructure:"logical_backends"` + + CredentialBackends map[string]logical.Factory `json:"credential_backends" structs:"credential_backends" mapstructure:"credential_backends"` + + AuditBackends map[string]audit.Factory `json:"audit_backends" structs:"audit_backends" mapstructure:"audit_backends"` + + Physical physical.Backend `json:"physical" structs:"physical" mapstructure:"physical"` + + // May be nil, which disables HA operations + HAPhysical physical.HABackend `json:"ha_physical" structs:"ha_physical" mapstructure:"ha_physical"` + + Seal Seal `json:"seal" structs:"seal" mapstructure:"seal"` + + Logger *log.Logger `json:"logger" structs:"logger" mapstructure:"logger"` + + // Disables the LRU cache on the physical backend + DisableCache bool `json:"disable_cache" structs:"disable_cache" mapstructure:"disable_cache"` + + // Disables mlock syscall + DisableMlock bool `json:"disable_mlock" structs:"disable_mlock" mapstructure:"disable_mlock"` + + // Custom cache size of zero for default + CacheSize int `json:"cache_size" structs:"cache_size" mapstructure:"cache_size"` + + // Set as the leader address for HA + AdvertiseAddr string `json:"advertise_addr" structs:"advertise_addr" mapstructure:"advertise_addr"` + + DefaultLeaseTTL time.Duration `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` + + MaxLeaseTTL time.Duration `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` + + LocalClusterName string `json:"local_cluster_name" structs:"local_cluster_name" mapstructure:"local_cluster_name"` + + LocalClusterID string `json:"local_cluster_id" structs:"local_cluster_id" mapstructure:"local_cluster_id"` + + GlobalClusterName string `json:"global_cluster_name" structs:"global_cluster_name" mapstructure:"global_cluster_name"` + + GlobalClusterID string `json:"global_cluster_id" structs:"global_cluster_id" mapstructure:"global_cluster_id"` } // NewCore is used to construct a new core @@ -304,17 +335,21 @@ func NewCore(conf *CoreConfig) (*Core, error) { // Setup the core c := &Core{ - advertiseAddr: conf.AdvertiseAddr, - physical: conf.Physical, - seal: conf.Seal, - barrier: barrier, - router: NewRouter(), - sealed: true, - standby: true, - logger: conf.Logger, - defaultLeaseTTL: conf.DefaultLeaseTTL, - maxLeaseTTL: conf.MaxLeaseTTL, - cachingDisabled: conf.DisableCache, + advertiseAddr: conf.AdvertiseAddr, + physical: conf.Physical, + seal: conf.Seal, + barrier: barrier, + router: NewRouter(), + sealed: true, + standby: true, + logger: conf.Logger, + defaultLeaseTTL: conf.DefaultLeaseTTL, + maxLeaseTTL: conf.MaxLeaseTTL, + cachingDisabled: conf.DisableCache, + localClusterName: conf.LocalClusterName, + localClusterID: conf.LocalClusterID, + globalClusterName: conf.GlobalClusterName, + globalClusterID: conf.GlobalClusterID, } if conf.HAPhysical != nil && conf.HAPhysical.HAEnabled() { @@ -970,6 +1005,9 @@ func (c *Core) postUnseal() (retErr error) { if err := c.setupAudits(); err != nil { return err } + if err := c.setupCluster(); err != nil { + return err + } c.metricsCh = make(chan struct{}) go c.emitMetrics(c.metricsCh) c.logger.Printf("[INFO] core: post-unseal setup complete") From bae3e090711c664215932aee6444a2a2387814e8 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 09:18:38 -0400 Subject: [PATCH 2/7] As it is --- vault/cluster.go | 76 ++++++++++++------------------------------------ 1 file changed, 18 insertions(+), 58 deletions(-) diff --git a/vault/cluster.go b/vault/cluster.go index c838a747d8..c01bba058a 100644 --- a/vault/cluster.go +++ b/vault/cluster.go @@ -10,10 +10,7 @@ import ( const ( // Storage path where the local cluster name and identifier are stored - coreClusterLocalPath = "core/cluster/local" - - // Storage path where the global cluster name and identifier are stored - coreClusterGlobalPath = "core/cluster/global" + coreClusterPath = "core/cluster/local" ) // Structure representing the storage entry that holds cluster information @@ -27,16 +24,9 @@ type Cluster struct { // Cluster fetches the details of either local or global cluster based on the // input. This method errors out when Vault is sealed. -func (c *Core) Cluster(isLocal bool) (*Cluster, error) { - var key string - if isLocal { - key = coreClusterLocalPath - } else { - key = coreClusterGlobalPath - } - +func (c *Core) Cluster() (*Cluster, error) { // Fetch the storage entry. This call fails when Vault is sealed. - entry, err := c.barrier.Get(key) + entry, err := c.barrier.Get(coreClusterPath) if err != nil { return nil, err } @@ -54,26 +44,11 @@ func (c *Core) Cluster(isLocal bool) (*Cluster, error) { } // setupCluster creates storage entries for holding Vault cluster information. -// Entries will be created only if they are not already present. +// Entries will be created only if they are not already present. If clusterName +// is not supplied, this method will auto-generate it. func (c *Core) setupCluster() error { - // Create or store a local name and local cluster ID, if not already stored - if err := c.setCluster(true, c.localClusterName, c.localClusterID); err != nil { - return err - } - - // Create or store a global name and global cluster ID, if not already stored - if err := c.setCluster(false, c.globalClusterName, c.globalClusterID); err != nil { - return err - } - return nil -} - -// setCluster creates a local or global storage index for a set of cluster -// information. If cluster name or cluster ID is not supplied, this method will -// auto-generate them respectively. -func (c *Core) setCluster(isLocal bool, clusterName, clusterID string) error { // Check if storage index is already present or not - cluster, err := c.Cluster(isLocal) + cluster, err := c.Cluster() if err != nil { c.logger.Printf("[ERR] core: failed to get cluster details: %v", err) return err @@ -83,35 +58,27 @@ func (c *Core) setCluster(isLocal bool, clusterName, clusterID string) error { return nil } - // If clusterName is not supplied, generate one - if clusterName == "" { + // If cluster name is not supplied, generate one + if c.clusterName == "" { clusterNameBytes, err := uuid.GenerateRandomBytes(4) if err != nil { c.logger.Printf("[ERR] core: failed to generate cluster name: %v", err) return err } - prefix := "vault-" - if isLocal { - prefix += "local-" - } else { - prefix += "global-" - } - clusterName = fmt.Sprintf("%s%08x", prefix, clusterNameBytes) + c.clusterName = fmt.Sprintf("vaule-cluster-%08x", clusterNameBytes) } - // If clusterName is not supplied, generate one - if clusterID == "" { - var err error - clusterID, err = uuid.GenerateUUID() - if err != nil { - c.logger.Printf("[ERR] core: failed to generate cluster identifier: %v", err) - return err - } + // Generate a clusterID + var err error + clusterID, err := uuid.GenerateUUID() + if err != nil { + c.logger.Printf("[ERR] core: failed to generate cluster identifier: %v", err) + return err } // Encode the cluster information into as a JSON string rawCluster, err := json.Marshal(&Cluster{ - Name: clusterName, + Name: c.clusterName, ID: clusterID, }) if err != nil { @@ -119,17 +86,10 @@ func (c *Core) setCluster(isLocal bool, clusterName, clusterID string) error { return err } - // Determine the storage path - var key string - if isLocal { - key = coreClusterLocalPath - } else { - key = coreClusterGlobalPath - } - // Store it return c.barrier.Put(&Entry{ - Key: key, + Key: coreClusterPath, Value: rawCluster, }) + } From e5c61509d625f286b217a3751688ec46fcbeaf32 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 10:01:35 -0400 Subject: [PATCH 3/7] Remove global name/id. Make only cluster name configurable. --- command/server.go | 5 +--- command/server/config.go | 11 ++------ http/sys_health.go | 55 ++++++++++++++-------------------------- http/sys_health_test.go | 24 ++++++------------ vault/cluster.go | 1 - vault/cluster_test.go | 12 ++------- vault/core.go | 41 ++++++++++-------------------- 7 files changed, 46 insertions(+), 103 deletions(-) diff --git a/command/server.go b/command/server.go index 0275104420..19f97b9a74 100644 --- a/command/server.go +++ b/command/server.go @@ -187,10 +187,7 @@ func (c *ServerCommand) Run(args []string) int { DisableMlock: config.DisableMlock, MaxLeaseTTL: config.MaxLeaseTTL, DefaultLeaseTTL: config.DefaultLeaseTTL, - LocalClusterName: config.LocalClusterName, - LocalClusterID: config.LocalClusterID, - GlobalClusterName: config.GlobalClusterName, - GlobalClusterID: config.GlobalClusterID, + ClusterName: config.ClusterName, } // Initialize the separate HA physical backend, if it exists diff --git a/command/server/config.go b/command/server/config.go index 0943e038d2..d58a11fe10 100644 --- a/command/server/config.go +++ b/command/server/config.go @@ -34,11 +34,7 @@ type Config struct { DefaultLeaseTTL time.Duration `hcl:"-"` DefaultLeaseTTLRaw string `hcl:"default_lease_ttl"` - LocalClusterName string `hcl:"local_cluster_name"` - LocalClusterID string `hcl:"local_cluster_id"` - - GlobalClusterName string `hcl:"global_cluster_name"` - GlobalClusterID string `hcl:"global_cluster_id"` + ClusterName string `hcl:"cluster_name"` } // DevConfig is a Config that is used for dev mode of Vault. @@ -283,10 +279,7 @@ func ParseConfig(d string) (*Config, error) { "telemetry", "default_lease_ttl", "max_lease_ttl", - "local_cluster_name", - "local_cluster_id", - "global_cluster_name", - "global_cluster_id", + "cluster_name", // TODO: Remove in 0.6.0 // Deprecated keys diff --git a/http/sys_health.go b/http/sys_health.go index df046ddf04..a448f3725e 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -115,54 +115,37 @@ func getSysHealth(core *vault.Core, r *http.Request) (int, *HealthResponse, erro } // Fetch the local cluster name and identifier - var localClusterName, localClusterID string - localCluster, err := core.Cluster(true) + var clusterName, clusterID string + cluster, err := core.Cluster() // Don't set the cluster details in the health status when Vault is sealed if err != nil && err.Error() != "Vault is sealed" { return http.StatusInternalServerError, nil, err } - if localCluster != nil { - localClusterName = localCluster.Name - localClusterID = localCluster.ID - } - - // Fetch the global cluster name and identifier - var globalClusterName, globalClusterID string - globalCluster, err := core.Cluster(false) - - // Don't set the cluster details in the health status when Vault is sealed - if err != nil && err.Error() != "Vault is sealed" { - return http.StatusInternalServerError, nil, err - } - if globalCluster != nil { - globalClusterName = globalCluster.Name - globalClusterID = globalCluster.ID + if cluster != nil { + clusterName = cluster.Name + clusterID = cluster.ID } // Format the body body := &HealthResponse{ - Initialized: init, - Sealed: sealed, - Standby: standby, - ServerTimeUTC: time.Now().UTC().Unix(), - Version: version.GetVersion().String(), - LocalClusterName: localClusterName, - LocalClusterID: localClusterID, - GlobalClusterName: globalClusterName, - GlobalClusterID: globalClusterID, + Initialized: init, + Sealed: sealed, + Standby: standby, + ServerTimeUTC: time.Now().UTC().Unix(), + Version: version.GetVersion().String(), + ClusterName: clusterName, + ClusterID: clusterID, } return code, body, nil } type HealthResponse struct { - Initialized bool `json:"initialized"` - Sealed bool `json:"sealed"` - Standby bool `json:"standby"` - ServerTimeUTC int64 `json:"server_time_utc"` - Version string `json:"version"` - LocalClusterName string `json:"local_cluster_name"` - LocalClusterID string `json:"local_cluster_id"` - GlobalClusterName string `json:"global_cluster_name"` - GlobalClusterID string `json:"global_cluster_id"` + Initialized bool `json:"initialized"` + Sealed bool `json:"sealed"` + Standby bool `json:"standby"` + ServerTimeUTC int64 `json:"server_time_utc"` + Version string `json:"version"` + ClusterName string `json:"cluster_name"` + ClusterID string `json:"cluster_id"` } diff --git a/http/sys_health_test.go b/http/sys_health_test.go index a27254083f..93b519b6b3 100644 --- a/http/sys_health_test.go +++ b/http/sys_health_test.go @@ -31,10 +31,8 @@ func TestSysHealth_get(t *testing.T) { testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] - expected["local_cluster_name"] = actual["local_cluster_name"] - expected["local_cluster_id"] = actual["local_cluster_id"] - expected["global_cluster_name"] = actual["global_cluster_name"] - expected["global_cluster_id"] = actual["global_cluster_id"] + expected["cluster_name"] = actual["cluster_name"] + expected["cluster_id"] = actual["cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } @@ -56,10 +54,8 @@ func TestSysHealth_get(t *testing.T) { testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] - expected["local_cluster_name"] = actual["local_cluster_name"] - expected["local_cluster_id"] = actual["local_cluster_id"] - expected["global_cluster_name"] = actual["global_cluster_name"] - expected["global_cluster_id"] = actual["global_cluster_id"] + expected["cluster_name"] = actual["cluster_name"] + expected["cluster_id"] = actual["cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } @@ -90,10 +86,8 @@ func TestSysHealth_customcodes(t *testing.T) { expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] - expected["local_cluster_name"] = actual["local_cluster_name"] - expected["local_cluster_id"] = actual["local_cluster_id"] - expected["global_cluster_name"] = actual["global_cluster_name"] - expected["global_cluster_id"] = actual["global_cluster_id"] + expected["cluster_name"] = actual["cluster_name"] + expected["cluster_id"] = actual["cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } @@ -119,10 +113,8 @@ func TestSysHealth_customcodes(t *testing.T) { testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] - expected["local_cluster_name"] = actual["local_cluster_name"] - expected["local_cluster_id"] = actual["local_cluster_id"] - expected["global_cluster_name"] = actual["global_cluster_name"] - expected["global_cluster_id"] = actual["global_cluster_id"] + expected["cluster_name"] = actual["cluster_name"] + expected["cluster_id"] = actual["cluster_id"] if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } diff --git a/vault/cluster.go b/vault/cluster.go index c01bba058a..98f9a71432 100644 --- a/vault/cluster.go +++ b/vault/cluster.go @@ -69,7 +69,6 @@ func (c *Core) setupCluster() error { } // Generate a clusterID - var err error clusterID, err := uuid.GenerateUUID() if err != nil { c.logger.Printf("[ERR] core: failed to generate cluster identifier: %v", err) diff --git a/vault/cluster_test.go b/vault/cluster_test.go index c2c63b1f1b..e4c6596ca6 100644 --- a/vault/cluster_test.go +++ b/vault/cluster_test.go @@ -4,19 +4,11 @@ import "testing" func TestCluster(t *testing.T) { c, _, _ := TestCoreUnsealed(t) - cluster, err := c.Cluster(true) + cluster, err := c.Cluster() if err != nil { t.Fatal(err) } if cluster == nil || cluster.Name == "" || cluster.ID == "" { - t.Fatalf("local cluster information missing: cluster:%#v", cluster) - } - - cluster, err = c.Cluster(false) - if err != nil { - t.Fatal(err) - } - if cluster == nil || cluster.Name == "" || cluster.ID == "" { - t.Fatalf("global cluster information missing: cluster:%#v", cluster) + t.Fatalf("cluster information missing: cluster:%#v", cluster) } } diff --git a/vault/core.go b/vault/core.go index a57aa463a6..30a63095b8 100644 --- a/vault/core.go +++ b/vault/core.go @@ -219,11 +219,7 @@ type Core struct { // cachingDisabled indicates whether caches are disabled cachingDisabled bool - localClusterName string - localClusterID string - - globalClusterName string - globalClusterID string + clusterName string } // CoreConfig is used to parameterize a core @@ -259,13 +255,7 @@ type CoreConfig struct { MaxLeaseTTL time.Duration `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` - LocalClusterName string `json:"local_cluster_name" structs:"local_cluster_name" mapstructure:"local_cluster_name"` - - LocalClusterID string `json:"local_cluster_id" structs:"local_cluster_id" mapstructure:"local_cluster_id"` - - GlobalClusterName string `json:"global_cluster_name" structs:"global_cluster_name" mapstructure:"global_cluster_name"` - - GlobalClusterID string `json:"global_cluster_id" structs:"global_cluster_id" mapstructure:"global_cluster_id"` + ClusterName string `json:"cluster_name" structs:"cluster_name" mapstructure:"cluster_name"` } // NewCore is used to construct a new core @@ -335,21 +325,18 @@ func NewCore(conf *CoreConfig) (*Core, error) { // Setup the core c := &Core{ - advertiseAddr: conf.AdvertiseAddr, - physical: conf.Physical, - seal: conf.Seal, - barrier: barrier, - router: NewRouter(), - sealed: true, - standby: true, - logger: conf.Logger, - defaultLeaseTTL: conf.DefaultLeaseTTL, - maxLeaseTTL: conf.MaxLeaseTTL, - cachingDisabled: conf.DisableCache, - localClusterName: conf.LocalClusterName, - localClusterID: conf.LocalClusterID, - globalClusterName: conf.GlobalClusterName, - globalClusterID: conf.GlobalClusterID, + advertiseAddr: conf.AdvertiseAddr, + physical: conf.Physical, + seal: conf.Seal, + barrier: barrier, + router: NewRouter(), + sealed: true, + standby: true, + logger: conf.Logger, + defaultLeaseTTL: conf.DefaultLeaseTTL, + maxLeaseTTL: conf.MaxLeaseTTL, + cachingDisabled: conf.DisableCache, + clusterName: conf.ClusterName, } if conf.HAPhysical != nil && conf.HAPhysical.HAEnabled() { From 46b94d8612a645deb2facfad1dd12f8fc3681e40 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 11:11:12 -0400 Subject: [PATCH 4/7] Update cluster name during config merge --- command/server/config.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/command/server/config.go b/command/server/config.go index d58a11fe10..571d4fc59d 100644 --- a/command/server/config.go +++ b/command/server/config.go @@ -212,6 +212,11 @@ func (c *Config) Merge(c2 *Config) *Config { result.DefaultLeaseTTL = c2.DefaultLeaseTTL } + result.ClusterName = c.ClusterName + if c2.ClusterName != "" { + result.ClusterName = c2.ClusterName + } + return result } From f76c926b0a36e55e71190eb3e2da312f29aca54e Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 11:38:24 -0400 Subject: [PATCH 5/7] Added cluster_name for existing config tests --- command/server/config_test.go | 3 +++ command/server/test-fixtures/config-dir/baz.hcl | 1 + command/server/test-fixtures/config.hcl | 1 + command/server/test-fixtures/config.hcl.json | 3 ++- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/command/server/config_test.go b/command/server/config_test.go index 708bf337cd..0d963f9a8a 100644 --- a/command/server/config_test.go +++ b/command/server/config_test.go @@ -61,6 +61,7 @@ func TestLoadConfigFile(t *testing.T) { MaxLeaseTTLRaw: "10h", DefaultLeaseTTL: 10 * time.Hour, DefaultLeaseTTLRaw: "10h", + ClusterName: "testcluster", } if !reflect.DeepEqual(config, expected) { t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected) @@ -120,6 +121,7 @@ func TestLoadConfigFile_json(t *testing.T) { MaxLeaseTTLRaw: "10h", DefaultLeaseTTL: 10 * time.Hour, DefaultLeaseTTLRaw: "10h", + ClusterName: "testcluster", } if !reflect.DeepEqual(config, expected) { t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected) @@ -218,6 +220,7 @@ func TestLoadConfigDir(t *testing.T) { MaxLeaseTTL: 10 * time.Hour, DefaultLeaseTTL: 10 * time.Hour, + ClusterName: "testcluster", } if !reflect.DeepEqual(config, expected) { t.Fatalf("bad: %#v", config) diff --git a/command/server/test-fixtures/config-dir/baz.hcl b/command/server/test-fixtures/config-dir/baz.hcl index e57d76581a..9b650104b2 100644 --- a/command/server/test-fixtures/config-dir/baz.hcl +++ b/command/server/test-fixtures/config-dir/baz.hcl @@ -5,3 +5,4 @@ telemetry { } default_lease_ttl = "10h" +cluster_name = "testcluster" diff --git a/command/server/test-fixtures/config.hcl b/command/server/test-fixtures/config.hcl index 122710bf41..426f109238 100644 --- a/command/server/test-fixtures/config.hcl +++ b/command/server/test-fixtures/config.hcl @@ -26,3 +26,4 @@ ha_backend "consul" { max_lease_ttl = "10h" default_lease_ttl = "10h" +cluster_name = "testcluster" diff --git a/command/server/test-fixtures/config.hcl.json b/command/server/test-fixtures/config.hcl.json index 094dc154a5..eb0970d31b 100644 --- a/command/server/test-fixtures/config.hcl.json +++ b/command/server/test-fixtures/config.hcl.json @@ -20,5 +20,6 @@ "statsite_address": "baz" }, "max_lease_ttl": "10h", - "default_lease_ttl": "10h" + "default_lease_ttl": "10h", + "cluster_name":"testcluster" } From a64fa19a0e68a98113454ceb47aad304bf2bd633 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 14:05:27 -0400 Subject: [PATCH 6/7] Address review feedback from @jefferai --- http/sys_health.go | 18 ++++++++++-------- vault/cluster.go | 2 +- website/source/docs/http/sys-health.html.md | 6 ++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/http/sys_health.go b/http/sys_health.go index a448f3725e..2b3eed364c 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -116,15 +116,17 @@ func getSysHealth(core *vault.Core, r *http.Request) (int, *HealthResponse, erro // Fetch the local cluster name and identifier var clusterName, clusterID string - cluster, err := core.Cluster() + if !sealed { + cluster, err := core.Cluster() - // Don't set the cluster details in the health status when Vault is sealed - if err != nil && err.Error() != "Vault is sealed" { - return http.StatusInternalServerError, nil, err - } - if cluster != nil { - clusterName = cluster.Name - clusterID = cluster.ID + // Don't set the cluster details in the health status when Vault is sealed + if err != nil { + return http.StatusInternalServerError, nil, err + } + if cluster != nil { + clusterName = cluster.Name + clusterID = cluster.ID + } } // Format the body diff --git a/vault/cluster.go b/vault/cluster.go index 98f9a71432..53c68da810 100644 --- a/vault/cluster.go +++ b/vault/cluster.go @@ -65,7 +65,7 @@ func (c *Core) setupCluster() error { c.logger.Printf("[ERR] core: failed to generate cluster name: %v", err) return err } - c.clusterName = fmt.Sprintf("vaule-cluster-%08x", clusterNameBytes) + c.clusterName = fmt.Sprintf("vault-cluster-%08x", clusterNameBytes) } // Generate a clusterID diff --git a/website/source/docs/http/sys-health.html.md b/website/source/docs/http/sys-health.html.md index 454f0e28a3..cd770c59e7 100644 --- a/website/source/docs/http/sys-health.html.md +++ b/website/source/docs/http/sys-health.html.md @@ -54,8 +54,10 @@ description: |- ```javascript { - "version": "Vault v0.6.1-dev ('418257d27c67fabc4fdd831a6a750d54d8bed76f+CHANGES')", - "server_time_utc": 1469226751, + "cluster_id": "c9abceea-4f46-4dab-a688-5ce55f89e228", + "cluster_name": "vault-cluster-5515c810", + "version": "Vault v0.6.1-dev ('f76c926b0a36e55e71190eb3e2da312f29aca54e+CHANGES')", + "server_time_utc": 1469555798, "standby": false, "sealed": false, "initialized": true From 415c463a87558f6529285befff8fb867e9e78f89 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Tue, 26 Jul 2016 14:11:32 -0400 Subject: [PATCH 7/7] Added omitempty to ClusterName and ClusterID --- http/sys_health.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/http/sys_health.go b/http/sys_health.go index 2b3eed364c..4f3182bb26 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -148,6 +148,6 @@ type HealthResponse struct { Standby bool `json:"standby"` ServerTimeUTC int64 `json:"server_time_utc"` Version string `json:"version"` - ClusterName string `json:"cluster_name"` - ClusterID string `json:"cluster_id"` + ClusterName string `json:"cluster_name,omitempty"` + ClusterID string `json:"cluster_id,omitempty"` }