m/n/c/consensus: handle empty etcd member Name
When an etcd member has not been started yet, the member.Name field is
the empty string. In this case, we need to extract the node id from
PeerURLs instead.
Change-Id: I41aa39423bd4c7888467d65eb2a3f96e7d02e617
Reviewed-on: https://review.monogon.dev/c/monogon/+/3385
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/metropolis/node/core/consensus/consensus.go b/metropolis/node/core/consensus/consensus.go
index e749f7b..8da53d6 100644
--- a/metropolis/node/core/consensus/consensus.go
+++ b/metropolis/node/core/consensus/consensus.go
@@ -97,6 +97,7 @@
"net/url"
"time"
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/server/v3/embed"
@@ -143,6 +144,26 @@
}
}
+// GetEtcdMemberNodeId returns the node ID of an etcd member. It works even for
+// members which have not started, where member.Name is empty.
+func GetEtcdMemberNodeId(member *etcdserverpb.Member) string {
+ if member.Name != "" {
+ return member.Name
+ }
+ if len(member.PeerURLs) == 0 {
+ return ""
+ }
+ u, err := url.Parse(member.PeerURLs[0])
+ if err != nil {
+ return ""
+ }
+ nodeId, _, err := net.SplitHostPort(u.Host)
+ if err != nil {
+ return ""
+ }
+ return nodeId
+}
+
// Service is the etcd cluster member service. See package-level documentation
// for more information.
type Service struct {
@@ -497,6 +518,10 @@
if !member.IsLearner {
continue
}
+ if member.Name == "" {
+ // If the name is empty, the member has not started.
+ continue
+ }
// Always call PromoteMember since the metadata necessary to decide if we should
// is private. Luckily etcd already does consistency checks internally and will
// refuse to promote nodes that aren't connected or are still behind on