blob: 53294ddf2d5871183a02de14e3b163f2dfb94a0f [file] [log] [blame]
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +02001package model
2
3import (
4 "context"
5 "fmt"
6 "net"
7 "strings"
8 "time"
9
10 pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
11 "code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model/migrations"
12 migrate "github.com/golang-migrate/migrate/v4"
13 _ "github.com/golang-migrate/migrate/v4/database/cockroachdb"
14 "github.com/jmoiron/sqlx"
15 _ "github.com/lib/pq"
16)
17
18type Model interface {
19 MigrateUp() error
20
21 RecordPeeringDBPeers(ctx context.Context, members []*pb.PeeringDBMember) error
22 RecordPeeringDBPeerRouters(ctx context.Context, members []*pb.PeeringDBMember) error
23 GetPeeringDBPeer(ctx context.Context, asn int64) (*pb.PeeringDBMember, error)
24
25 GetCheckablePeers(ctx context.Context) ([]*Peer, error)
Serge Bazanskiec71cb52019-08-22 18:13:13 +020026 SubmitPeerCheckResults(ctx context.Context, checkName string, res []*PeerCheckResult) error
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020027 GetPeerCheckResults(ctx context.Context, asn []int64) ([]*PeerCheckResult, error)
28
29 UpdatePGPKey(ctx context.Context, key *PeerPGPKey) error
Serge Bazanskiec71cb52019-08-22 18:13:13 +020030 GetPGPKeysRequiringAttention(ctx context.Context) ([]*PeerPGPKey, error)
31 ValidatePGPKeys(ctx context.Context, positive, negative []string) error
32 GetPeerPGPKey(ctx context.Context, asn int64) (*PeerPGPKey, error)
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020033
34 ConfigureMissingSessions(ctx context.Context, gen func() SessionConfig) error
35
Serge Bazanskiec71cb52019-08-22 18:13:13 +020036 GetPeerConfiguration(ctx context.Context) ([]*PeerConfiguration, error)
37
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020038 UpdateAllowedPrefixes(ctx context.Context, asn int64, prefixes []*AllowedPrefix) error
39 GetAllowedPrefixes(ctx context.Context, asn int64) ([]*AllowedPrefix, error)
40}
41
Serge Bazanskiec71cb52019-08-22 18:13:13 +020042type Router struct {
43 V6 net.IP
44 V4 net.IP
45 Config *SessionConfig
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020046}
47
Serge Bazanskiec71cb52019-08-22 18:13:13 +020048func (p *Router) String() string {
49 if p == nil {
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020050 return "<nil>"
51 }
Serge Bazanskiec71cb52019-08-22 18:13:13 +020052 return fmt.Sprintf("%+v", *p)
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020053}
54
55type Peer struct {
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020056 ASN int64
57 Name string
58 Routers []*Router
59}
60
Serge Bazanskiec71cb52019-08-22 18:13:13 +020061func (p *Peer) String() string {
62 if p == nil {
63 return "<nil>"
64 }
65 return fmt.Sprintf("%+v", *p)
66}
67
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020068type PeerCheckStatus int
69
70const (
71 PeerCheckStatus_Invalid PeerCheckStatus = iota
72 PeerCheckStatus_Okay
73 PeerCheckStatus_Failed
74 PeerCheckStatus_SoftFailed
75)
76
77type PeerCheckResult struct {
78 PeerASN int64
79 CheckName string
80 Time time.Time
81 Status PeerCheckStatus
82 Message string
83}
84
85func (p *PeerCheckResult) String() string {
86 if p == nil {
87 return "<nil>"
88 }
89 return fmt.Sprintf("%+v", *p)
90}
91
92type PeerPGPKey struct {
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +020093 PeerASN int64
94 Fingerprint string
Serge Bazanskiec71cb52019-08-22 18:13:13 +020095 State string
96}
97
98func (p *PeerPGPKey) String() string {
99 if p == nil {
100 return "<nil>"
101 }
102 return fmt.Sprintf("%+v", *p)
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +0200103}
104
105type SessionConfig struct {
106 BGPSecret string
107}
108
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200109func (p *SessionConfig) String() string {
110 if p == nil {
111 return "<nil>"
112 }
113 return fmt.Sprintf("%+v", *p)
114}
115
116type PeerConfiguration struct {
117 Peer Peer
118 Key PeerPGPKey
119}
120
121func (p *PeerConfiguration) String() string {
122 if p == nil {
123 return "<nil>"
124 }
125 return fmt.Sprintf("%+v", *p)
126}
127
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +0200128type AllowedPrefix struct {
129 Prefix net.IPNet
130 MaxLength int64
131 TA string
132}
133
134func (p *AllowedPrefix) String() string {
135 if p == nil {
136 return "<nil>"
137 }
138 return fmt.Sprintf("%+v", *p)
139}
140
141type sqlModel struct {
142 db *sqlx.DB
143 dsn string
144}
145
146func Connect(ctx context.Context, driver, dsn string) (Model, error) {
147 if dsn == "" {
148 return nil, fmt.Errorf("dsn cannot be empty")
149 }
150
151 db, err := sqlx.ConnectContext(ctx, driver, dsn)
152 if err != nil {
153 return nil, fmt.Errorf("could not connect to database: %v", err)
154 }
155
156 return &sqlModel{
157 db: db,
158 dsn: dsn,
159 }, nil
160}
161
162func (m *sqlModel) MigrateUp() error {
163 dsn := "cockroach://" + strings.TrimPrefix(m.dsn, "postgres://")
164 mig, err := migrations.New(dsn)
165 if err != nil {
166 return err
167 }
168 err = mig.Up()
169 switch err {
170 case migrate.ErrNoChange:
171 return nil
172 default:
173 return err
174 }
175}