Repository: bacalhau-project/bacalhau (language: python)

Issue:
Add node command to delete nodes from the info store
Nodes are currently always kept in the node info store once they have been seen.  There are likely use-cases where we want to manually delete nodes from the store.  We should add `node delete`


Discussion / hints:

Fix patch:
diff --git a/cmd/cli/node/root.go b/cmd/cli/node/root.go
index 65d7934831..18c30f2a30 100644
--- a/cmd/cli/node/root.go
+++ b/cmd/cli/node/root.go
@@ -23,5 +23,8 @@ func NewCmd() *cobra.Command {
 	// Reject Action
 	cmd.AddCommand(NewActionCmd(apimodels.NodeActionReject))
 
+	// Reject Action
+	cmd.AddCommand(NewActionCmd(apimodels.NodeActionDelete))
+
 	return cmd
 }
diff --git a/pkg/node/manager/node_manager.go b/pkg/node/manager/node_manager.go
index 3d87f17a12..abb6acf809 100644
--- a/pkg/node/manager/node_manager.go
+++ b/pkg/node/manager/node_manager.go
@@ -189,7 +189,7 @@ func (n *NodeManager) Delete(ctx context.Context, nodeID string) error {
 // Approve is used to approve a node for joining the cluster along with a specific
 // reason for the approval (for audit). The return values denote success and any
 // failure of the operation as a human readable string.
-func (n *NodeManager) Approve(ctx context.Context, nodeID string, reason string) (bool, string) {
+func (n *NodeManager) ApproveAction(ctx context.Context, nodeID string, reason string) (bool, string) {
 	info, err := n.nodeInfo.GetByPrefix(ctx, nodeID)
 	if err != nil {
 		return false, err.Error()
@@ -212,7 +212,7 @@ func (n *NodeManager) Approve(ctx context.Context, nodeID string, reason string)
 // Reject is used to reject a node from joining the cluster along with a specific
 // reason for the rejection (for audit). The return values denote success and any
 // failure of the operation as a human readable string.
-func (n *NodeManager) Reject(ctx context.Context, nodeID string, reason string) (bool, string) {
+func (n *NodeManager) RejectAction(ctx context.Context, nodeID string, reason string) (bool, string) {
 	info, err := n.nodeInfo.GetByPrefix(ctx, nodeID)
 	if err != nil {
 		return false, err.Error()
@@ -232,5 +232,21 @@ func (n *NodeManager) Reject(ctx context.Context, nodeID string, reason string)
 	return true, ""
 }
 
+// Reject is used to reject a node from joining the cluster along with a specific
+// reason for the rejection (for audit). The return values denote success and any
+// failure of the operation as a human readable string.
+func (n *NodeManager) DeleteAction(ctx context.Context, nodeID string, reason string) (bool, string) {
+	info, err := n.nodeInfo.GetByPrefix(ctx, nodeID)
+	if err != nil {
+		return false, err.Error()
+	}
+
+	if err := n.nodeInfo.Delete(ctx, info.NodeID); err != nil {
+		return false, fmt.Sprintf("failed to delete nodeinfo: %s", err)
+	}
+
+	return true, ""
+}
+
 var _ compute.ManagementEndpoint = (*NodeManager)(nil)
 var _ routing.NodeInfoStore = (*NodeManager)(nil)
diff --git a/pkg/publicapi/apimodels/node.go b/pkg/publicapi/apimodels/node.go
index 27f5cb944d..05ebf60b65 100644
--- a/pkg/publicapi/apimodels/node.go
+++ b/pkg/publicapi/apimodels/node.go
@@ -59,6 +59,7 @@ type NodeAction string
 const (
 	NodeActionApprove NodeAction = "approve"
 	NodeActionReject  NodeAction = "reject"
+	NodeActionDelete  NodeAction = "delete"
 )
 
 func (n NodeAction) Description() string {
@@ -67,10 +68,12 @@ func (n NodeAction) Description() string {
 		return "Approve a node whose membership is pending"
 	case NodeActionReject:
 		return "Reject a node whose membership is pending"
+	case NodeActionDelete:
+		return "Delete a node from the cluster."
 	}
 	return ""
 }
 
 func (n NodeAction) IsValid() bool {
-	return n == NodeActionApprove || n == NodeActionReject
+	return n == NodeActionApprove || n == NodeActionReject || n == NodeActionDelete
 }
diff --git a/pkg/publicapi/endpoint/orchestrator/node.go b/pkg/publicapi/endpoint/orchestrator/node.go
index bae1810d4d..c4817f5341 100644
--- a/pkg/publicapi/endpoint/orchestrator/node.go
+++ b/pkg/publicapi/endpoint/orchestrator/node.go
@@ -148,9 +148,11 @@ func (e *Endpoint) updateNode(c echo.Context) error {
 
 	var action func(context.Context, string, string) (bool, string)
 	if args.Action == string(apimodels.NodeActionApprove) {
-		action = e.nodeManager.Approve
+		action = e.nodeManager.ApproveAction
 	} else if args.Action == string(apimodels.NodeActionReject) {
-		action = e.nodeManager.Reject
+		action = e.nodeManager.RejectAction
+	} else if args.Action == string(apimodels.NodeActionDelete) {
+		action = e.nodeManager.DeleteAction
 	} else {
 		action = func(context.Context, string, string) (bool, string) {
 			return false, "unsupported action"


Test patch:
diff --git a/cmd/cli/node/action_test.go b/cmd/cli/node/action_test.go
index 76317ad6bb..7530247412 100644
--- a/cmd/cli/node/action_test.go
+++ b/cmd/cli/node/action_test.go
@@ -75,6 +75,23 @@ func (s *NodeActionSuite) TestListNodes() {
 	)
 	s.Require().NoError(err)
 	s.Require().Contains(out, "Ok")
+
+	// Delete the node
+	_, out, err = s.ExecuteTestCobraCommand(
+		"node",
+		"delete",
+		nodeID,
+	)
+	s.Require().NoError(err)
+	s.Require().Contains(out, "Ok")
+
+	_, out, err = s.ExecuteTestCobraCommand(
+		"node",
+		"list",
+		"--output", "csv",
+	)
+	s.Require().NoError(err)
+	s.Require().NotContains(out, nodeID)
 }
 
 func getCells(output string, lineNo int) []string {