bgpwtf/cccampix: draw the rest of the fucking owl
Change-Id: I49fd5906e69512e8f2d414f406edc0179522f225
diff --git a/bgpwtf/cccampix/verifier/model/checkable_peers.go b/bgpwtf/cccampix/verifier/model/checkable_peers.go
new file mode 100644
index 0000000..2fe133f
--- /dev/null
+++ b/bgpwtf/cccampix/verifier/model/checkable_peers.go
@@ -0,0 +1,76 @@
+package model
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "strconv"
+)
+
+func (m *sqlModel) GetCheckablePeers(ctx context.Context) ([]*Peer, error) {
+
+ data := []struct {
+ sqlPeer `db:"peers"`
+ sqlPeerRouter `db:"peer_routers"`
+ }{}
+ q := `
+ SELECT
+ peers.id "peers.id",
+ peers.asn "peers.asn",
+ peers.name "peers.name",
+
+ peer_routers.peer_id "peer_routers.peer_id",
+ peer_routers.v6 "peer_routers.v6",
+ peer_routers.v4 "peer_routers.v4"
+ FROM peers
+ LEFT JOIN peer_routers
+ ON peer_routers.peer_id = peers.id
+ `
+ if err := m.db.SelectContext(ctx, &data, q); err != nil {
+ return nil, fmt.Errorf("SELECT peers/peerRouters: %v", err)
+ }
+
+ // Collapse peers into map
+ // ID -> Peer
+ peers := make(map[string]*Peer)
+
+ for _, row := range data {
+ peer, ok := peers[row.sqlPeer.ID]
+ if !ok {
+ asn, err := strconv.ParseInt(row.sqlPeer.ASN, 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("data corruption: invalid ASN %q", row.sqlPeer.ASN)
+ }
+ peer = &Peer{
+ ASN: asn,
+ Name: row.sqlPeer.Name,
+ Routers: []*Router{},
+ }
+ peers[row.sqlPeer.ID] = peer
+ }
+
+ var v6 net.IP
+ var v4 net.IP
+
+ if row.sqlPeerRouter.V6.Valid {
+ v6 = net.ParseIP(row.sqlPeerRouter.V6.String)
+ }
+ if row.sqlPeerRouter.V4.Valid {
+ v4 = net.ParseIP(row.sqlPeerRouter.V4.String)
+ }
+
+ peer.Routers = append(peer.Routers, &Router{
+ V6: v6,
+ V4: v4,
+ })
+ }
+
+ res := make([]*Peer, len(peers))
+ i := 0
+ for _, peer := range peers {
+ res[i] = peer
+ i += 1
+ }
+
+ return res, nil
+}