diff --git a/management/server/account.go b/management/server/account.go index 517f1368177..8856735b7ef 100644 --- a/management/server/account.go +++ b/management/server/account.go @@ -254,6 +254,28 @@ func (a *Account) getEnabledAndDisabledRoutesByPeer(peerID string) ([]*route.Rou var enabledRoutes []*route.Route var disabledRoutes []*route.Route for _, r := range a.Routes { + if r.PeersGroup != "" { + group := a.GetGroup(r.PeersGroup) + if group == nil { + log.Errorf("route %s has peers group %s that doesn't exist under account %s", r.ID, r.PeersGroup, a.Id) + continue + } + for _, id := range group.Peers { + peer := a.GetPeer(id) + if peer == nil { + log.Errorf("route %s has peers group %s that which has %s that doesn't exist under account %s", + r.ID, r.PeersGroup, id, a.Id) + continue + } + raut := r.Copy() + raut.Peer = peer.Key + if r.Enabled { + enabledRoutes = append(enabledRoutes, raut) + continue + } + disabledRoutes = append(disabledRoutes, raut) + } + } if r.Peer == peerID { // We need to set Peer.Key instead of Peer.ID because this object will be sent to agents as part of a network map. // Ideally we should have a separate field for that, but fine for now. @@ -317,7 +339,31 @@ func (a *Account) GetPeerNetworkMap(peerID, dnsDomain string) *NetworkMap { peersToConnect = append(peersToConnect, p) } // Please mind, that the returned route.Route objects will contain Peer.Key instead of Peer.ID. - routesUpdate := a.getRoutesToSync(peerID, peersToConnect) + routes := a.getRoutesToSync(peerID, peersToConnect) + + // TODO(yury): each route can contain peers group. We should unfold them to peers + var routesUpdate []*route.Route + seenPeer := make(map[string]bool) + for _, r := range routes { + if r.PeersGroup == "" { + routesUpdate = append(routesUpdate, r) + continue + } + if group := a.GetGroup(r.PeersGroup); group != nil { + for _, peerId := range group.Peers { + peer := a.GetPeer(peerId) + if peer == nil { + continue + } + if _, ok := seenPeer[peer.Key]; !ok { + rCopy := r.Copy() + rCopy.Peer = peer.Key + routesUpdate = append(routesUpdate, rCopy) + } + seenPeer[peer.Key] = true + } + } + } dnsManagementStatus := a.getPeerDNSManagementStatus(peerID) dnsUpdate := nbdns.Config{ diff --git a/management/server/route_test.go b/management/server/route_test.go index 8d62340d1f4..3e70cb37e23 100644 --- a/management/server/route_test.go +++ b/management/server/route_test.go @@ -927,7 +927,57 @@ func TestDeleteRoute(t *testing.T) { } } -// TODO(yury): this test needs to be extended with peers group +func TestGetNetworkMap_RouteSyncPeersGroup(t *testing.T) { + baseRoute := &route.Route{ + Network: netip.MustParsePrefix("192.168.0.0/16"), + NetID: "superNet", + NetworkType: route.IPv4Network, + PeersGroup: routeGroupHA, + Description: "ha route", + Masquerade: false, + Metric: 9999, + Enabled: true, + Groups: []string{routeGroup1, routeGroup2}, + } + + am, err := createRouterManager(t) + if err != nil { + t.Error("failed to create account manager") + } + + account, err := initTestRouteAccount(t, am) + if err != nil { + t.Error("failed to init testing account") + } + + newAccountRoutes, err := am.GetNetworkMap(peer1ID) + require.NoError(t, err) + require.Len(t, newAccountRoutes.Routes, 0, "new accounts should have no routes") + + newRoute, err := am.CreateRoute( + account.Id, baseRoute.Network.String(), baseRoute.Peer, baseRoute.PeersGroup, baseRoute.Description, + baseRoute.NetID, baseRoute.Masquerade, baseRoute.Metric, baseRoute.Groups, baseRoute.Enabled, userID) + require.NoError(t, err) + require.Equal(t, newRoute.Enabled, true) + + peer1Routes, err := am.GetNetworkMap(peer1ID) + require.NoError(t, err) + require.Len(t, peer1Routes.Routes, 2, "HA route should have more than 1 peer") + + peer2Routes, err := am.GetNetworkMap(peer2ID) + require.NoError(t, err) + require.Len(t, peer2Routes.Routes, 2, "HA route should have more than 1 peer") + + //TODO(yury): test adding peer to the group. route should have that peer + + err = am.DeleteRoute(account.Id, newRoute.ID, userID) + require.NoError(t, err) + + peer1DeletedRoute, err := am.GetNetworkMap(peer1ID) + require.NoError(t, err) + require.Len(t, peer1DeletedRoute.Routes, 0, "we should receive one route for peer1") +} + func TestGetNetworkMap_RouteSync(t *testing.T) { // no routes for peer in different groups // no routes when route is deleted