diff --git a/management/internals/network_map_db/pgsql/peer.go b/management/internals/network_map_db/pgsql/peer.go index 3c92ae0b5..962669f7a 100644 --- a/management/internals/network_map_db/pgsql/peer.go +++ b/management/internals/network_map_db/pgsql/peer.go @@ -2,9 +2,6 @@ package networkmap_pgsql import ( "context" - "database/sql" - "encoding/json" - "reflect" "github.com/jackc/pgx/v5" networkmapdb "github.com/netbirdio/netbird/management/internals/network_map_db" @@ -28,113 +25,10 @@ func (pgc *PgStoreConn) GetPeers(ctx context.Context, accountId string) ([]nmdat return nil, nil, err } - peers, err := pgx.CollectRows(rows, pgx.RowToStructByName[peer]) + peers, err := pgx.CollectRows(rows, pgx.RowToStructByName[networkmapdb.Peer]) if err != nil { return nil, nil, err } - toret := make([]nmdata.Peer, 0, len(peers)) - clusterToPeerIdx := make(map[string][]*nmdata.Peer) - for _, p := range peers { - dp := nmdata.Peer{} - err := networkmapdb.FromSqlTypesToSharedTypes( - reflect.ValueOf(&p), reflect.ValueOf(&dp)) - if err != nil { - return nil, nil, err - } - - if p.ProxyMetaEmbedded.Valid { - dp.ProxyMeta.Embedded = p.ProxyMetaEmbedded.Bool - } - // This is only used to build private service candidates, not connected peers are skipped - if dp.ProxyMeta.Embedded && p.PeerStatusConnected.Bool { - clusterToPeerIdx[p.ProxyMetaCluster.String] = append(clusterToPeerIdx[p.ProxyMetaCluster.String], &dp) - } - if p.MetaWtVersion.Valid { - dp.Meta.WtVersion = p.MetaWtVersion.String - } - if p.MetaSyncMessageVersion.Valid { - dp.Meta.SyncMessageVersion = int(p.MetaSyncMessageVersion.Int64) - } - if p.MetaGoOS.Valid { - dp.Meta.GoOS = p.MetaGoOS.String - } - if p.MetaOSVersion.Valid { - dp.Meta.OSVersion = p.MetaOSVersion.String - } - if p.MetaKernelVersion.Valid { - dp.Meta.KernelVersion = p.MetaKernelVersion.String - } - if p.LocationCountryCode.Valid { - dp.Location.CountryCode = p.LocationCountryCode.String - } - if p.LocationCityName.Valid { - dp.Location.CityName = p.LocationCityName.String - } - if p.LocationConnectionIp != nil { - err := json.Unmarshal(p.LocationConnectionIp, &dp.Location.ConnectionIP) - if err != nil { - return toret, nil, err - } - } - if p.MetaFiles != nil { - err := json.Unmarshal(p.MetaFiles, &dp.Meta.Files) - if err != nil { - return toret, nil, err - } - } - if p.MetaCapabilities != nil { - err := json.Unmarshal(p.MetaCapabilities, &dp.Meta.Capabilities) - if err != nil { - return toret, nil, err - } - } - if p.MetaFlags != nil { - err := json.Unmarshal(p.MetaFlags, &dp.Meta.Flags) - if err != nil { - return toret, nil, err - } - } - if p.MetaNetworkAddresses != nil { - err := json.Unmarshal(p.MetaNetworkAddresses, &dp.Meta.NetworkAddresses) - if err != nil { - return toret, nil, err - } - } - - toret = append(toret, dp) - } - - return toret, clusterToPeerIdx, nil -} - -// TODO add support for creating struct fields from denormalized fields -type peer struct { - ID string - Key sql.NullString - SSHKey sql.NullString - DNSLabel sql.NullString - ExtraDNSLabels json.RawMessage - UserID sql.NullString - LastLogin sql.NullTime - SSHEnabled sql.NullBool - LoginExpirationEnabled sql.NullBool - PeerStatusConnected sql.NullBool `nmap:"skip"` - PeerStatusRequiresApproval sql.NullBool `nmap:"map_to:RequiresApproval"` - ProxyMetaEmbedded sql.NullBool `nmap:"skip"` - ProxyMetaCluster sql.NullString `nmap:"skip"` - IP json.RawMessage - IPv6 json.RawMessage - LocationConnectionIp json.RawMessage `nmap:"skip"` - MetaFiles json.RawMessage `nmap:"skip"` - MetaCapabilities json.RawMessage `nmap:"skip"` - MetaFlags json.RawMessage `nmap:"skip"` - MetaNetworkAddresses json.RawMessage `nmap:"skip"` - MetaWtVersion sql.NullString `nmap:"skip"` - MetaGoOS sql.NullString `nmap:"skip"` - MetaOSVersion sql.NullString `nmap:"skip"` - MetaKernelVersion sql.NullString `nmap:"skip"` - MetaSyncMessageVersion sql.NullInt64 `nmap:"skip"` - LocationCountryCode sql.NullString `nmap:"skip"` - LocationCityName sql.NullString `nmap:"skip"` + return networkmapdb.ConvertToNmdataPeers(peers) } diff --git a/management/internals/network_map_db/shared_types.go b/management/internals/network_map_db/shared_types.go index c2b6d78f2..ccedaafc4 100644 --- a/management/internals/network_map_db/shared_types.go +++ b/management/internals/network_map_db/shared_types.go @@ -92,6 +92,37 @@ type Network struct { PublicID sql.NullString } +// TODO add support for creating struct fields from denormalized fields +type Peer struct { + ID string + Key sql.NullString + SSHKey sql.NullString + DNSLabel sql.NullString + ExtraDNSLabels []byte `nmap:"json"` + UserID sql.NullString + SSHEnabled sql.NullBool + LoginExpirationEnabled sql.NullBool + LastLogin sql.NullTime + IP []byte `nmap:"json"` + IPv6 []byte `nmap:"json"` + PeerStatusRequiresApproval sql.NullBool `nmap:"map_to:RequiresApproval"` + PeerStatusConnected sql.NullBool `nmap:"skip"` + ProxyMetaEmbedded sql.NullBool `nmap:"skip"` + ProxyMetaCluster sql.NullString `nmap:"skip"` + MetaWtVersion sql.NullString `nmap:"skip"` + MetaGoOS sql.NullString `nmap:"skip"` + MetaOSVersion sql.NullString `nmap:"skip"` + MetaKernelVersion sql.NullString `nmap:"skip"` + MetaNetworkAddresses []byte `nmap:"skip,json"` + MetaFiles []byte `nmap:"skip,json"` + MetaCapabilities []byte `nmap:"skip,json"` + MetaFlags []byte `nmap:"skip,json"` + MetaSyncMessageVersion sql.NullInt64 `nmap:"skip"` + LocationCountryCode sql.NullString `nmap:"skip"` + LocationCityName sql.NullString `nmap:"skip"` + LocationConnectionIp []byte `nmap:"skip,json"` +} + func RecordTypeAndRdata(t, rdata string) (int, string, error) { switch t { case "A": @@ -157,3 +188,79 @@ func AppliedZoneCandidateFromZone(z nmdata.CustomZone, distributionGroups []stri Zone: z, } } + +func ConvertToNmdataPeers(peers []Peer) ([]nmdata.Peer, map[string][]*nmdata.Peer, error) { + toret := make([]nmdata.Peer, 0, len(peers)) + clusterToPeerIdx := make(map[string][]*nmdata.Peer) + for _, p := range peers { + dp := nmdata.Peer{} + err := FromSqlTypesToSharedTypes( + reflect.ValueOf(&p), reflect.ValueOf(&dp)) + if err != nil { + return nil, nil, err + } + + if p.ProxyMetaEmbedded.Valid { + dp.ProxyMeta.Embedded = p.ProxyMetaEmbedded.Bool + } + // This is only used to build private service candidates, not connected peers are skipped + if dp.ProxyMeta.Embedded && p.PeerStatusConnected.Bool { + clusterToPeerIdx[p.ProxyMetaCluster.String] = append(clusterToPeerIdx[p.ProxyMetaCluster.String], &dp) + } + if p.MetaWtVersion.Valid { + dp.Meta.WtVersion = p.MetaWtVersion.String + } + if p.MetaSyncMessageVersion.Valid { + dp.Meta.SyncMessageVersion = int(p.MetaSyncMessageVersion.Int64) + } + if p.MetaGoOS.Valid { + dp.Meta.GoOS = p.MetaGoOS.String + } + if p.MetaOSVersion.Valid { + dp.Meta.OSVersion = p.MetaOSVersion.String + } + if p.MetaKernelVersion.Valid { + dp.Meta.KernelVersion = p.MetaKernelVersion.String + } + if p.LocationCountryCode.Valid { + dp.Location.CountryCode = p.LocationCountryCode.String + } + if p.LocationCityName.Valid { + dp.Location.CityName = p.LocationCityName.String + } + if p.LocationConnectionIp != nil { + err := json.Unmarshal(p.LocationConnectionIp, &dp.Location.ConnectionIP) + if err != nil { + return toret, nil, err + } + } + if p.MetaFiles != nil { + err := json.Unmarshal(p.MetaFiles, &dp.Meta.Files) + if err != nil { + return toret, nil, err + } + } + if p.MetaCapabilities != nil { + err := json.Unmarshal(p.MetaCapabilities, &dp.Meta.Capabilities) + if err != nil { + return toret, nil, err + } + } + if p.MetaFlags != nil { + err := json.Unmarshal(p.MetaFlags, &dp.Meta.Flags) + if err != nil { + return toret, nil, err + } + } + if p.MetaNetworkAddresses != nil { + err := json.Unmarshal(p.MetaNetworkAddresses, &dp.Meta.NetworkAddresses) + if err != nil { + return toret, nil, err + } + } + + toret = append(toret, dp) + } + + return toret, clusterToPeerIdx, nil +} diff --git a/management/internals/network_map_db/sqlite/peer.go b/management/internals/network_map_db/sqlite/peer.go new file mode 100644 index 000000000..12d9e9ab7 --- /dev/null +++ b/management/internals/network_map_db/sqlite/peer.go @@ -0,0 +1,33 @@ +package networkmap_sqlite + +import ( + "context" + + networkmapdb "github.com/netbirdio/netbird/management/internals/network_map_db" + "github.com/netbirdio/netbird/shared/management/networkmap/nmdata" +) + +const ( + GetPeersQuery = ` + select id, key, ssh_key, dns_label, extra_dns_labels, user_id, ssh_enabled, login_expiration_enabled, last_login, ip, ipv6, + peer_status_requires_approval, peer_status_connected, proxy_meta_embedded, proxy_meta_cluster, + meta_wt_version, meta_go_os, meta_os_version, meta_kernel_version, meta_network_addresses, meta_files, meta_capabilities, meta_flags, meta_sync_message_version, + location_country_code, location_city_name, location_connection_ip + from peers + where account_id = ? + ` +) + +func (sc *SqliteStoreConn) GetPeers(ctx context.Context, accountId string) ([]nmdata.Peer, map[string][]*nmdata.Peer, error) { + rows, err := sc.Conn.QueryContext(ctx, GetPeersQuery, accountId) + if err != nil { + return nil, nil, err + } + + peers, err := CollectRowsForSqlite[networkmapdb.Peer](rows) + if err != nil { + return nil, nil, err + } + + return networkmapdb.ConvertToNmdataPeers(peers) +} diff --git a/management/internals/network_map_db/sqlite/sqlite_store.go b/management/internals/network_map_db/sqlite/sqlite_store.go index 82d9e3692..4c9112c62 100644 --- a/management/internals/network_map_db/sqlite/sqlite_store.go +++ b/management/internals/network_map_db/sqlite/sqlite_store.go @@ -120,9 +120,6 @@ func CollectRowsForSqlite[T any](rows *sql.Rows) ([]T, error) { return toret, nil } -func (s *SqliteStoreConn) GetPeers(ctx context.Context, accountId string) ([]nmdata.Peer, map[string][]*nmdata.Peer, error) { - return nil, nil, nil -} func (s *SqliteStoreConn) GetPolicies(ctx context.Context, accountId string) ([]nmdata.Policy, map[string]map[string]any, map[string]map[string]any, error) { return nil, nil, nil, nil }