| package model |
| |
| import ( |
| "context" |
| "database/sql" |
| "fmt" |
| "net" |
| "strconv" |
| ) |
| |
| func (m *sqlModel) ConfigureMissingSessions(ctx context.Context, gen func() SessionConfig) error { |
| tx := m.db.MustBeginTx(ctx, &sql.TxOptions{}) |
| defer tx.Rollback() |
| |
| q := ` |
| SELECT |
| peer_routers.peer_id "peer_id", |
| peer_routers.id "id" |
| FROM peer_routers |
| WHERE peer_routers.id NOT IN ( |
| SELECT session_configs.peer_router_id |
| FROM session_configs |
| ) |
| ` |
| missing := []struct { |
| PeerID string `db:"peer_id"` |
| ID string `db:"id"` |
| }{} |
| if err := m.db.SelectContext(ctx, &missing, q); err != nil { |
| return fmt.Errorf("SELECT peerRouters: %v", err) |
| } |
| |
| for _, m := range missing { |
| config := gen() |
| q = ` |
| INSERT INTO |
| session_configs |
| (peer_id, peer_router_id, bgp_secret) |
| VALUES |
| (:peer_id, :peer_router_id, :bgp_secret) |
| ` |
| data := sqlSessionConfig{ |
| PeerID: m.PeerID, |
| PeerRouterID: m.ID, |
| BGPSecret: config.BGPSecret, |
| } |
| if _, err := tx.NamedExecContext(ctx, q, data); err != nil { |
| return err |
| } |
| } |
| |
| return tx.Commit() |
| } |
| |
| func (m *sqlModel) GetPeerConfiguration(ctx context.Context) ([]*PeerConfiguration, error) { |
| q := ` |
| SELECT |
| peers.asn "asn", |
| peer_pgp_keys.fingerprint "peer_pgp_keys.fingerprint", |
| peer_routers.v6 "peer_routers.v6", peer_routers.v4 "peer_routers.v4", |
| session_configs.bgp_secret "session_configs.bgp_secret" |
| FROM session_configs |
| LEFT JOIN peer_routers |
| ON peer_routers.id = session_configs.peer_router_id |
| INNER JOIN peer_pgp_keys |
| ON peer_pgp_keys.peer_id = session_configs.peer_id |
| LEFT JOIN peers |
| on peers.id = session_configs.peer_id |
| ` |
| |
| data := []struct { |
| PGP sqlPeerPGPKey `db:"peer_pgp_keys"` |
| Config sqlSessionConfig `db:"session_configs"` |
| Router sqlPeerRouter `db:"peer_routers"` |
| ASN string `db:"asn"` |
| }{} |
| |
| if err := m.db.SelectContext(ctx, &data, q); err != nil { |
| return nil, fmt.Errorf("SELECT peers/peer_pgp_keys/session_configs: %v", err) |
| } |
| |
| resM := make(map[string]*PeerConfiguration) |
| |
| for _, d := range data { |
| k := fmt.Sprintf("%s", d.ASN) |
| r, ok := resM[k] |
| if !ok { |
| asn, err := strconv.ParseInt(d.ASN, 10, 64) |
| if err != nil { |
| return nil, fmt.Errorf("data corruption: invalid ASN %q", d.ASN) |
| } |
| r = &PeerConfiguration{ |
| Peer: Peer{ |
| ASN: asn, |
| Routers: []*Router{}, |
| }, |
| Key: PeerPGPKey{ |
| PeerASN: asn, |
| Fingerprint: d.PGP.Fingerprint, |
| }, |
| } |
| resM[k] = r |
| } |
| |
| v6 := net.ParseIP(d.Router.V6.String) |
| v4 := net.ParseIP(d.Router.V4.String) |
| secret := d.Config.BGPSecret |
| r.Peer.Routers = append(r.Peer.Routers, &Router{ |
| V6: v6, |
| V4: v4, |
| Config: &SessionConfig{ |
| BGPSecret: secret, |
| }, |
| }) |
| } |
| |
| res := make([]*PeerConfiguration, len(resM)) |
| i := 0 |
| for _, pc := range resM { |
| res[i] = pc |
| i += 1 |
| } |
| |
| return res, nil |
| } |