support for applied zone candidates

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
This commit is contained in:
Dmitri Dolguikh
2026-08-03 14:32:54 +02:00
parent 2f399f1e6e
commit e2797360f4
4 changed files with 46 additions and 30 deletions
@@ -29,7 +29,7 @@ type NetworkMapDBStore interface {
GetNetworkResources(ctx context.Context, accountId string) ([]nmdata.NetworkResource, error) GetNetworkResources(ctx context.Context, accountId string) ([]nmdata.NetworkResource, error)
GetNetworkRouters(ctx context.Context, accountId string) (map[string]map[string]*nmdata.NetworkRouter, error) GetNetworkRouters(ctx context.Context, accountId string) (map[string]map[string]*nmdata.NetworkRouter, error)
GetNetwork(ctx context.Context, accountId string) (nmdata.Network, error) GetNetwork(ctx context.Context, accountId string) (nmdata.Network, error)
GetAccountZones(ctx context.Context, accountId string) ([]nmdata.CustomZone, error) GetAppliedZoneCandidates(ctx context.Context, accountId string) ([]networkmap.AppliedZoneCandidate, error)
GetAccountSettings(ctx context.Context, accountId string) (nmdata.AccountSettingsInfo, error) GetAccountSettings(ctx context.Context, accountId string) (nmdata.AccountSettingsInfo, error)
GetPostureChecks(ctx context.Context, accountId string) ([]nmdata.PostureChecks, error) GetPostureChecks(ctx context.Context, accountId string) ([]nmdata.PostureChecks, error)
GetNetworkMapData(ctx context.Context, accountId string) (*networkmap.NetworkMapData, error) GetNetworkMapData(ctx context.Context, accountId string) (*networkmap.NetworkMapData, error)
@@ -3,6 +3,7 @@ package networkmap_pgsql
import ( import (
"context" "context"
"database/sql" "database/sql"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
@@ -10,6 +11,7 @@ import (
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/miekg/dns" "github.com/miekg/dns"
networkmapdb "github.com/netbirdio/netbird/management/internals/network_map_db" networkmapdb "github.com/netbirdio/netbird/management/internals/network_map_db"
"github.com/netbirdio/netbird/shared/management/networkmap"
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata" "github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
) )
@@ -17,7 +19,7 @@ var DnsUnsupportedRecordTypeError = errors.New("unsupported record type")
const ( const (
GetAccountZonesQuery = ` GetAccountZonesQuery = `
select zones.id as id, domain, enable_search_domain as search_domain_disabled, select zones.id as id, domain, enable_search_domain as search_domain_disabled, distribution_groups,
r.name as record_name, r.type as record_type, 'IN' record_class, r.ttl as record_ttl, r.content as record_rdata r.name as record_name, r.type as record_type, 'IN' record_class, r.ttl as record_ttl, r.content as record_rdata
from zones from zones
left join records as r on r.zone_id = zones.id left join records as r on r.zone_id = zones.id
@@ -25,15 +27,15 @@ const (
` `
) )
func (pg *PgStore) GetAccountZones(ctx context.Context, accountId string) ([]nmdata.CustomZone, error) { func (pg *PgStore) GetAppliedZoneCandidates(ctx context.Context, accountId string) ([]networkmap.AppliedZoneCandidate, error) {
c, err := pg.Pool.Acquire(ctx) c, err := pg.Pool.Acquire(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return GetAccountZonesViaPgxConnection(ctx, c.Conn(), accountId) return GetAppliedZoneCandidatesViaPgxConnection(ctx, c.Conn(), accountId)
} }
func GetAccountZonesViaPgxConnection(ctx context.Context, conn *pgx.Conn, accountId string) ([]nmdata.CustomZone, error) { func GetAppliedZoneCandidatesViaPgxConnection(ctx context.Context, conn *pgx.Conn, accountId string) ([]networkmap.AppliedZoneCandidate, error) {
rows, err := conn.Query(ctx, GetAccountZonesQuery, accountId) rows, err := conn.Query(ctx, GetAccountZonesQuery, accountId)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -44,7 +46,7 @@ func GetAccountZonesViaPgxConnection(ctx context.Context, conn *pgx.Conn, accoun
return nil, err return nil, err
} }
toret := make([]nmdata.CustomZone, 0, len(zones)) toret := make([]networkmap.AppliedZoneCandidate, 0, len(zones))
currentZoneId := "" currentZoneId := ""
for _, z := range zones { for _, z := range zones {
zone := nmdata.CustomZone{} zone := nmdata.CustomZone{}
@@ -54,6 +56,11 @@ func GetAccountZonesViaPgxConnection(ctx context.Context, conn *pgx.Conn, accoun
return nil, err return nil, err
} }
var distributionGroups []string
if err := json.Unmarshal(z.DistributionGroups, &distributionGroups); err != nil {
return nil, err
}
rtype, rdata, err := recordTypeAndRdata(z.RecordType.String, z.RecordRData.String) rtype, rdata, err := recordTypeAndRdata(z.RecordType.String, z.RecordRData.String)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -68,25 +75,26 @@ func GetAccountZonesViaPgxConnection(ctx context.Context, conn *pgx.Conn, accoun
zone.Records = []nmdata.SimpleRecord{record} zone.Records = []nmdata.SimpleRecord{record}
if len(toret) == 0 { if len(toret) == 0 {
toret = append(toret, zone) toret = append(toret, appliedZoneCandidateFromZone(zone, distributionGroups))
currentZoneId = z.Id currentZoneId = z.Id
continue continue
} }
if z.Id == currentZoneId { if z.Id == currentZoneId {
lastZone := &toret[len(toret)-1] lastZone := &toret[len(toret)-1]
lastZone.Records = append(lastZone.Records, record) lastZone.Zone.Records = append(lastZone.Zone.Records, record)
continue continue
} }
toret = append(toret, zone) toret = append(toret, appliedZoneCandidateFromZone(zone, distributionGroups))
currentZoneId = z.Id currentZoneId = z.Id
} }
return toret, nil return toret, nil
} }
type zone struct { type zone struct {
Id string `nmap:"skip"` Id string `nmap:"skip"`
DistributionGroups json.RawMessage `nmap:"skip"`
Domain sql.NullString Domain sql.NullString
SearchDomainDisabled sql.NullBool SearchDomainDisabled sql.NullBool
RecordName sql.NullString `nmap:"skip"` RecordName sql.NullString `nmap:"skip"`
@@ -108,3 +116,10 @@ func recordTypeAndRdata(t, rdata string) (int, string, error) {
return 0, "", fmt.Errorf("record type: %s %w", t, DnsUnsupportedRecordTypeError) return 0, "", fmt.Errorf("record type: %s %w", t, DnsUnsupportedRecordTypeError)
} }
} }
func appliedZoneCandidateFromZone(z nmdata.CustomZone, distributionGroups []string) networkmap.AppliedZoneCandidate {
return networkmap.AppliedZoneCandidate{
DistributionGroups: distributionGroups,
Zone: z,
}
}
@@ -200,7 +200,7 @@ func TestGetAccountZones(t *testing.T) {
// err = loadSQL(ctx, s.pool, initDb) // err = loadSQL(ctx, s.pool, initDb)
//assert.NoError(t, err) //assert.NoError(t, err)
zones, err := s.GetAccountZones(ctx, "d4g66rjl0ubs73b2q3b0") //"ckd7ee2fic3c73dtendg") zones, err := s.GetAppliedZoneCandidates(ctx, "d4g66rjl0ubs73b2q3b0") //"ckd7ee2fic3c73dtendg")
assert.NoError(t, err) assert.NoError(t, err)
fmt.Print(zones) fmt.Print(zones)
@@ -18,10 +18,10 @@ func (pg *PgStore) GetNetworkMapData(ctx context.Context, accountId string) (*ne
if err != nil { if err != nil {
return rollbackAndReturnError(ctx, tx, err) return rollbackAndReturnError(ctx, tx, err)
} }
// dnsZones, err := GetAccountZonesViaPgxConnection(ctx, tx.Conn(), accountId) dnsZones, err := GetAppliedZoneCandidatesViaPgxConnection(ctx, tx.Conn(), accountId)
// if err != nil { if err != nil {
// return rollbackAndReturnError(ctx, tx, err) return rollbackAndReturnError(ctx, tx, err)
// } }
groups, resourceToGroupIdx, err := GetGroupsViaPgxConnection(ctx, tx.Conn(), accountId) groups, resourceToGroupIdx, err := GetGroupsViaPgxConnection(ctx, tx.Conn(), accountId)
if err != nil { if err != nil {
return rollbackAndReturnError(ctx, tx, err) return rollbackAndReturnError(ctx, tx, err)
@@ -102,21 +102,22 @@ func (pg *PgStore) GetNetworkMapData(ctx context.Context, accountId string) (*ne
} }
toret := networkmap.NetworkMapData{ toret := networkmap.NetworkMapData{
AccountSettings: &acctSettings, AccountSettings: &acctSettings,
DNSSettings: &dnsSettings, DNSSettings: &dnsSettings,
Network: &network, Network: &network,
Peers: toMap(peers, func(p nmdata.Peer) string { return p.ID }), Peers: toMap(peers, func(p nmdata.Peer) string { return p.ID }),
Groups: toMap(groups, func(g nmdata.Group) string { return g.PublicID }), Groups: toMap(groups, func(g nmdata.Group) string { return g.PublicID }),
Policies: toSliceOfPtrs(policies), Policies: toSliceOfPtrs(policies),
ResourcePolicies: resourcePolicies, ResourcePolicies: resourcePolicies,
Routes: toSliceOfPtrs(routes), Routes: toSliceOfPtrs(routes),
Routers: routers, Routers: routers,
NameServerGroups: toSliceOfPtrs(nsGroups), NameServerGroups: toSliceOfPtrs(nsGroups),
NetworkResources: toSliceOfPtrs(networkResources), NetworkResources: toSliceOfPtrs(networkResources),
PostureChecks: toMap(postureChecks, func(pc nmdata.PostureChecks) string { return pc.ID }), PostureChecks: toMap(postureChecks, func(pc nmdata.PostureChecks) string { return pc.ID }),
AllowedUserIDs: allowedUserIds, AllowedUserIDs: allowedUserIds,
GroupIDToUserIDs: groupsToUserIds, GroupIDToUserIDs: groupsToUserIds,
NetworkXIDToPublicID: networkXIDToPublicID, // TODO (dmitri) maybe we can switch to public ids everywhere? NetworkXIDToPublicID: networkXIDToPublicID, // TODO (dmitri) maybe we can switch to public ids everywhere?
AppliedZoneCandidates: dnsZones,
} }
return &toret, nil return &toret, nil