# Standalone cluster-config.json generator # Usage: nix-build cluster-config-generator.nix --argstr hostname node01 --argstr clusterName plasmacloud { pkgs ? import {} , hostname ? "node01" , clusterName ? "plasmacloud" , topologyFile ? ./example-topology.nix }: let # Import topology module lib = pkgs.lib; # Evaluate the topology file topologyEval = import topologyFile { inherit lib; }; # Get the cluster configuration cluster = topologyEval.nix-nos.clusters.${clusterName} or (throw "Cluster ${clusterName} not found"); node = cluster.nodes.${hostname} or (throw "Node ${hostname} not found in cluster ${clusterName}"); # Determine bootstrap node controlPlaneNodes = lib.filter (n: cluster.nodes.${n}.role == "control-plane") (lib.attrNames cluster.nodes); bootstrapNodeName = if cluster.bootstrapNode != null then cluster.bootstrapNode else lib.head controlPlaneNodes; isBootstrap = hostname == bootstrapNodeName; # Leader URL (bootstrap node's API endpoint) bootstrapNode = cluster.nodes.${bootstrapNodeName}; leaderUrl = "https://${bootstrapNode.ip}:${toString bootstrapNode.apiPort}"; # Initial peers for Raft cluster initialPeers = map (nodeName: { id = nodeName; addr = "${cluster.nodes.${nodeName}.ip}:${toString cluster.nodes.${nodeName}.raftPort}"; }) controlPlaneNodes; # FlareDB peers (all control-plane nodes) flaredbPeers = map (nodeName: "${cluster.nodes.${nodeName}.ip}:${toString (cluster.nodes.${nodeName}.apiPort + 100)}" ) controlPlaneNodes; # Generate cluster config clusterConfig = { node_id = hostname; node_role = node.role; bootstrap = isBootstrap; cluster_name = cluster.name; leader_url = leaderUrl; raft_addr = "${node.ip}:${toString node.raftPort}"; initial_peers = initialPeers; flaredb_peers = flaredbPeers; services = node.services; metadata = node.metadata; }; # Convert to JSON configJson = builtins.toJSON clusterConfig; in pkgs.writeTextFile { name = "cluster-config-${hostname}.json"; text = configJson; destination = "/cluster-config.json"; }