m/n/core/network/hostsfile: fix stale curator entries

This prevents the cluster from getting in a state where nodes are not
aware of new control plane nodes on restart (because the only thing that
changed about them is their role, not their IP address).

This fixes the deduplication to also take into consideration role
changes.

Change-Id: I184916427650fdbf68fb0fdf5ced365b94af190e
Reviewed-on: https://review.monogon.dev/c/monogon/+/2880
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/core/network/hostsfile/hostsfile.go b/metropolis/node/core/network/hostsfile/hostsfile.go
index b82ecbe..1bf0c53 100644
--- a/metropolis/node/core/network/hostsfile/hostsfile.go
+++ b/metropolis/node/core/network/hostsfile/hostsfile.go
@@ -27,13 +27,12 @@
 	"google.golang.org/grpc"
 	"google.golang.org/protobuf/proto"
 
+	ipb "source.monogon.dev/metropolis/node/core/curator/proto/api"
 	"source.monogon.dev/metropolis/node/core/curator/watcher"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 	"source.monogon.dev/metropolis/node/core/network"
 	"source.monogon.dev/metropolis/pkg/event"
 	"source.monogon.dev/metropolis/pkg/supervisor"
-
-	ipb "source.monogon.dev/metropolis/node/core/curator/proto/api"
 	cpb "source.monogon.dev/metropolis/proto/common"
 )
 
@@ -279,7 +278,13 @@
 			return true
 		},
 		EqualsFn: func(a *ipb.Node, b *ipb.Node) bool {
-			return a.Status.ExternalAddress == b.Status.ExternalAddress
+			if a.Status.ExternalAddress != b.Status.ExternalAddress {
+				return false
+			}
+			if (a.Roles.ConsensusMember != nil) != (b.Roles.ConsensusMember != nil) {
+				return false
+			}
+			return true
 		},
 		OnNewUpdated: func(new *ipb.Node) error {
 			nodes[new.Id] = nodeInfo{