Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion cmd/mpcium/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ func main() {
Aliases: []string{"k"},
Usage: "Path to file containing password for decrypting .age encrypted node private key",
},
&cli.StringFlag{
Name: "peers",
Usage: "Path to peers.json file (syncs new peers to Consul on startup)",
},
&cli.BoolFlag{
Name: "debug",
Usage: "Enable debug logging",
Expand Down Expand Up @@ -146,6 +150,19 @@ func runNode(ctx context.Context, c *cli.Command) error {

consulClient := infra.GetConsulClient(environment)
keyinfoStore := keyinfo.NewStore(consulClient.KV())

// If --peers flag is provided, sync new peers from file to Consul
peersFile := c.String("peers")
if peersFile != "" {
filePeers, err := config.LoadPeersFromFile(peersFile)
if err != nil {
logger.Fatal("Failed to load peers from file", err)
}
if err := config.SyncPeersToConsul(consulClient.KV(), filePeers); err != nil {
logger.Fatal("Failed to sync peers to Consul", err)
}
}

peers := LoadPeersFromConsul(consulClient)
nodeID := GetIDFromName(nodeName, peers)

Expand Down Expand Up @@ -474,7 +491,7 @@ func NewConsulClient(addr string) *api.Client {

func LoadPeersFromConsul(consulClient *api.Client) []config.Peer { // Create a Consul Key-Value store client
kv := consulClient.KV()
peers, err := config.LoadPeersFromConsul(kv, "mpc_peers/")
peers, err := config.LoadPeersFromConsul(kv, config.PeersPrefix)
if err != nil {
logger.Fatal("Failed to load peers from Consul", err)
}
Expand Down
56 changes: 56 additions & 0 deletions pkg/config/peers.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package config

import (
"encoding/json"
"fmt"
"os"

"github.com/hashicorp/consul/api"
)
Expand Down Expand Up @@ -33,6 +35,60 @@ func LoadPeersFromConsul(kv *api.KV, prefix string) ([]Peer, error) {
return peers, nil
}

// LoadPeersFromFile loads peers from a JSON file (map[string]string: name -> ID)
func LoadPeersFromFile(path string) ([]Peer, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read peers file: %w", err)
}

var peersMap map[string]string
if err := json.Unmarshal(data, &peersMap); err != nil {
return nil, fmt.Errorf("failed to parse peers JSON: %w", err)
}

if len(peersMap) == 0 {
return nil, fmt.Errorf("no peers found in file %s", path)
}

peers := make([]Peer, 0, len(peersMap))
for name, id := range peersMap {
peers = append(peers, Peer{
ID: id,
Name: name,
})
}

return peers, nil
}

const PeersPrefix = "mpc_peers/"

// SyncPeersToConsul registers new peers from a file into Consul.
// Existing peers are skipped. New peers are registered and logged.
func SyncPeersToConsul(kv *api.KV, peers []Peer) error {
for _, peer := range peers {
key := PeersPrefix + peer.Name

existing, _, err := kv.Get(key, nil)
if err != nil {
return fmt.Errorf("failed to check existing key %s: %w", key, err)
}

if existing != nil {
continue
}

p := &api.KVPair{Key: key, Value: []byte(peer.ID)}
if _, err := kv.Put(p, nil); err != nil {
return fmt.Errorf("failed to register peer %s in Consul: %w", peer.Name, err)
}
fmt.Printf("New peer registered: %s with ID %s\n", peer.Name, peer.ID)
}

return nil
}

func GetNodeID(nodeName string, peers []Peer) string {
for _, peer := range peers {
if peer.Name == nodeName {
Expand Down
Loading