blob: 62ab7bd68a8f45a2d2af793ca96bed854fdcddbd [file] [log] [blame]
Mateusz Zalegac437dc42022-07-07 13:01:43 +02001package main
2
3import (
4 "context"
5 "fmt"
Mateusz Zalegac437dc42022-07-07 13:01:43 +02006 "log"
Tim Windelschmidtb765f242024-05-08 01:40:02 +02007 "os"
8 "os/signal"
Mateusz Zalegac437dc42022-07-07 13:01:43 +02009
10 "github.com/spf13/cobra"
11
Mateusz Zalega18a67b02022-08-02 13:37:50 +020012 "source.monogon.dev/metropolis/cli/metroctl/core"
Mateusz Zalegac437dc42022-07-07 13:01:43 +020013 "source.monogon.dev/metropolis/node/core/identity"
14 "source.monogon.dev/metropolis/proto/api"
15)
16
17var approveCmd = &cobra.Command{
18 Short: "Approves a candidate node, if specified; lists nodes pending approval otherwise.",
19 Use: "approve [node-id]",
20 Args: cobra.MaximumNArgs(1), // One positional argument: node ID
21 Run: doApprove,
22}
23
24func init() {
25 rootCmd.AddCommand(approveCmd)
26}
27
Mateusz Zalegac437dc42022-07-07 13:01:43 +020028// nodeById returns the node matching id, if it exists within nodes.
29func nodeById(nodes []*api.Node, id string) *api.Node {
30 for _, n := range nodes {
31 if identity.NodeID(n.Pubkey) == id {
32 return n
33 }
34 }
35 return nil
36}
37
38func doApprove(cmd *cobra.Command, args []string) {
Tim Windelschmidtb765f242024-05-08 01:40:02 +020039 ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
Mateusz Zalegadb75e212022-08-04 17:31:34 +020040 cc := dialAuthenticated(ctx)
Mateusz Zalegac437dc42022-07-07 13:01:43 +020041 mgmt := api.NewManagementClient(cc)
42
43 // Get a list of all nodes pending approval by calling Management.GetNodes.
44 // We need this list regardless of whether we're actually approving nodes, or
45 // just listing them.
Mateusz Zalega18a67b02022-08-02 13:37:50 +020046 nodes, err := core.GetNodes(ctx, mgmt, "node.state == NODE_STATE_NEW")
Mateusz Zalegac437dc42022-07-07 13:01:43 +020047 if err != nil {
48 log.Fatalf("While fetching a list of nodes pending approval: %v", err)
49 }
50
51 if len(args) == 0 {
52 // If no id was given, just list the nodes pending approval.
53 if len(nodes) != 0 {
54 for _, n := range nodes {
Lorenz Brun1600d9b2023-06-14 20:00:59 +020055 fmt.Println(identity.NodeID(n.Pubkey))
Mateusz Zalegac437dc42022-07-07 13:01:43 +020056 }
57 } else {
58 log.Print("There are no nodes pending approval at this time.")
59 }
60 } else {
Mateusz Zalega4c078782022-08-12 19:03:53 +020061 // Otherwise, try to approve the nodes matching the supplied ids.
62 for _, tgtNodeId := range args {
63 n := nodeById(nodes, tgtNodeId)
64 if n == nil {
65 log.Fatalf("Couldn't find a new node matching id %s", tgtNodeId)
66 }
Tim Windelschmidt2d5ae8f2024-04-18 23:11:53 +020067 // nolint:SA5011
Mateusz Zalega4c078782022-08-12 19:03:53 +020068 _, err := mgmt.ApproveNode(ctx, &api.ApproveNodeRequest{
69 Pubkey: n.Pubkey,
70 })
71 if err != nil {
72 log.Fatalf("While approving node %s: %v", tgtNodeId, err)
73 }
74 log.Printf("Approved node %s.", tgtNodeId)
Mateusz Zalegac437dc42022-07-07 13:01:43 +020075 }
Mateusz Zalegac437dc42022-07-07 13:01:43 +020076 }
77}