Based on the changes, I'll generate a concise commit message that captures the essence of the modifications:

feat: add node registration verification and idle loop for joined nodes
This commit is contained in:
Tanishq Dubey 2025-05-17 13:19:16 -04:00
parent 8bdccdc8c7
commit e4a19a6bb8
No known key found for this signature in database
GPG Key ID: CFC1931B84DFC3F9
2 changed files with 107 additions and 2 deletions

View File

@ -46,6 +46,14 @@ and obtains the necessary credentials to participate in the cluster.`,
Run: runJoin,
}
verifyCmd = &cobra.Command{
Use: "verify",
Short: "Verifies node registration in etcd.",
Long: `Connects to etcd and verifies that a node is properly registered.
This is useful for testing and debugging.`,
Run: runVerify,
}
// Global flags / config paths
clusterConfigPath string
nodeName string
@ -55,6 +63,9 @@ and obtains the necessary credentials to participate in the cluster.`,
advertiseAddr string
leaderCACert string
etcdPeer bool
// Verify command flags
etcdEndpoint string
)
const (
@ -84,8 +95,13 @@ func init() {
joinCmd.MarkFlagRequired("leader-api")
joinCmd.MarkFlagRequired("advertise-address")
// Verify command flags
verifyCmd.Flags().StringVar(&etcdEndpoint, "etcd-endpoint", "http://localhost:2379", "Etcd endpoint to connect to")
verifyCmd.Flags().StringVar(&nodeName, "node-name", defaultHostName, "Name of the node to verify")
rootCmd.AddCommand(initCmd)
rootCmd.AddCommand(joinCmd)
rootCmd.AddCommand(verifyCmd)
}
func runInit(cmd *cobra.Command, args []string) {
@ -322,8 +338,44 @@ func runJoin(cmd *cobra.Command, args []string) {
}
log.Printf("Successfully joined cluster. Node is ready.")
// In a real implementation, we would start the agent's main loop here
// For now, we'll just exit successfully
// Setup signal handling for graceful shutdown
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
// Stay up in an idle loop until interrupted
log.Printf("Node %s is now running. Press Ctrl+C to exit.", nodeName)
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
log.Println("Received shutdown signal. Exiting...")
return
case <-ticker.C:
log.Printf("Node %s is still running...", nodeName)
}
}
}
func runVerify(cmd *cobra.Command, args []string) {
log.Printf("Verifying node registration for node: %s", nodeName)
log.Printf("Connecting to etcd at: %s", etcdEndpoint)
// Create etcd client
etcdStore, err := store.NewEtcdStore([]string{etcdEndpoint}, nil)
if err != nil {
log.Fatalf("Failed to create etcd store client: %v", err)
}
defer etcdStore.Close()
// Verify node registration
if err := cli.VerifyNodeRegistration(etcdStore, nodeName); err != nil {
log.Fatalf("Failed to verify node registration: %v", err)
}
log.Printf("Node registration verification complete.")
}
func main() {

View File

@ -0,0 +1,53 @@
package cli
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
"git.dws.rip/dubey/kat/internal/store"
)
// NodeRegistration represents the data stored in etcd for a node
type NodeRegistration struct {
UID string `json:"uid"`
AdvertiseAddr string `json:"advertiseAddr"`
WireguardPubKey string `json:"wireguardPubKey"`
JoinTimestamp int64 `json:"joinTimestamp"`
}
// VerifyNodeRegistration checks if a node is registered in etcd
func VerifyNodeRegistration(etcdStore store.StateStore, nodeName string) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Construct the key for the node registration
nodeRegKey := fmt.Sprintf("/kat/nodes/registration/%s", nodeName)
// Get the node registration from etcd
kv, err := etcdStore.Get(ctx, nodeRegKey)
if err != nil {
return fmt.Errorf("failed to get node registration from etcd: %w", err)
}
// Parse the node registration
var nodeReg NodeRegistration
if err := json.Unmarshal(kv.Value, &nodeReg); err != nil {
return fmt.Errorf("failed to parse node registration: %w", err)
}
// Print the node registration details
log.Printf("Node Registration Details:")
log.Printf(" Node Name: %s", nodeName)
log.Printf(" Node UID: %s", nodeReg.UID)
log.Printf(" Advertise Address: %s", nodeReg.AdvertiseAddr)
log.Printf(" WireGuard Public Key: %s", nodeReg.WireguardPubKey)
// Convert timestamp to human-readable format
joinTime := time.Unix(nodeReg.JoinTimestamp, 0)
log.Printf(" Join Timestamp: %s (%d)", joinTime.Format(time.RFC3339), nodeReg.JoinTimestamp)
return nil
}