adding cypher graph generation utitlies

This commit is contained in:
Winzlieb - 2021-12-28 18:43:42 +01:00
parent cffdd7bbd7
commit 1f2cbd03b8
2 changed files with 172 additions and 1 deletions

View File

@ -40,6 +40,7 @@ let
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; };
mkRootfs = hostName:
@ -92,7 +93,7 @@ let
inherit self nixpkgs system;
};
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
encrypt-secrets decrypt-secrets switch-to-production
;

View File

@ -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})\"}]}"
'';
}