m/n/c/r/resolver: allow disabling curator updater

This allows some resolvers to not attempt to contact the cluster for
curator node updates. We use this in the Join and Register resolvers as
they don't have permission to access this data anywa.

We also generalize Resolver options into a proper WithX setup. We also
use this opportunity to move the resolver creation in node code outside
of the roleserver, as it should have been in the first place.

Change-Id: I1cc227711d784e07959371873029e09fc8cd1b99
Reviewed-on: https://review.monogon.dev/c/monogon/+/808
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/node/core/roleserve/roleserve.go b/metropolis/node/core/roleserve/roleserve.go
index 23076a4..5a0e2f6 100644
--- a/metropolis/node/core/roleserve/roleserve.go
+++ b/metropolis/node/core/roleserve/roleserve.go
@@ -63,6 +63,12 @@
 
 	// Network is a handle to the network service, used by workloads.
 	Network *network.Service
+
+	// resolver is the main, long-lived, authenticated cluster resolver that is used
+	// for all subsequent gRPC calls by the subordinates of the roleserver. It is
+	// created early in the roleserver lifecycle, and is seeded with node
+	// information as the first subordinate runs DialCurator().
+	Resolver *resolver.Resolver
 }
 
 // Service is the roleserver/“Role Server” service. See the package-level
@@ -80,23 +86,12 @@
 	heartbeat    *workerHeartbeat
 	kubernetes   *workerKubernetes
 	rolefetch    *workerRoleFetch
-
-	// resolver is the main, long-lived, authenticated cluster resolver that is used
-	// for all subsequent gRPC calls by the subordinates of the roleserver. It is
-	// created early in the roleserver lifecycle, and is seeded with node
-	// information as the first subordinate runs DialCurator().
-	resolver *resolver.Resolver
 }
 
 // New creates a Role Server services from a Config.
 func New(c Config) *Service {
-	// Run the resolver forever in the background, making sure to keep it as
-	// long-lived as possible.
-	rctx := context.Background()
-
 	s := &Service{
-		Config:   c,
-		resolver: resolver.New(rctx),
+		Config: c,
 	}
 	s.controlPlane = &workerControlPlane{
 		storageRoot: s.StorageRoot,
@@ -104,7 +99,7 @@
 		bootstrapData:     &s.bootstrapData,
 		clusterMembership: &s.ClusterMembership,
 		localRoles:        &s.localRoles,
-		resolver:          s.resolver,
+		resolver:          s.Resolver,
 	}
 
 	s.statusPush = &workerStatusPush{
@@ -144,11 +139,11 @@
 
 	// This is the first time we have the node ID, tell the resolver that it's
 	// available on the loopback interface.
-	s.resolver.AddOverride(nid, resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
+	s.Resolver.AddOverride(nid, resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
 
 	s.ClusterMembership.set(&ClusterMembership{
 		pubkey:   pubkey,
-		resolver: s.resolver,
+		resolver: s.Resolver,
 	})
 	s.bootstrapData.set(&bootstrapData{
 		nodePrivateKey:     privkey,
@@ -162,36 +157,32 @@
 func (s *Service) ProvideRegisterData(credentials identity.NodeCredentials, directory *cpb.ClusterDirectory) {
 	// This is the first time we have the node ID, tell the resolver that it's
 	// available on the loopback interface.
-	s.resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
+	s.Resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
 
 	s.ClusterMembership.set(&ClusterMembership{
 		remoteCurators: directory,
 		credentials:    &credentials,
 		pubkey:         credentials.PublicKey(),
-		resolver:       s.resolver,
+		resolver:       s.Resolver,
 	})
 }
 
 func (s *Service) ProvideJoinData(credentials identity.NodeCredentials, directory *cpb.ClusterDirectory) {
 	// This is the first time we have the node ID, tell the resolver that it's
 	// available on the loopback interface.
-	s.resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
+	s.Resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
 
 	s.ClusterMembership.set(&ClusterMembership{
 		remoteCurators: directory,
 		credentials:    &credentials,
 		pubkey:         credentials.PublicKey(),
-		resolver:       s.resolver,
+		resolver:       s.Resolver,
 	})
 }
 
 // Run the Role Server service, which uses intermediary workload launchers to
 // start/stop subordinate services as the Node's roles change.
 func (s *Service) Run(ctx context.Context) error {
-	s.resolver.SetLogger(func(f string, args ...interface{}) {
-		supervisor.Logger(ctx).WithAddedStackDepth(2).Infof(f, args...)
-	})
-
 	supervisor.Run(ctx, "controlplane", s.controlPlane.run)
 	supervisor.Run(ctx, "kubernetes", s.kubernetes.run)
 	supervisor.Run(ctx, "statuspush", s.statusPush.run)