From 0f51c7d542227f1f4c9895db36007b9d95963d99 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 29 Oct 2024 21:13:43 +0100 Subject: utils: networks --- utils/Makefile | 5 + utils/ipam/yaml_model/yaml_model.go | 36 +++++++ utils/main.go | 178 +---------------------------------- utils/networks/networks.go | 181 ++++++++++++++++++++++++++++++++++++ utils/routers/routers.go | 4 + utils/yaml_ipam/yaml_ipam.go | 26 ------ 6 files changed, 228 insertions(+), 202 deletions(-) create mode 100644 utils/Makefile create mode 100644 utils/ipam/yaml_model/yaml_model.go create mode 100644 utils/networks/networks.go create mode 100644 utils/routers/routers.go delete mode 100644 utils/yaml_ipam/yaml_ipam.go (limited to 'utils') diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..77e67a3 --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,5 @@ +all: utils + go run main.go > ../ansible/group_vars/all/ipam.tmp.dot && dot -Tpng ../ansible/group_vars/all/ipam.tmp.dot > ../ansible/group_vars/all/ipam.tmp.png + +utils: + go build diff --git a/utils/ipam/yaml_model/yaml_model.go b/utils/ipam/yaml_model/yaml_model.go new file mode 100644 index 0000000..6e5b0f8 --- /dev/null +++ b/utils/ipam/yaml_model/yaml_model.go @@ -0,0 +1,36 @@ +package yaml_model + +import "gopkg.in/yaml.v3" + +type Ipam struct { + Ipam6 Ipam6 `yaml:"ipam6,omitempty"` + Routers []Router `yaml:"routers,omitempty"` +} + +type Ipam6 struct { + Networks map[string]Network6Yaml `yaml:"networks"` +} + +type Network6Yaml struct { + Range string `yaml:"range"` + Hosts map[string]string `yaml:"hosts"` +} + +type Router struct { + As string `yaml:"as,omitempty"` + Peer []Peer `yaml:"peer,omitempty"` +} + +type Peer struct { + Name string `yaml:"name"` +} + +func Parse(bs []byte) (Ipam, error) { + var ipam Ipam + err := yaml.Unmarshal(bs, &ipam) + if err != nil { + return Ipam{}, err + } + + return ipam, nil +} diff --git a/utils/main.go b/utils/main.go index 42adbd6..af3a4a7 100644 --- a/utils/main.go +++ b/utils/main.go @@ -1,189 +1,15 @@ package main import ( - "cmp" "fmt" - "log" - "net/netip" "os" - "slices" - "utils/yaml_ipam" + "utils/networks" ) func main() { - err := work() + err := networks.RunNetworks() if err != nil { _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } } - -func work() error { - ipamYaml := "../ansible/group_vars/all/ipam.yml" - bs, err := os.ReadFile(ipamYaml) - if err != nil { - return err - } - - ipam, err := loadIpam(bs) - if err != nil { - return err - } - - networks := slices.SortedFunc(slices.Values(ipam.networks), CompareNetwork) - roots := slices.SortedFunc(slices.Values(ipam.FindRoots()), CompareNetwork) - - fmt.Printf("digraph {\n") - //fmt.Printf(" layout=dot\n") - //fmt.Printf(" layout=twopi\n") - fmt.Printf(" layout=fdp\n") - //fmt.Printf(" layout=circo\n") - //fmt.Printf(" layout=neato\n") - //fmt.Printf(" ranksep=3\n") - //fmt.Printf(" ratio=auto\n") - //fmt.Printf(" rankdir=LR\n") - //fmt.Printf(" rankdir=RL\n") - fmt.Printf(" rankdir=TB\n") - //fmt.Printf(" sep=3\n") - //fmt.Printf(" overlap_scaling=-10\n") - fmt.Printf("node [len=10];") - fmt.Printf("node [shape=box];") - fmt.Printf("overlap=false") - - fmt.Printf("\n") - fmt.Printf(" # Nodes\n") - for _, n := range networks { - fmt.Printf(" %s [ label = \"%s\\n%s\"];\n", n.name, n.name, n.prefix) - } - - fmt.Printf("\n") - fmt.Printf(" # Roots\n") - for _, n := range roots { - fmt.Printf(" %s [ root = true ];\n", n.name) - } - - fmt.Printf("\n") - fmt.Printf(" # Relationships\n") - for _, n := range networks { - for _, c := range ipam.networks { - if c.parent == n { - fmt.Printf(" %s -> %s", n.name, c.name) - fmt.Printf(";\n") - } - } - } - fmt.Printf("}\n") - - return nil -} - -func loadIpam(bs []byte) (*Ipam, error) { - parsed, err := yaml_ipam.Parse(bs) - if err != nil { - return nil, err - } - - ipam_, err := processNetworks(parsed.Ipam6.Networks) - if err != nil { - return nil, err - } - - ipam_.ResolveParents() - - return ipam_, nil -} - -type Ipam struct { - networks []*Network -} - -func contains(a, b netip.Prefix) bool { - return b.Bits() > a.Bits() && b.Overlaps(a) -} - -func (ipam *Ipam) ResolveParents() { - for _, n := range ipam.networks { - log.Printf("network %s/%s", n.name, n.prefix) - for _, p := range ipam.networks { - if n == p { - continue - } - log.Printf(" candidate %s/%s", p.name, p.prefix) - if contains(p.prefix, n.prefix) { - if n.parent == nil { - log.Printf(" found parent %s/%s", p.name, p.prefix) - n.parent = p - } else { - if n.parent.prefix.Bits() < p.prefix.Bits() { - log.Printf(" found better parent %s/%s", p.name, p.prefix) - n.parent = p - } - } - } - } - } - - return -} - -func (ipam *Ipam) FindRoots() []*Network { - var ns []*Network - - for _, n := range ipam.networks { - if n.parent == nil { - ns = append(ns, n) - } - } - - return ns -} - -type Network struct { - name string - parent *Network - prefix netip.Prefix - hosts []networkHost -} - -func CompareNetwork(a, b *Network) int { - return cmp.Compare(a.name, b.name) -} - -func (n *Network) Compare(other *Network) int { - return cmp.Compare(n.name, other.name) -} - -type networkHost struct { - name string - address netip.Addr -} - -func processNetworks(networks map[string]yaml_ipam.Network6Yaml) (*Ipam, error) { - var ns []*Network - - for name, net := range networks { - log.Printf("Processing net %v\n", name) - prefix, err := netip.ParsePrefix(net.Range) - if err != nil { - return nil, fmt.Errorf("error parsing net range: %v", err) - } - log.Printf("prefix: %s", prefix.String()) - - n := Network{name: name, prefix: prefix} - for hostname, a := range net.Hosts { - addr, err := netip.ParseAddr(a) - if err != nil { - return nil, fmt.Errorf("network: %s, unable to parse host address %s", n.name, a) - } - - n.hosts = append(n.hosts, networkHost{ - name: hostname, - address: addr, - }) - } - - ns = append(ns, &n) - } - - return &Ipam{networks: ns}, nil -} diff --git a/utils/networks/networks.go b/utils/networks/networks.go new file mode 100644 index 0000000..328f006 --- /dev/null +++ b/utils/networks/networks.go @@ -0,0 +1,181 @@ +package networks + +import ( + "cmp" + "fmt" + "log" + "net/netip" + "os" + "slices" + "utils/ipam/yaml_model" +) + +func RunNetworks() error { + ipamYaml := "../ansible/group_vars/all/ipam.yml" + bs, err := os.ReadFile(ipamYaml) + if err != nil { + return err + } + + ipam, err := loadIpam(bs) + if err != nil { + return err + } + + networks := slices.SortedFunc(slices.Values(ipam.networks), CompareNetwork) + roots := slices.SortedFunc(slices.Values(ipam.FindRoots()), CompareNetwork) + + fmt.Printf("digraph {\n") + //fmt.Printf(" layout=dot\n") + //fmt.Printf(" layout=twopi\n") + fmt.Printf(" layout=fdp\n") + //fmt.Printf(" layout=circo\n") + //fmt.Printf(" layout=neato\n") + //fmt.Printf(" ranksep=3\n") + //fmt.Printf(" ratio=auto\n") + //fmt.Printf(" rankdir=LR\n") + //fmt.Printf(" rankdir=RL\n") + fmt.Printf(" rankdir=TB\n") + //fmt.Printf(" sep=3\n") + //fmt.Printf(" overlap_scaling=-10\n") + fmt.Printf("node [len=10];") + fmt.Printf("node [shape=box];") + fmt.Printf("overlap=false") + + fmt.Printf("\n") + fmt.Printf(" # Nodes\n") + for _, n := range networks { + fmt.Printf(" %s [ label = \"%s\\n%s\"];\n", n.name, n.name, n.prefix) + } + + fmt.Printf("\n") + fmt.Printf(" # Roots\n") + for _, n := range roots { + fmt.Printf(" %s [ root = true ];\n", n.name) + } + + fmt.Printf("\n") + fmt.Printf(" # Relationships\n") + for _, n := range networks { + for _, c := range ipam.networks { + if c.parent == n { + fmt.Printf(" %s -> %s", n.name, c.name) + fmt.Printf(";\n") + } + } + } + fmt.Printf("}\n") + + return nil +} + +func loadIpam(bs []byte) (*Ipam, error) { + parsed, err := yaml_model.Parse(bs) + if err != nil { + return nil, err + } + + ipam_, err := processNetworks(parsed.Ipam6.Networks) + if err != nil { + return nil, err + } + + ipam_.ResolveParents() + + return ipam_, nil +} + +type Ipam struct { + networks []*Network +} + +func contains(a, b netip.Prefix) bool { + return b.Bits() > a.Bits() && b.Overlaps(a) +} + +func (ipam *Ipam) ResolveParents() { + for _, n := range ipam.networks { + log.Printf("network %s/%s", n.name, n.prefix) + for _, p := range ipam.networks { + if n == p { + continue + } + log.Printf(" candidate %s/%s", p.name, p.prefix) + if contains(p.prefix, n.prefix) { + if n.parent == nil { + log.Printf(" found parent %s/%s", p.name, p.prefix) + n.parent = p + } else { + if n.parent.prefix.Bits() < p.prefix.Bits() { + log.Printf(" found better parent %s/%s", p.name, p.prefix) + n.parent = p + } + } + } + } + } + + return +} + +func (ipam *Ipam) FindRoots() []*Network { + var ns []*Network + + for _, n := range ipam.networks { + if n.parent == nil { + ns = append(ns, n) + } + } + + return ns +} + +type Network struct { + name string + parent *Network + prefix netip.Prefix + hosts []networkHost +} + +func CompareNetwork(a, b *Network) int { + return cmp.Compare(a.name, b.name) +} + +func (n *Network) Compare(other *Network) int { + return cmp.Compare(n.name, other.name) +} + +type networkHost struct { + name string + address netip.Addr +} + +func processNetworks(networks map[string]yaml_model.Network6Yaml) (*Ipam, error) { + var ns []*Network + + for name, net := range networks { + log.Printf("Processing net %v\n", name) + prefix, err := netip.ParsePrefix(net.Range) + if err != nil { + return nil, fmt.Errorf("error parsing net range: %v", err) + } + log.Printf("prefix: %s", prefix.String()) + + n := Network{name: name, prefix: prefix} + for hostname, a := range net.Hosts { + addr, err := netip.ParseAddr(a) + if err != nil { + return nil, fmt.Errorf("network: %s, unable to parse host address %s", n.name, a) + } + + n.hosts = append(n.hosts, networkHost{ + name: hostname, + address: addr, + }) + } + + ns = append(ns, &n) + } + + return &Ipam{networks: ns}, nil +} diff --git a/utils/routers/routers.go b/utils/routers/routers.go new file mode 100644 index 0000000..0afb355 --- /dev/null +++ b/utils/routers/routers.go @@ -0,0 +1,4 @@ +package routers + +type Routers struct { +} diff --git a/utils/yaml_ipam/yaml_ipam.go b/utils/yaml_ipam/yaml_ipam.go deleted file mode 100644 index ff65155..0000000 --- a/utils/yaml_ipam/yaml_ipam.go +++ /dev/null @@ -1,26 +0,0 @@ -package yaml_ipam - -import "gopkg.in/yaml.v3" - -type Ipam struct { - Ipam6 Ipam6 `yaml:"ipam6"` -} - -type Ipam6 struct { - Networks map[string]Network6Yaml `yaml:"networks"` -} - -type Network6Yaml struct { - Range string `yaml:"range"` - Hosts map[string]string `yaml:"hosts"` -} - -func Parse(bs []byte) (Ipam, error) { - var ipam Ipam - err := yaml.Unmarshal(bs, &ipam) - if err != nil { - return Ipam{}, err - } - - return ipam, nil -} -- cgit v1.2.3