orchestrator: switch to github.com/oschwald/maxminddb-golang/v2

Also, remove the AS name, this is not used at all.
This commit is contained in:
Vincent Bernat
2025-08-02 15:54:54 +02:00
parent 3b353ea940
commit 0a10764cc9
8 changed files with 71 additions and 102 deletions

4
go.mod
View File

@@ -33,8 +33,9 @@ require (
github.com/openconfig/gnmi v0.14.0 github.com/openconfig/gnmi v0.14.0
github.com/openconfig/gnmic/pkg/api v0.1.9 github.com/openconfig/gnmic/pkg/api v0.1.9
github.com/opencontainers/image-spec v1.1.1 github.com/opencontainers/image-spec v1.1.1
github.com/oschwald/maxminddb-golang v1.13.1 github.com/oschwald/maxminddb-golang/v2 v2.0.0-beta.8
github.com/osrg/gobgp/v3 v3.37.0 github.com/osrg/gobgp/v3 v3.37.0
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10
github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_golang v1.22.0
github.com/rs/zerolog v1.34.0 github.com/rs/zerolog v1.34.0
github.com/scrapli/scrapligo v1.3.3 github.com/scrapli/scrapligo v1.3.3
@@ -152,7 +153,6 @@ require (
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect

4
go.sum
View File

@@ -332,8 +332,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE= github.com/oschwald/maxminddb-golang/v2 v2.0.0-beta.8 h1:aM1/rO6p+XV+l+seD7UCtFZgsOefDTrFVLvPoZWjXZs=
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8= github.com/oschwald/maxminddb-golang/v2 v2.0.0-beta.8/go.mod h1:Jts8ztuE0PkUwY7VCJyp6B68ujQfr6G9P5Dn3Yx9u6w=
github.com/osrg/gobgp/v3 v3.37.0 h1:+ObuOdvj7G7nxrT0fKFta+EAupdWf/q1WzbXydr8IOY= github.com/osrg/gobgp/v3 v3.37.0 h1:+ObuOdvj7G7nxrT0fKFta+EAupdWf/q1WzbXydr8IOY=
github.com/osrg/gobgp/v3 v3.37.0/go.mod h1:kVHVFy1/fyZHJ8P32+ctvPeJogn9qKwa1YCeMRXXrP0= github.com/osrg/gobgp/v3 v3.37.0/go.mod h1:kVHVFy1/fyZHJ8P32+ctvPeJogn9qKwa1YCeMRXXrP0=
github.com/pascaldekloe/name v1.0.1 h1:9lnXOHeqeHHnWLbKfH6X98+4+ETVqFqxN09UXSjcMb0= github.com/pascaldekloe/name v1.0.1 h1:9lnXOHeqeHHnWLbKfH6X98+4+ETVqFqxN09UXSjcMb0=

View File

@@ -7,7 +7,7 @@ import (
"compress/gzip" "compress/gzip"
"context" "context"
"encoding/csv" "encoding/csv"
"net" "net/netip"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@@ -57,8 +57,8 @@ func (c *Component) networksCSVRefresher() {
networks := helpers.MustNewSubnetMap[NetworkAttributes](nil) networks := helpers.MustNewSubnetMap[NetworkAttributes](nil)
// Add content of all geoip databases // Add content of all geoip databases
err := c.d.GeoIP.IterASNDatabases(func(subnet *net.IPNet, data geoip.ASNInfo) error { err := c.d.GeoIP.IterASNDatabases(func(prefix netip.Prefix, data geoip.ASNInfo) error {
subV6Str, err := helpers.SubnetMapParseKey(subnet.String()) subV6Str, err := helpers.SubnetMapParseKey(prefix.String())
if err != nil { if err != nil {
return err return err
} }
@@ -71,8 +71,8 @@ func (c *Component) networksCSVRefresher() {
c.r.Err(err).Msg("unable to iter over ASN databases") c.r.Err(err).Msg("unable to iter over ASN databases")
return return
} }
err = c.d.GeoIP.IterGeoDatabases(func(subnet *net.IPNet, data geoip.GeoInfo) error { err = c.d.GeoIP.IterGeoDatabases(func(prefix netip.Prefix, data geoip.GeoInfo) error {
subV6Str, err := helpers.SubnetMapParseKey(subnet.String()) subV6Str, err := helpers.SubnetMapParseKey(prefix.String())
if err != nil { if err != nil {
return err return err
} }

View File

@@ -5,17 +5,17 @@ package geoip
import ( import (
"fmt" "fmt"
"net" "net/netip"
"strings" "strings"
"github.com/oschwald/maxminddb-golang" "github.com/oschwald/maxminddb-golang/v2"
) )
// GeoIterFunc is the required signature to iter a geo database. // GeoIterFunc is the required signature to iter a geo database.
type GeoIterFunc func(*net.IPNet, GeoInfo) error type GeoIterFunc func(netip.Prefix, GeoInfo) error
// AsnIterFunc is the required signature to iter an asn database; // AsnIterFunc is the required signature to iter an asn database;
type AsnIterFunc func(*net.IPNet, ASNInfo) error type AsnIterFunc func(netip.Prefix, ASNInfo) error
type geoDatabase interface { type geoDatabase interface {
Close() Close()

View File

@@ -14,10 +14,9 @@ type GeoInfo struct {
State string State string
} }
// ASNInfo describes ASN data of an asn database. // ASNInfo describes ASN data of an ASN database.
type ASNInfo struct { type ASNInfo struct {
ASNumber uint32 ASNumber uint32
ASName string
} }
// IterGeoDatabases iter all entries in all geo databases. // IterGeoDatabases iter all entries in all geo databases.

View File

@@ -6,41 +6,30 @@ package geoip
import ( import (
"strconv" "strconv"
"github.com/oschwald/maxminddb-golang" "github.com/oschwald/maxminddb-golang/v2"
) )
type ipinfoDBASN struct {
ASN string `maxminddb:"asn"`
ASName string `maxminddb:"as_name"`
}
type ipinfoDBCountry struct {
Country string `maxminddb:"country"`
Region string `maxminddb:"region"`
City string `maxminddb:"city"`
}
type ipinfoDB struct { type ipinfoDB struct {
db *maxminddb.Reader db *maxminddb.Reader
} }
func (mmdb *ipinfoDB) IterASNDatabase(f AsnIterFunc) error { func (mmdb *ipinfoDB) IterASNDatabase(f AsnIterFunc) error {
it := mmdb.db.Networks() for result := range mmdb.db.Networks() {
maxminddb.SkipAliasedNetworks(it) var asnStr string // They are stored as ASxxxx
for it.Next() {
asnInfo := &ipinfoDBASN{}
subnet, err := it.Network(asnInfo)
if err != nil { // Get AS number, skip if not found
return err result.DecodePath(&asnStr, "asn")
if asnStr == "" {
continue
} }
n, err := strconv.ParseUint(asnInfo.ASN[2:], 10, 32) asn, err := strconv.ParseUint(asnStr[2:], 10, 32)
if err != nil { if err != nil {
return err continue
} }
if err := f(subnet, ASNInfo{
ASNumber: uint32(n), prefix := result.Prefix()
ASName: asnInfo.ASName, if err := f(prefix, ASNInfo{
ASNumber: uint32(asn),
}); err != nil { }); err != nil {
return err return err
} }
@@ -49,19 +38,19 @@ func (mmdb *ipinfoDB) IterASNDatabase(f AsnIterFunc) error {
} }
func (mmdb *ipinfoDB) IterGeoDatabase(f GeoIterFunc) error { func (mmdb *ipinfoDB) IterGeoDatabase(f GeoIterFunc) error {
it := mmdb.db.Networks() for result := range mmdb.db.Networks() {
maxminddb.SkipAliasedNetworks(it) var country, region, city string
for it.Next() {
geoInfo := &ipinfoDBCountry{}
subnet, err := it.Network(geoInfo)
if err != nil { // Get country, region, and city
return err result.DecodePath(&country, "country")
} result.DecodePath(&region, "region")
if err := f(subnet, GeoInfo{ result.DecodePath(&city, "city")
Country: geoInfo.Country,
State: geoInfo.Region, prefix := result.Prefix()
City: geoInfo.City, if err := f(prefix, GeoInfo{
Country: country,
State: region,
City: city,
}); err != nil { }); err != nil {
return err return err
} }

View File

@@ -4,45 +4,27 @@
package geoip package geoip
import ( import (
"github.com/oschwald/maxminddb-golang" "github.com/oschwald/maxminddb-golang/v2"
) )
type maxmindDBASN struct {
AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"`
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
}
// for a list fields available, see: https://github.com/oschwald/geoip2-golang/blob/main/reader.go // for a list fields available, see: https://github.com/oschwald/geoip2-golang/blob/main/reader.go
type maxmindDBCountry struct {
Country struct {
IsoCode string `maxminddb:"iso_code"`
} `maxminddb:"country"`
City struct {
Names map[string]string `maxminddb:"names"`
} `maxminddb:"city"`
Subdivisions []struct {
IsoCode string `maxminddb:"iso_code"`
} `maxminddb:"subdivisions"`
}
type maxmindDB struct { type maxmindDB struct {
db *maxminddb.Reader db *maxminddb.Reader
} }
func (mmdb *maxmindDB) IterASNDatabase(f AsnIterFunc) error { func (mmdb *maxmindDB) IterASNDatabase(f AsnIterFunc) error {
it := mmdb.db.Networks() for result := range mmdb.db.Networks() {
maxminddb.SkipAliasedNetworks(it) var asn uint32
for it.Next() { // Get AS number, skip if not found
asnInfo := &maxmindDBASN{} result.DecodePath(&asn, "autonomous_system_number")
subnet, err := it.Network(asnInfo) if asn == 0 {
continue
if err != nil {
return err
} }
if err := f(subnet, ASNInfo{ prefix := result.Prefix()
ASNumber: uint32(asnInfo.AutonomousSystemNumber), if err := f(prefix, ASNInfo{
ASName: asnInfo.AutonomousSystemOrganization, ASNumber: asn,
}); err != nil { }); err != nil {
return err return err
} }
@@ -51,25 +33,24 @@ func (mmdb *maxmindDB) IterASNDatabase(f AsnIterFunc) error {
} }
func (mmdb *maxmindDB) IterGeoDatabase(f GeoIterFunc) error { func (mmdb *maxmindDB) IterGeoDatabase(f GeoIterFunc) error {
it := mmdb.db.Networks() for result := range mmdb.db.Networks() {
maxminddb.SkipAliasedNetworks(it) var country string
var city string
for it.Next() {
geoInfo := &maxmindDBCountry{}
subnet, err := it.Network(geoInfo)
if err != nil {
return err
}
var state string var state string
if len(geoInfo.Subdivisions) > 0 {
state = geoInfo.Subdivisions[0].IsoCode
}
if err := f(subnet, GeoInfo{ // Get country, city, and state. Skip if no country
Country: geoInfo.Country.IsoCode, result.DecodePath(&country, "country", "iso_code")
if country == "" {
continue
}
result.DecodePath(&city, "city", "names", "en")
result.DecodePath(&state, "subdivisions", "0", "iso_code")
prefix := result.Prefix()
if err := f(prefix, GeoInfo{
Country: country,
State: state, State: state,
City: geoInfo.City.Names["en"], City: city,
}); err != nil { }); err != nil {
return err return err
} }

View File

@@ -4,7 +4,7 @@
package geoip package geoip
import ( import (
"net" "net/netip"
"path/filepath" "path/filepath"
"testing" "testing"
@@ -55,10 +55,10 @@ func TestIterDatabase(t *testing.T) {
}, },
} }
err := c.IterASNDatabases(func(n *net.IPNet, a ASNInfo) error { err := c.IterASNDatabases(func(prefix netip.Prefix, a ASNInfo) error {
for i, h := range mustHave { for i, h := range mustHave {
// found the IP // found the IP
if n.Contains(net.ParseIP(h.IP)) { if ip, err := netip.ParseAddr(h.IP); err == nil && prefix.Contains(ip) {
if h.ExpectedASN != 0 && a.ASNumber != h.ExpectedASN { if h.ExpectedASN != 0 && a.ASNumber != h.ExpectedASN {
t.Errorf("expected ASN %d, got %d", h.ExpectedASN, a.ASNumber) t.Errorf("expected ASN %d, got %d", h.ExpectedASN, a.ASNumber)
} }
@@ -72,10 +72,10 @@ func TestIterDatabase(t *testing.T) {
t.Fatalf("IterASNDatabases() error:\n%+v", err) t.Fatalf("IterASNDatabases() error:\n%+v", err)
} }
err = c.IterGeoDatabases(func(n *net.IPNet, a GeoInfo) error { err = c.IterGeoDatabases(func(prefix netip.Prefix, a GeoInfo) error {
for i, h := range mustHave { for i, h := range mustHave {
// found the IP // found the IP
if n.Contains(net.ParseIP(h.IP).To16()) { if ip, err := netip.ParseAddr(h.IP); err == nil && prefix.Contains(ip) {
if h.ExpectedCountry != "" && a.Country != h.ExpectedCountry { if h.ExpectedCountry != "" && a.Country != h.ExpectedCountry {
t.Errorf("expected Country %s, got %s", h.ExpectedCountry, a.Country) t.Errorf("expected Country %s, got %s", h.ExpectedCountry, a.Country)
} }
@@ -112,12 +112,12 @@ func TestIterNonExistingDatabase(t *testing.T) {
t.Fatalf("New() error:\n%+v", err) t.Fatalf("New() error:\n%+v", err)
} }
helpers.StartStop(t, c) helpers.StartStop(t, c)
if err := c.IterASNDatabases(func(_ *net.IPNet, _ ASNInfo) error { if err := c.IterASNDatabases(func(_ netip.Prefix, _ ASNInfo) error {
return nil return nil
}); err != nil { }); err != nil {
t.Fatalf("IterASNDatabases() error:\n%+v", err) t.Fatalf("IterASNDatabases() error:\n%+v", err)
} }
if err := c.IterGeoDatabases(func(_ *net.IPNet, _ GeoInfo) error { if err := c.IterGeoDatabases(func(_ netip.Prefix, _ GeoInfo) error {
return nil return nil
}); err != nil { }); err != nil {
t.Fatalf("IterGeoDatabases() error:\n%+v", err) t.Fatalf("IterGeoDatabases() error:\n%+v", err)