m/node/core/consensus: always use member name as address
Instead of explicitly giving the consensus service an address to listen
on, we now just give it a hostname. Etcd will resolve the name itself on
startup. It's not yet known if it will re-resolve it and handle changes.
If that's not the case, we will have to implement a restarting
babysitter process instead.
Test Plan: E2e tests should cover this.
X-Origin-Diff: phab/D734
GitOrigin-RevId: c2255b2956137e2bbd705ac1965418c0540d0046
diff --git a/metropolis/node/core/consensus/consensus.go b/metropolis/node/core/consensus/consensus.go
index 269ff7e..2bbe1ae 100644
--- a/metropolis/node/core/consensus/consensus.go
+++ b/metropolis/node/core/consensus/consensus.go
@@ -34,7 +34,6 @@
"context"
"encoding/pem"
"fmt"
- "net"
"net/url"
"sync"
"time"
@@ -88,16 +87,13 @@
// NewCluster selects whether the etcd member will start a new cluster and bootstrap a CA and the first member
// certificate, or load existing PKI certificates from disk.
NewCluster bool
- // InitialCluster sets the initial cluster peer URLs when NewCluster is set, and is ignored otherwise. Usually this
- // will be just the new, single server, and more members will be added later.
- InitialCluster string
- // ExternalHost is the IP address or hostname at which this cluster member is reachable to other cluster members.
- ExternalHost string
- // ListenHost is the IP address or hostname at which this cluster member will listen.
- ListenHost string
// Port is the port at which this cluster member will listen for other members. If zero, defaults to the global
// Metropolis setting.
Port int
+
+ // ExternalHost is used by tests to override the address at which etcd should listen for peer connections.
+ // TODO(q3k): make this unexported once the new cluster manager logic lands.
+ ExternalHost string
}
func New(config Config) *Service {
@@ -116,6 +112,9 @@
return nil, fmt.Errorf("failed to create data directory: %w", err)
}
+ if s.config.Name == "" {
+ return nil, fmt.Errorf("Name not set")
+ }
port := s.config.Port
if port == 0 {
port = node.ConsensusPort
@@ -140,19 +139,25 @@
cfg.ACUrls = []url.URL{}
cfg.LPUrls = []url.URL{{
Scheme: "https",
- Host: fmt.Sprintf("%s:%d", s.config.ListenHost, port),
+ Host: fmt.Sprintf("[::]:%d", port),
}}
+
+ // Always listen on the address pointed to by our name - unless running in
+ // tests, where we can't control our hostname easily.
+ ExternalHost := fmt.Sprintf("%s:%d", s.config.Name, port)
+ if s.config.ExternalHost != "" {
+ ExternalHost = fmt.Sprintf("%s:%d", s.config.ExternalHost, port)
+ }
cfg.APUrls = []url.URL{{
Scheme: "https",
- Host: fmt.Sprintf("%s:%d", s.config.ExternalHost, port),
+ Host: ExternalHost,
}}
if s.config.NewCluster {
cfg.ClusterState = "new"
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
- } else if s.config.InitialCluster != "" {
+ } else {
cfg.ClusterState = "existing"
- cfg.InitialCluster = s.config.InitialCluster
}
// TODO(q3k): pipe logs from etcd to supervisor.RawLogger via a file.
@@ -189,12 +194,7 @@
return fmt.Errorf("when creating new cluster's peer CA: %w", err)
}
- ip := net.ParseIP(s.config.ExternalHost)
- if ip == nil {
- return fmt.Errorf("configued external host is not an IP address (got %q)", s.config.ExternalHost)
- }
-
- cert, key, err := st.ca.Issue(ctx, nil, s.config.Name, ip)
+ cert, key, err := st.ca.Issue(ctx, nil, s.config.Name)
if err != nil {
return fmt.Errorf("when issuing new cluster's first certificate: %w", err)
}
@@ -240,8 +240,6 @@
}
st.etcd = server
- supervisor.Logger(ctx).Info("waiting for etcd...")
-
okay := true
select {
case <-st.etcd.Server.ReadyNotify():