Skip to content

Commit

Permalink
raft: handle retry_join as blocks
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Cragun <[email protected]>
  • Loading branch information
ryancragun committed Jan 10, 2025
1 parent 180d65d commit 2af9223
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 43 deletions.
42 changes: 28 additions & 14 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1072,19 +1072,33 @@ func normalizeStorageConfigAddresses(storage string, key string, value string) (
func normalizeRaftRetryJoin(val any) ([]byte, error) {
res := []map[string]any{}

retryJoin, ok := val.([]any)
if !ok {
return nil, fmt.Errorf("malformed retry_join stanza: %v+", val)
}

for _, rj := range retryJoin {
rjMap, ok := rj.(map[string]any)
// Depending on whether the retry_join stanzas were configured as an attribute,
// a block, or a mixture of both, we'll get different values from which we
// need to extract our individual retry joins stanzas.
stanzas := []map[string]any{}
if retryJoin, ok := val.([]map[string]any); ok {
// retry_join stanzas are defined as blocks
stanzas = retryJoin
} else {
// retry_join stanzas are defined as attributes or attributes and blocks
retryJoin, ok := val.([]any)
if !ok {
return nil, fmt.Errorf("malformed retry_join stanza: %v+", rj)
// retry_join stanzas have not been configured correctly
return nil, fmt.Errorf("malformed retry_join stanza: %v", val)
}

rjRes := map[string]any{}
for k, v := range rjMap {
for _, stanza := range retryJoin {
stanzaVal, ok := stanza.(map[string]any)
if !ok {
return nil, fmt.Errorf("malformed retry_join stanza: %v", stanza)
}
stanzas = append(stanzas, stanzaVal)
}
}

for _, stanza := range stanzas {
normalizedStanza := map[string]any{}
for k, v := range stanza {
switch k {
case "auto_join":
pairs := strings.Split(v.(string), " ")
Expand All @@ -1100,15 +1114,15 @@ func normalizeRaftRetryJoin(val any) ([]byte, error) {
pairs[i] = pair
}
}
rjRes[k] = strings.Join(pairs, " ")
normalizedStanza[k] = strings.Join(pairs, " ")
case "leader_api_addr":
rjRes[k] = configutil.NormalizeAddr(v.(string))
normalizedStanza[k] = configutil.NormalizeAddr(v.(string))
default:
rjRes[k] = v
normalizedStanza[k] = v
}
}

res = append(res, rjRes)
res = append(res, normalizedStanza)
}

return json.Marshal(res)
Expand Down
62 changes: 35 additions & 27 deletions command/server/config_test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ func boolPointer(x bool) *bool {

// testConfigRaftRetryJoin decodes and normalizes retry_join stanzas.
func testConfigRaftRetryJoin(t *testing.T) {
t.Helper()
config, err := LoadConfigFile("./test-fixtures/raft_retry_join.hcl")
if err != nil {
t.Fatal(err)
}
t.Parallel()

retryJoinExpected := []map[string]string{
{"leader_api_addr": "http://127.0.0.1:8200"},
Expand All @@ -47,32 +43,44 @@ func testConfigRaftRetryJoin(t *testing.T) {
{"auto_join": "provider=packet auth_token=token project=uuid url=https://[2001:db8::2:1] address_type=public_v6"},
{"auto_join": "provider=vsphere category_name=consul-role tag_name=consul-server host=https://[2001:db8::2:1] user=foo password=bar insecure_ssl=false"},
}
retryJoinJSON, err := json.Marshal(retryJoinExpected)
require.NoError(t, err)
for _, cfg := range []string{
"attr",
"block",
"mixed",
} {
t.Run(cfg, func(t *testing.T) {
t.Parallel()

expected := &Config{
SharedConfig: &configutil.SharedConfig{
Listeners: []*configutil.Listener{
{
Type: "tcp",
Address: "127.0.0.1:8200",
CustomResponseHeaders: DefaultCustomHeaders,
config, err := LoadConfigFile(fmt.Sprintf("./test-fixtures/raft_retry_join_%s.hcl", cfg))
require.NoError(t, err)
retryJoinJSON, err := json.Marshal(retryJoinExpected)
require.NoError(t, err)

expected := &Config{
SharedConfig: &configutil.SharedConfig{
Listeners: []*configutil.Listener{
{
Type: "tcp",
Address: "127.0.0.1:8200",
CustomResponseHeaders: DefaultCustomHeaders,
},
},
DisableMlock: true,
},
},
DisableMlock: true,
},

Storage: &Storage{
Type: "raft",
Config: map[string]string{
"path": "/storage/path/raft",
"node_id": "raft1",
"retry_join": string(retryJoinJSON),
},
},
Storage: &Storage{
Type: "raft",
Config: map[string]string{
"path": "/storage/path/raft",
"node_id": "raft1",
"retry_join": string(retryJoinJSON),
},
},
}
config.Prune()
require.EqualValues(t, expected, config)
})
}
config.Prune()
require.EqualValues(t, expected, config)
}

func testLoadConfigFile_topLevel(t *testing.T, entropy *configutil.Entropy) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ storage "raft" {
node_id = "raft1"
retry_join = [
{ "leader_api_addr" = "http://127.0.0.1:8200" },
]
retry_join = [
{ "leader_api_addr" = "http://[2001:db8:0:0:0:0:2:1]:8200" }
]
retry_join = [
Expand Down
35 changes: 35 additions & 0 deletions command/server/test-fixtures/raft_retry_join_block.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

storage "raft" {
path = "/storage/path/raft"
node_id = "raft1"

retry_join {
"leader_api_addr" = "http://127.0.0.1:8200"
}
retry_join {
"leader_api_addr" = "http://[2001:db8:0:0:0:0:2:1]:8200"
}
retry_join {
"auto_join" = "provider=mdns service=consul domain=2001:db8:0:0:0:0:2:1"
}
retry_join {
"auto_join" = "provider=os tag_key=consul tag_value=server username=foo password=bar auth_url=https://[2001:db8:0:0:0:0:2:1]/auth"
}
retry_join {
"auto_join" = "provider=triton account=testaccount url=https://[2001:db8:0:0:0:0:2:1] key_id=1234 tag_key=consul-role tag_value=server"
}
retry_join {
"auto_join" = "provider=packet auth_token=token project=uuid url=https://[2001:db8:0:0:0:0:2:1] address_type=public_v6"
}
retry_join {
"auto_join" = "provider=vsphere category_name=consul-role tag_name=consul-server host=https://[2001:db8:0:0:0:0:2:1] user=foo password=bar insecure_ssl=false"
}
}

listener "tcp" {
address = "127.0.0.1:8200"
}

disable_mlock = true
32 changes: 32 additions & 0 deletions command/server/test-fixtures/raft_retry_join_mixed.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

storage "raft" {
path = "/storage/path/raft"
node_id = "raft1"
retry_join = [
{ "leader_api_addr" = "http://127.0.0.1:8200" },
{ "leader_api_addr" = "http://[2001:db8:0:0:0:0:2:1]:8200" }
]
retry_join {
"auto_join" = "provider=mdns service=consul domain=2001:db8:0:0:0:0:2:1"
}
retry_join = [
{ "auto_join" = "provider=os tag_key=consul tag_value=server username=foo password=bar auth_url=https://[2001:db8:0:0:0:0:2:1]/auth" }
]
retry_join {
"auto_join" = "provider=triton account=testaccount url=https://[2001:db8:0:0:0:0:2:1] key_id=1234 tag_key=consul-role tag_value=server"
}
retry_join = [
{ "auto_join" = "provider=packet auth_token=token project=uuid url=https://[2001:db8:0:0:0:0:2:1] address_type=public_v6" }
]
retry_join {
"auto_join" = "provider=vsphere category_name=consul-role tag_name=consul-server host=https://[2001:db8:0:0:0:0:2:1] user=foo password=bar insecure_ssl=false"
}
}

listener "tcp" {
address = "127.0.0.1:8200"
}

disable_mlock = true

0 comments on commit 2af9223

Please sign in to comment.