Auto-join support for IPv6 discovery (#12366)

* Auto-join support for IPv6 discovery

The go-discover library returns IP addresses and not URLs. It just so
happens net.URL parses "127.0.0.1", which isn't a valid URL.

Instead, we construct the URL ourselves. Being careful to check if it's
an ipv6 address and making sure it's in explicit form if so.

Fixes #12323

* feedback: addrs & ipv6 test

Rename addrs to clusterIPs to improve clarity and intent

Tighten up our IPv6 address detection to be more correct and to ensure
it's actually in implicit form
This commit is contained in:
Daniel Kimsey 2021-09-07 13:55:07 -05:00 committed by GitHub
parent 30ca69f16a
commit b4b61efc75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 29 deletions

3
changelog/12366.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
storage/raft: Support `addr_type=public_v6` in auto-join
```

View File

@ -947,39 +947,28 @@ func (c *Core) JoinRaftCluster(ctx context.Context, leaderInfos []*raft.LeaderJo
}
case leaderInfo.AutoJoin != "":
addrs, err := disco.Addrs(leaderInfo.AutoJoin, c.logger.StandardLogger(nil))
scheme := leaderInfo.AutoJoinScheme
if scheme == "" {
// default to HTTPS when no scheme is provided
scheme = "https"
}
port := leaderInfo.AutoJoinPort
if port == 0 {
// default to 8200 when no port is provided
port = 8200
}
// Addrs returns either IPv4 or IPv6 address sans scheme or port
clusterIPs, err := disco.Addrs(leaderInfo.AutoJoin, c.logger.StandardLogger(nil))
if err != nil {
c.logger.Error("failed to parse addresses from auto-join metadata", "error", err)
}
for _, addr := range addrs {
u, err := url.Parse(addr)
if err != nil {
c.logger.Error("failed to parse discovered address", "error", err)
continue
for _, ip := range clusterIPs {
if strings.Count(ip, ":") >= 2 && !strings.HasPrefix(ip, "["){
// An IPv6 address in implicit form, however we need it in explicit form to use in a URL.
ip = fmt.Sprintf("[%s]", ip)
}
if u.Scheme == "" {
scheme := leaderInfo.AutoJoinScheme
if scheme == "" {
// default to HTTPS when no scheme is provided
scheme = "https"
}
addr = fmt.Sprintf("%s://%s", scheme, addr)
}
if u.Port() == "" {
port := leaderInfo.AutoJoinPort
if port == 0 {
// default to 8200 when no port is provided
port = 8200
}
addr = fmt.Sprintf("%s:%d", addr, port)
}
if err := joinLeader(leaderInfo, addr); err != nil {
u := fmt.Sprintf("%s://%s:%d", scheme, ip, port)
if err := joinLeader(leaderInfo, u); err != nil {
c.logger.Warn("join attempt failed", "error", err)
} else {
// successfully joined leader