adding cypher graph generation utitlies
This commit is contained in:
parent
cffdd7bbd7
commit
1f2cbd03b8
|
@ -40,6 +40,7 @@ let
|
||||||
cp secrets-production.nix secrets.nix
|
cp secrets-production.nix secrets.nix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
network-cypher-graphs = import ./network-cypher-graphs.nix { inherit config pkgs; };
|
||||||
network-graphs = import ./network-graphs.nix { inherit config pkgs; };
|
network-graphs = import ./network-graphs.nix { inherit config pkgs; };
|
||||||
|
|
||||||
mkRootfs = hostName:
|
mkRootfs = hostName:
|
||||||
|
@ -92,7 +93,7 @@ let
|
||||||
inherit self nixpkgs system;
|
inherit self nixpkgs system;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
rootfs-packages // vm-packages // device-templates // network-graphs // starlink // subnetplans // {
|
rootfs-packages // vm-packages // device-templates // network-graphs // network-cypher-graphs // starlink // subnetplans // {
|
||||||
inherit all-rootfs export-openwrt-models export-config dns-slaves
|
inherit all-rootfs export-openwrt-models export-config dns-slaves
|
||||||
encrypt-secrets decrypt-secrets switch-to-production
|
encrypt-secrets decrypt-secrets switch-to-production
|
||||||
;
|
;
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
inherit (pkgs) lib runCommand curl;
|
||||||
|
|
||||||
|
netColor = net:
|
||||||
|
if net == "core"
|
||||||
|
then "grey"
|
||||||
|
else if net == "mgmt"
|
||||||
|
then "brown"
|
||||||
|
else if builtins.elem net [ "c3d2" "serv" "cluster" ]
|
||||||
|
then "green"
|
||||||
|
else if builtins.match "up.+" net != null ||
|
||||||
|
builtins.match "anon.+" net != null
|
||||||
|
then "red"
|
||||||
|
else if builtins.match "priv.+" net != null
|
||||||
|
then "blue"
|
||||||
|
else "black";
|
||||||
|
|
||||||
|
dedupLinks = links:
|
||||||
|
builtins.attrValues (
|
||||||
|
builtins.foldl' (result: { pair, attrs ? {}, startLabel ? "" }:
|
||||||
|
let
|
||||||
|
peer1 = builtins.elemAt pair 0;
|
||||||
|
peer2 = builtins.elemAt pair 1;
|
||||||
|
sorted =
|
||||||
|
if peer1 < peer2
|
||||||
|
then { from = peer1; to = peer2; }
|
||||||
|
else { from = peer2; to = peer1; };
|
||||||
|
key = with sorted; "${from} ${to}";
|
||||||
|
prevAttrs =
|
||||||
|
if result ? ${key}
|
||||||
|
then result.${key}.attrs
|
||||||
|
else {};
|
||||||
|
newAttrs = attrs // (
|
||||||
|
if peer1 < peer2
|
||||||
|
then { taillabel = startLabel; }
|
||||||
|
else { headlabel = startLabel; }
|
||||||
|
);
|
||||||
|
in result // {
|
||||||
|
"${key}" = {
|
||||||
|
inherit (sorted) from to;
|
||||||
|
attrs = prevAttrs // newAttrs;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) {} links
|
||||||
|
);
|
||||||
|
|
||||||
|
toCypher = { nodes, links, ... }: ''
|
||||||
|
${lib.concatMapStringsSep " " (name:
|
||||||
|
let
|
||||||
|
nodeAttrs = nodes.${name};
|
||||||
|
id = builtins.replaceStrings ["-"] ["_"] name;
|
||||||
|
nodeType = nodeAttrs.type;
|
||||||
|
in ''
|
||||||
|
CREATE (${id}:`${nodeType}`
|
||||||
|
{label:"${name}",
|
||||||
|
${lib.concatMapStringsSep ", " (attr:
|
||||||
|
let
|
||||||
|
value = nodeAttrs.${attr};
|
||||||
|
in
|
||||||
|
if builtins.isString value
|
||||||
|
then "${attr}:\"${value}\""
|
||||||
|
else "${attr}:${toString value}"
|
||||||
|
) (builtins.attrNames nodeAttrs)}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
'') (builtins.attrNames nodes)}
|
||||||
|
|
||||||
|
${lib.concatMapStringsSep " " ({ from, to, attrs }:
|
||||||
|
let
|
||||||
|
idFrom = builtins.replaceStrings ["-"] ["_"] from;
|
||||||
|
idTo = builtins.replaceStrings ["-"] ["_"] to;
|
||||||
|
in ''
|
||||||
|
CREATE (${idFrom})-[:CONNECTED_TO
|
||||||
|
{${lib.concatMapStringsSep ", " (attr:
|
||||||
|
let
|
||||||
|
value = attrs.${attr};
|
||||||
|
in
|
||||||
|
if builtins.isString value
|
||||||
|
then "${attr}:\"${value}\""
|
||||||
|
else "${attr}:${toString value}"
|
||||||
|
) (builtins.attrNames attrs)}
|
||||||
|
}]->(${idTo})
|
||||||
|
'') (dedupLinks links)}
|
||||||
|
'';
|
||||||
|
|
||||||
|
cypherGraph = args@{ name, ... }:
|
||||||
|
runCommand "${name}.cypher" {
|
||||||
|
src = builtins.toFile "${name}.cypher" (
|
||||||
|
toCypher args
|
||||||
|
);
|
||||||
|
} ''
|
||||||
|
sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' $src | tr -d '\n' > $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
in rec {
|
||||||
|
# Layer 2
|
||||||
|
physical-cypher-graph = cypherGraph {
|
||||||
|
name = "physical";
|
||||||
|
nodes =
|
||||||
|
builtins.mapAttrs (_: { role, ... }: {
|
||||||
|
type = {
|
||||||
|
switch = "Switch";
|
||||||
|
server = "Server";
|
||||||
|
container = "Container";
|
||||||
|
ap = "AccessPoint";
|
||||||
|
client = "Client";
|
||||||
|
}.${role};
|
||||||
|
}) (
|
||||||
|
lib.filterAttrs (_: { links, ... }:
|
||||||
|
links != {}
|
||||||
|
) config.site.hosts
|
||||||
|
) // builtins.mapAttrs (_: _: {
|
||||||
|
type = "Other";
|
||||||
|
}) (
|
||||||
|
lib.filterAttrs (net: _:
|
||||||
|
builtins.match "up.*" net != null
|
||||||
|
) config.site.net
|
||||||
|
);
|
||||||
|
links =
|
||||||
|
builtins.concatMap (hostName:
|
||||||
|
map (link: {
|
||||||
|
pair = [ hostName link ];
|
||||||
|
startLabel = ( #lib.optionalString (config.site.hosts.${hostName}.links ? ${link}) (
|
||||||
|
lib.concatStringsSep ","
|
||||||
|
config.site.hosts.${hostName}.links.${link}.ports
|
||||||
|
);
|
||||||
|
}) (
|
||||||
|
builtins.filter (link:
|
||||||
|
config.site.hosts ? ${link}
|
||||||
|
||
|
||||||
|
builtins.match "up.*" link != null
|
||||||
|
) (builtins.attrNames config.site.hosts.${hostName}.links)
|
||||||
|
)
|
||||||
|
) (builtins.attrNames config.site.hosts);
|
||||||
|
};
|
||||||
|
# Layer 3
|
||||||
|
logical-cypher-graph =
|
||||||
|
let
|
||||||
|
containers =
|
||||||
|
lib.filterAttrs (_: { isRouter, role, ... }:
|
||||||
|
role == "container"
|
||||||
|
) config.site.hosts;
|
||||||
|
in
|
||||||
|
cypherGraph {
|
||||||
|
name = "logical";
|
||||||
|
nodes =
|
||||||
|
builtins.foldl' (result: hostName:
|
||||||
|
result // {
|
||||||
|
"${hostName}".type = "Container";
|
||||||
|
} // builtins.mapAttrs (_: _: {
|
||||||
|
type = "Container";
|
||||||
|
}) containers.${hostName}.interfaces
|
||||||
|
) {} (builtins.attrNames containers);
|
||||||
|
links =
|
||||||
|
builtins.concatMap (hostName:
|
||||||
|
map (net: {
|
||||||
|
pair = [ hostName net ];
|
||||||
|
attrs.color = netColor net;
|
||||||
|
}) (builtins.attrNames containers.${hostName}.interfaces)
|
||||||
|
) (builtins.attrNames containers);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
import-network-graphs = runCommand "import-network-graphs" {} ''
|
||||||
|
${curl}/bin/curl -X POST -H 'Content-type: application/json' http://localhost:7474/db/data/transaction/commit -d "{\"statements\": [{\"statement\": \"$(cat ${physical-cypher-graph})\"}]}"
|
||||||
|
${curl}/bin/curl -X POST -H 'Content-type: application/json' http://localhost:7474/db/data/transaction/commit -d "{\"statements\": [{\"statement\": \"$(cat ${logical-cypher-graph})\"}]}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue