Refactor redundancy_zone/upgrade_version out of client meta

This commit is contained in:
Kyle Havlovitz
2018-01-29 19:53:34 -08:00
parent ad8bfaea00
commit 2c873adba4
30 changed files with 350 additions and 299 deletions

View File

@@ -163,6 +163,12 @@ func convertServerConfig(agentConfig *Config, logOutput io.Writer) (*nomad.Confi
if agentConfig.Server.NonVotingServer {
conf.NonVoter = true
}
if agentConfig.Server.RedundancyZone != "" {
conf.RedundancyZone = agentConfig.Server.RedundancyZone
}
if agentConfig.Server.UpgradeVersion != "" {
conf.UpgradeVersion = agentConfig.Server.UpgradeVersion
}
if agentConfig.Autopilot != nil {
if agentConfig.Autopilot.CleanupDeadServers != nil {
conf.AutopilotConfig.CleanupDeadServers = *agentConfig.Autopilot.CleanupDeadServers
@@ -176,14 +182,14 @@ func convertServerConfig(agentConfig *Config, logOutput io.Writer) (*nomad.Confi
if agentConfig.Autopilot.MaxTrailingLogs != 0 {
conf.AutopilotConfig.MaxTrailingLogs = uint64(agentConfig.Autopilot.MaxTrailingLogs)
}
if agentConfig.Autopilot.RedundancyZoneTag != "" {
conf.AutopilotConfig.RedundancyZoneTag = agentConfig.Autopilot.RedundancyZoneTag
if agentConfig.Autopilot.EnableRedundancyZones != nil {
conf.AutopilotConfig.EnableRedundancyZones = *agentConfig.Autopilot.EnableRedundancyZones
}
if agentConfig.Autopilot.DisableUpgradeMigration != nil {
conf.AutopilotConfig.DisableUpgradeMigration = *agentConfig.Autopilot.DisableUpgradeMigration
}
if agentConfig.Autopilot.UpgradeVersionTag != "" {
conf.AutopilotConfig.UpgradeVersionTag = agentConfig.Autopilot.UpgradeVersionTag
if agentConfig.Autopilot.EnableCustomUpgrades != nil {
conf.AutopilotConfig.EnableCustomUpgrades = *agentConfig.Autopilot.EnableCustomUpgrades
}
}

View File

@@ -83,6 +83,8 @@ server {
retry_interval = "15s"
rejoin_after_leave = true
non_voting_server = true
redundancy_zone = "foo"
upgrade_version = "0.8.0"
encrypt = "abc"
}
acl {
@@ -166,7 +168,7 @@ autopilot {
disable_upgrade_migration = true
last_contact_threshold = "12705s"
max_trailing_logs = 17849
redundancy_zone_tag = "foo"
enable_redundancy_zones = true
server_stabilization_time = "23057s"
upgrade_version_tag = "bar"
enable_custom_upgrades = true
}

View File

@@ -330,10 +330,17 @@ type ServerConfig struct {
// true, we ignore the leave, and rejoin the cluster on start.
RejoinAfterLeave bool `mapstructure:"rejoin_after_leave"`
// NonVotingServer is whether this server will act as a non-voting member
// of the cluster to help provide read scalability. (Enterprise-only)
// (Enterprise-only) NonVotingServer is whether this server will act as a
// non-voting member of the cluster to help provide read scalability.
NonVotingServer bool `mapstructure:"non_voting_server"`
// (Enterprise-only) RedundancyZone is the redundancy zone to use for this server.
RedundancyZone string `mapstructure:"redundancy_zone"`
// (Enterprise-only) UpgradeVersion is the custom upgrade version to use when
// performing upgrade migrations.
UpgradeVersion string `mapstructure:"upgrade_version"`
// Encryption key to use for the Serf communication
EncryptKey string `mapstructure:"encrypt" json:"-"`
}
@@ -1034,6 +1041,12 @@ func (a *ServerConfig) Merge(b *ServerConfig) *ServerConfig {
if b.NonVotingServer {
result.NonVotingServer = true
}
if b.RedundancyZone != "" {
result.RedundancyZone = b.RedundancyZone
}
if b.UpgradeVersion != "" {
result.UpgradeVersion = b.UpgradeVersion
}
if b.EncryptKey != "" {
result.EncryptKey = b.EncryptKey
}

View File

@@ -9,6 +9,7 @@ import (
"time"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
"github.com/hashicorp/nomad/helper"
@@ -536,6 +537,8 @@ func parseServer(result **ServerConfig, list *ast.ObjectList) error {
"encrypt",
"authoritative_region",
"non_voting_server",
"redundancy_zone",
"upgrade_version",
}
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
return err
@@ -559,6 +562,12 @@ func parseServer(result **ServerConfig, list *ast.ObjectList) error {
return err
}
if config.UpgradeVersion != "" {
if _, err := version.NewVersion(config.UpgradeVersion); err != nil {
return fmt.Errorf("error parsing upgrade_version: %v", err)
}
}
*result = &config
return nil
}
@@ -865,9 +874,9 @@ func parseAutopilot(result **config.AutopilotConfig, list *ast.ObjectList) error
"server_stabilization_time",
"last_contact_threshold",
"max_trailing_logs",
"redundancy_zone_tag",
"enable_redundancy_zones",
"disable_upgrade_migration",
"upgrade_version_tag",
"enable_custom_upgrades",
}
if err := helper.CheckHCLKeys(listVal, valid); err != nil {

View File

@@ -104,6 +104,8 @@ func TestConfig_Parse(t *testing.T) {
RejoinAfterLeave: true,
RetryMaxAttempts: 3,
NonVotingServer: true,
RedundancyZone: "foo",
UpgradeVersion: "0.8.0",
EncryptKey: "abc",
},
ACL: &ACLConfig{
@@ -193,9 +195,9 @@ func TestConfig_Parse(t *testing.T) {
ServerStabilizationTime: 23057 * time.Second,
LastContactThreshold: 12705 * time.Second,
MaxTrailingLogs: 17849,
RedundancyZoneTag: "foo",
EnableRedundancyZones: &trueValue,
DisableUpgradeMigration: &trueValue,
UpgradeVersionTag: "bar",
EnableCustomUpgrades: &trueValue,
},
},
false,

View File

@@ -107,6 +107,8 @@ func TestConfig_Merge(t *testing.T) {
HeartbeatGrace: 30 * time.Second,
MinHeartbeatTTL: 30 * time.Second,
MaxHeartbeatsPerSecond: 30.0,
RedundancyZone: "foo",
UpgradeVersion: "foo",
},
ACL: &ACLConfig{
Enabled: true,
@@ -165,9 +167,9 @@ func TestConfig_Merge(t *testing.T) {
ServerStabilizationTime: 1 * time.Second,
LastContactThreshold: 1 * time.Second,
MaxTrailingLogs: 1,
RedundancyZoneTag: "1",
EnableRedundancyZones: &falseValue,
DisableUpgradeMigration: &falseValue,
UpgradeVersionTag: "1",
EnableCustomUpgrades: &falseValue,
},
}
@@ -260,6 +262,8 @@ func TestConfig_Merge(t *testing.T) {
RetryInterval: "10s",
retryInterval: time.Second * 10,
NonVotingServer: true,
RedundancyZone: "bar",
UpgradeVersion: "bar",
},
ACL: &ACLConfig{
Enabled: true,
@@ -328,9 +332,9 @@ func TestConfig_Merge(t *testing.T) {
ServerStabilizationTime: 2 * time.Second,
LastContactThreshold: 2 * time.Second,
MaxTrailingLogs: 2,
RedundancyZoneTag: "2",
EnableRedundancyZones: &trueValue,
DisableUpgradeMigration: &trueValue,
UpgradeVersionTag: "2",
EnableCustomUpgrades: &trueValue,
},
}

View File

@@ -104,19 +104,19 @@ func (s *HTTPServer) OperatorAutopilotConfiguration(resp http.ResponseWriter, re
return nil, nil
}
var reply autopilot.Config
var reply structs.AutopilotConfig
if err := s.agent.RPC("Operator.AutopilotGetConfiguration", &args, &reply); err != nil {
return nil, err
}
out := api.AutopilotConfiguration{
CleanupDeadServers: reply.CleanupDeadServers,
LastContactThreshold: api.NewReadableDuration(reply.LastContactThreshold),
LastContactThreshold: reply.LastContactThreshold,
MaxTrailingLogs: reply.MaxTrailingLogs,
ServerStabilizationTime: api.NewReadableDuration(reply.ServerStabilizationTime),
RedundancyZoneTag: reply.RedundancyZoneTag,
ServerStabilizationTime: reply.ServerStabilizationTime,
EnableRedundancyZones: reply.EnableRedundancyZones,
DisableUpgradeMigration: reply.DisableUpgradeMigration,
UpgradeVersionTag: reply.UpgradeVersionTag,
EnableCustomUpgrades: reply.EnableCustomUpgrades,
CreateIndex: reply.CreateIndex,
ModifyIndex: reply.ModifyIndex,
}
@@ -129,21 +129,20 @@ func (s *HTTPServer) OperatorAutopilotConfiguration(resp http.ResponseWriter, re
s.parseToken(req, &args.AuthToken)
var conf api.AutopilotConfiguration
durations := NewDurationFixer("lastcontactthreshold", "serverstabilizationtime")
if err := decodeBodyFunc(req, &conf, durations.FixupDurations); err != nil {
if err := decodeBody(req, &conf); err != nil {
resp.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(resp, "Error parsing autopilot config: %v", err)
return nil, nil
}
args.Config = autopilot.Config{
args.Config = structs.AutopilotConfig{
CleanupDeadServers: conf.CleanupDeadServers,
LastContactThreshold: conf.LastContactThreshold.Duration(),
LastContactThreshold: conf.LastContactThreshold,
MaxTrailingLogs: conf.MaxTrailingLogs,
ServerStabilizationTime: conf.ServerStabilizationTime.Duration(),
RedundancyZoneTag: conf.RedundancyZoneTag,
ServerStabilizationTime: conf.ServerStabilizationTime,
EnableRedundancyZones: conf.EnableRedundancyZones,
DisableUpgradeMigration: conf.DisableUpgradeMigration,
UpgradeVersionTag: conf.UpgradeVersionTag,
EnableCustomUpgrades: conf.EnableCustomUpgrades,
}
// Check for cas value
@@ -210,7 +209,7 @@ func (s *HTTPServer) OperatorServerHealth(resp http.ResponseWriter, req *http.Re
Version: server.Version,
Leader: server.Leader,
SerfStatus: server.SerfStatus.String(),
LastContact: api.NewReadableDuration(server.LastContact),
LastContact: server.LastContact,
LastTerm: server.LastTerm,
LastIndex: server.LastIndex,
Healthy: server.Healthy,
@@ -221,56 +220,3 @@ func (s *HTTPServer) OperatorServerHealth(resp http.ResponseWriter, req *http.Re
return out, nil
}
type durationFixer map[string]bool
func NewDurationFixer(fields ...string) durationFixer {
d := make(map[string]bool)
for _, field := range fields {
d[field] = true
}
return d
}
// FixupDurations is used to handle parsing any field names in the map to time.Durations
func (d durationFixer) FixupDurations(raw interface{}) error {
rawMap, ok := raw.(map[string]interface{})
if !ok {
return nil
}
for key, val := range rawMap {
switch val.(type) {
case map[string]interface{}:
if err := d.FixupDurations(val); err != nil {
return err
}
case []interface{}:
for _, v := range val.([]interface{}) {
if err := d.FixupDurations(v); err != nil {
return err
}
}
case []map[string]interface{}:
for _, v := range val.([]map[string]interface{}) {
if err := d.FixupDurations(v); err != nil {
return err
}
}
default:
if d[strings.ToLower(key)] {
// Convert a string value into an integer
if vStr, ok := val.(string); ok {
dur, err := time.ParseDuration(vStr)
if err != nil {
return err
}
rawMap[key] = dur
}
}
}
}
return nil
}

View File

@@ -9,7 +9,6 @@ import (
"testing"
"time"
"github.com/hashicorp/consul/agent/consul/autopilot"
"github.com/hashicorp/consul/testutil/retry"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/nomad/structs"
@@ -112,7 +111,7 @@ func TestOperator_AutopilotSetConfiguration(t *testing.T) {
t.Fatalf("err: %v", err)
}
if resp.Code != 200 {
t.Fatalf("bad code: %d", resp.Code)
t.Fatalf("bad code: %d, %q", resp.Code, resp.Body.String())
}
args := structs.GenericRequest{
@@ -121,7 +120,7 @@ func TestOperator_AutopilotSetConfiguration(t *testing.T) {
},
}
var reply autopilot.Config
var reply structs.AutopilotConfig
if err := s.RPC("Operator.AutopilotGetConfiguration", &args, &reply); err != nil {
t.Fatalf("err: %v", err)
}
@@ -150,7 +149,7 @@ func TestOperator_AutopilotCASConfiguration(t *testing.T) {
},
}
var reply autopilot.Config
var reply structs.AutopilotConfig
if err := s.RPC("Operator.AutopilotGetConfiguration", &args, &reply); err != nil {
t.Fatalf("err: %v", err)
}
@@ -200,7 +199,6 @@ func TestOperator_AutopilotCASConfiguration(t *testing.T) {
}
func TestOperator_ServerHealth(t *testing.T) {
t.Parallel()
httpTest(t, func(c *Config) {
c.Server.RaftProtocol = 3
}, func(s *TestAgent) {
@@ -259,47 +257,3 @@ func TestOperator_ServerHealth_Unhealthy(t *testing.T) {
})
})
}
func TestDurationFixer(t *testing.T) {
assert := assert.New(t)
obj := map[string]interface{}{
"key1": []map[string]interface{}{
{
"subkey1": "10s",
},
{
"subkey2": "5d",
},
},
"key2": map[string]interface{}{
"subkey3": "30s",
"subkey4": "20m",
},
"key3": "11s",
"key4": "49h",
}
expected := map[string]interface{}{
"key1": []map[string]interface{}{
{
"subkey1": 10 * time.Second,
},
{
"subkey2": "5d",
},
},
"key2": map[string]interface{}{
"subkey3": "30s",
"subkey4": 20 * time.Minute,
},
"key3": "11s",
"key4": 49 * time.Hour,
}
fixer := NewDurationFixer("key4", "subkey1", "subkey4")
if err := fixer.FixupDurations(obj); err != nil {
t.Fatal(err)
}
// Ensure we only processed the intended fieldnames
assert.Equal(obj, expected)
}