blob: 53294ddf2d5871183a02de14e3b163f2dfb94a0f [file] [log] [blame]
package model
import (
"context"
"fmt"
"net"
"strings"
"time"
pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
"code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model/migrations"
migrate "github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/cockroachdb"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
type Model interface {
MigrateUp() error
RecordPeeringDBPeers(ctx context.Context, members []*pb.PeeringDBMember) error
RecordPeeringDBPeerRouters(ctx context.Context, members []*pb.PeeringDBMember) error
GetPeeringDBPeer(ctx context.Context, asn int64) (*pb.PeeringDBMember, error)
GetCheckablePeers(ctx context.Context) ([]*Peer, error)
SubmitPeerCheckResults(ctx context.Context, checkName string, res []*PeerCheckResult) error
GetPeerCheckResults(ctx context.Context, asn []int64) ([]*PeerCheckResult, error)
UpdatePGPKey(ctx context.Context, key *PeerPGPKey) error
GetPGPKeysRequiringAttention(ctx context.Context) ([]*PeerPGPKey, error)
ValidatePGPKeys(ctx context.Context, positive, negative []string) error
GetPeerPGPKey(ctx context.Context, asn int64) (*PeerPGPKey, error)
ConfigureMissingSessions(ctx context.Context, gen func() SessionConfig) error
GetPeerConfiguration(ctx context.Context) ([]*PeerConfiguration, error)
UpdateAllowedPrefixes(ctx context.Context, asn int64, prefixes []*AllowedPrefix) error
GetAllowedPrefixes(ctx context.Context, asn int64) ([]*AllowedPrefix, error)
}
type Router struct {
V6 net.IP
V4 net.IP
Config *SessionConfig
}
func (p *Router) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type Peer struct {
ASN int64
Name string
Routers []*Router
}
func (p *Peer) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type PeerCheckStatus int
const (
PeerCheckStatus_Invalid PeerCheckStatus = iota
PeerCheckStatus_Okay
PeerCheckStatus_Failed
PeerCheckStatus_SoftFailed
)
type PeerCheckResult struct {
PeerASN int64
CheckName string
Time time.Time
Status PeerCheckStatus
Message string
}
func (p *PeerCheckResult) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type PeerPGPKey struct {
PeerASN int64
Fingerprint string
State string
}
func (p *PeerPGPKey) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type SessionConfig struct {
BGPSecret string
}
func (p *SessionConfig) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type PeerConfiguration struct {
Peer Peer
Key PeerPGPKey
}
func (p *PeerConfiguration) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type AllowedPrefix struct {
Prefix net.IPNet
MaxLength int64
TA string
}
func (p *AllowedPrefix) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("%+v", *p)
}
type sqlModel struct {
db *sqlx.DB
dsn string
}
func Connect(ctx context.Context, driver, dsn string) (Model, error) {
if dsn == "" {
return nil, fmt.Errorf("dsn cannot be empty")
}
db, err := sqlx.ConnectContext(ctx, driver, dsn)
if err != nil {
return nil, fmt.Errorf("could not connect to database: %v", err)
}
return &sqlModel{
db: db,
dsn: dsn,
}, nil
}
func (m *sqlModel) MigrateUp() error {
dsn := "cockroach://" + strings.TrimPrefix(m.dsn, "postgres://")
mig, err := migrations.New(dsn)
if err != nil {
return err
}
err = mig.Up()
switch err {
case migrate.ErrNoChange:
return nil
default:
return err
}
}