m/n/c/curator: add Management.UpdateNodeRoles

This provides an API for node role adjustments.

While changes to KubernetesWorker role are registered, not all side
effects are accounted for as of now. Specifically, disabling this role
within a node won't lead to its removal from the Kubernetes cluster.

Change-Id: Ie8e65990108b8cf82afecf3374f40f2e857fa776
Reviewed-on: https://review.monogon.dev/c/monogon/+/767
Tested-by: Jenkins CI
Reviewed-by: Sergiusz Bazanski <serge@monogon.tech>
diff --git a/metropolis/node/core/consensus/status.go b/metropolis/node/core/consensus/status.go
index e2b15f8..a19fa14 100644
--- a/metropolis/node/core/consensus/status.go
+++ b/metropolis/node/core/consensus/status.go
@@ -76,6 +76,11 @@
 	// stopped is set to true if the underlying service has been stopped or hasn't
 	// yet been started.
 	stopped bool
+
+	// noClusterMemberManagement disables etcd cluster member management in
+	// UpdateNodeRoles. This is currently necessary in order to test the call,
+	// due to limitations of the test harness.
+	noClusterMemberManagement bool
 }
 
 // Running returns true if this status represents a running consensus service
@@ -188,7 +193,7 @@
 		return nil, fmt.Errorf("could not retrieve initial CRL: %w", err)
 	}
 
-	if !newExists {
+	if !newExists && !s.noClusterMemberManagement {
 		addr := fmt.Sprintf("https://%s", net.JoinHostPort(name, strconv.Itoa(port)))
 		if _, err := s.cl.MemberAddAsLearner(ctx, []string{addr}); err != nil {
 			return nil, fmt.Errorf("could not add new member as learner: %w", err)
diff --git a/metropolis/node/core/consensus/testhelpers.go b/metropolis/node/core/consensus/testhelpers.go
index 32bbc46..f69f73e 100644
--- a/metropolis/node/core/consensus/testhelpers.go
+++ b/metropolis/node/core/consensus/testhelpers.go
@@ -27,8 +27,9 @@
 
 	tsh := testServiceHandle{}
 	st := &Status{
-		cl: cl,
-		ca: ca,
+		cl:                        cl,
+		ca:                        ca,
+		noClusterMemberManagement: true,
 	}
 	etcdPKI, err := st.pkiClient()
 	if err != nil {