[management] Add routing peer counter (#3036)

This commit is contained in:
Pascal Fischer
2024-12-13 11:57:07 +01:00
committed by GitHub
parent 86352f00fc
commit e436c39a86
16 changed files with 344 additions and 88 deletions
+26 -2
View File
@@ -1241,6 +1241,10 @@ components:
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
routing_peers_count:
description: Count of routing peers associated with the network
type: integer
example: 2
resources:
description: List of network resource IDs associated with the network
type: array
@@ -1251,8 +1255,9 @@ components:
- id
- routers
- resources
- routing_peers_count
- $ref: '#/components/schemas/NetworkRequest'
NetworkResourceRequest:
NetworkResourceMinimum:
type: object
properties:
name:
@@ -1270,6 +1275,19 @@ components:
required:
- name
- address
NetworkResourceRequest:
allOf:
- $ref: '#/components/schemas/NetworkResourceMinimum'
- type: object
properties:
groups:
description: Group IDs containing the resource
type: array
items:
type: string
example: "chacdk86lnnboviihd70"
required:
- groups
NetworkResource:
allOf:
- type: object
@@ -1280,10 +1298,16 @@ components:
example: chacdk86lnnboviihd7g
type:
$ref: '#/components/schemas/NetworkResourceType'
groups:
description: Groups that the resource belongs to
type: array
items:
$ref: '#/components/schemas/GroupMinimum'
required:
- id
- type
- $ref: '#/components/schemas/NetworkResourceRequest'
- groups
- $ref: '#/components/schemas/NetworkResourceMinimum'
NetworkResourceType:
description: Network resource type based of the address
type: string
+21
View File
@@ -532,6 +532,9 @@ type Network struct {
// Routers List of router IDs associated with the network
Routers []string `json:"routers"`
// RoutingPeersCount Count of routing peers associated with the network
RoutingPeersCount int `json:"routing_peers_count"`
}
// NetworkRequest defines model for NetworkRequest.
@@ -551,6 +554,9 @@ type NetworkResource struct {
// Description Network resource description
Description *string `json:"description,omitempty"`
// Groups Groups that the resource belongs to
Groups []GroupMinimum `json:"groups"`
// Id Network Resource ID
Id string `json:"id"`
@@ -561,6 +567,18 @@ type NetworkResource struct {
Type NetworkResourceType `json:"type"`
}
// NetworkResourceMinimum defines model for NetworkResourceMinimum.
type NetworkResourceMinimum struct {
// Address Network resource address (either a direct host like 1.1.1.1 or 1.1.1.1/32, or a subnet like 192.168.178.0/24, or a domain like example.com)
Address string `json:"address"`
// Description Network resource description
Description *string `json:"description,omitempty"`
// Name Network resource name
Name string `json:"name"`
}
// NetworkResourceRequest defines model for NetworkResourceRequest.
type NetworkResourceRequest struct {
// Address Network resource address (either a direct host like 1.1.1.1 or 1.1.1.1/32, or a subnet like 192.168.178.0/24, or a domain like example.com)
@@ -569,6 +587,9 @@ type NetworkResourceRequest struct {
// Description Network resource description
Description *string `json:"description,omitempty"`
// Groups Group IDs containing the resource
Groups []string `json:"groups"`
// Name Network resource name
Name string `json:"name"`
}
+1 -1
View File
@@ -94,7 +94,7 @@ func APIHandler(ctx context.Context, accountManager s.AccountManager, LocationMa
routes.AddEndpoints(api.AccountManager, authCfg, router)
dns.AddEndpoints(api.AccountManager, authCfg, router)
events.AddEndpoints(api.AccountManager, authCfg, router)
networks.AddEndpoints(api.AccountManager.GetNetworksManager(), api.AccountManager.GetAccountIDFromToken, authCfg, router)
networks.AddEndpoints(api.AccountManager.GetNetworksManager(), api.AccountManager.GetGroupsManager(), api.AccountManager.GetAccountIDFromToken, authCfg, router)
return rootRouter, nil
}
@@ -287,13 +287,7 @@ func toGroupResponse(peers []*nbpeer.Peer, group *types.Group) *api.Group {
peersMap[peer.ID] = peer
}
resMap := make(map[string]types.Resource, len(peers))
for _, peer := range peers {
peersMap[peer.ID] = peer
}
peerCache := make(map[string]api.PeerMinimum)
resCache := make(map[string]api.Resource)
gr := api.Group{
Id: group.ID,
Name: group.Name,
@@ -319,16 +313,8 @@ func toGroupResponse(peers []*nbpeer.Peer, group *types.Group) *api.Group {
gr.PeersCount = len(gr.Peers)
for _, res := range group.Resources {
_, ok := resCache[res.ID]
if !ok {
resource, ok := resMap[res.ID]
if !ok {
continue
}
resResp := resource.ToAPIResponse()
resCache[res.ID] = *resResp
gr.Resources = append(gr.Resources, *resResp)
}
resResp := res.ToAPIResponse()
gr.Resources = append(gr.Resources, *resResp)
}
gr.ResourcesCount = len(gr.Resources)
@@ -8,36 +8,42 @@ import (
"github.com/gorilla/mux"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/http/configs"
"github.com/netbirdio/netbird/management/server/http/util"
"github.com/netbirdio/netbird/management/server/jwtclaims"
"github.com/netbirdio/netbird/management/server/networks"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
"github.com/netbirdio/netbird/management/server/networks/types"
"github.com/netbirdio/netbird/management/server/status"
nbtypes "github.com/netbirdio/netbird/management/server/types"
)
// handler is a handler that returns networks of the account
type handler struct {
networksManager networks.Manager
groupsManager groups.Manager
extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error)
claimsExtractor *jwtclaims.ClaimsExtractor
}
func AddEndpoints(networksManager networks.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
networksHandler := newHandler(networksManager, extractFromToken, authCfg)
func AddEndpoints(networksManager networks.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
addRouterEndpoints(networksManager.GetRouterManager(), extractFromToken, authCfg, router)
addResourceEndpoints(networksManager.GetResourceManager(), groupsManager, extractFromToken, authCfg, router)
networksHandler := newHandler(networksManager, groupsManager, extractFromToken, authCfg)
router.HandleFunc("/networks", networksHandler.getAllNetworks).Methods("GET", "OPTIONS")
router.HandleFunc("/networks", networksHandler.createNetwork).Methods("POST", "OPTIONS")
router.HandleFunc("/networks/{networkId}", networksHandler.getNetwork).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}", networksHandler.updateNetwork).Methods("PUT", "OPTIONS")
router.HandleFunc("/networks/{networkId}", networksHandler.deleteNetwork).Methods("DELETE", "OPTIONS")
addRouterEndpoints(networksManager.GetRouterManager(), extractFromToken, authCfg, router)
addResourceEndpoints(networksManager.GetResourceManager(), extractFromToken, authCfg, router)
}
func newHandler(networksManager networks.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *handler {
func newHandler(networksManager networks.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *handler {
return &handler{
networksManager: networksManager,
groupsManager: groupsManager,
extractFromToken: extractFromToken,
claimsExtractor: jwtclaims.NewClaimsExtractor(
jwtclaims.WithAudience(authCfg.Audience),
@@ -60,24 +66,25 @@ func (h *handler) getAllNetworks(w http.ResponseWriter, r *http.Request) {
return
}
routers, err := h.networksManager.GetRouterManager().GetAllRouterIDsInAccount(r.Context(), accountID, userID)
resourceIDs, err := h.networksManager.GetResourceManager().GetAllResourceIDsInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
resources, err := h.networksManager.GetResourceManager().GetAllResourceIDsInAccount(r.Context(), accountID, userID)
groups, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
var networkResponse []*api.Network
for _, network := range networks {
networkResponse = append(networkResponse, network.ToAPIResponse(routers[network.ID], resources[network.ID]))
routers, err := h.networksManager.GetRouterManager().GetAllRoutersInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
util.WriteJSONObject(r.Context(), w, networkResponse)
util.WriteJSONObject(r.Context(), w, h.generateNetworkResponse(networks, routers, resourceIDs, groups))
}
func (h *handler) createNetwork(w http.ResponseWriter, r *http.Request) {
@@ -105,7 +112,7 @@ func (h *handler) createNetwork(w http.ResponseWriter, r *http.Request) {
return
}
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse([]string{}, []string{}))
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse([]string{}, []string{}, 0))
}
func (h *handler) getNetwork(w http.ResponseWriter, r *http.Request) {
@@ -129,13 +136,13 @@ func (h *handler) getNetwork(w http.ResponseWriter, r *http.Request) {
return
}
routerIDs, resourceIDs, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
routerIDs, resourceIDs, peerCount, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs))
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs, peerCount))
}
func (h *handler) updateNetwork(w http.ResponseWriter, r *http.Request) {
@@ -171,13 +178,13 @@ func (h *handler) updateNetwork(w http.ResponseWriter, r *http.Request) {
return
}
routerIDs, resourceIDs, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
routerIDs, resourceIDs, peerCount, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs))
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs, peerCount))
}
func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request) {
@@ -204,10 +211,10 @@ func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request) {
util.WriteJSONObject(r.Context(), w, util.EmptyObject{})
}
func (h *handler) collectIDsInNetwork(ctx context.Context, accountID, userID, networkID string) ([]string, []string, error) {
func (h *handler) collectIDsInNetwork(ctx context.Context, accountID, userID, networkID string) ([]string, []string, int, error) {
resources, err := h.networksManager.GetResourceManager().GetAllResourcesInNetwork(ctx, accountID, userID, networkID)
if err != nil {
return nil, nil, fmt.Errorf("failed to get resources in network: %w", err)
return nil, nil, 0, fmt.Errorf("failed to get resources in network: %w", err)
}
var resourceIDs []string
@@ -217,13 +224,48 @@ func (h *handler) collectIDsInNetwork(ctx context.Context, accountID, userID, ne
routers, err := h.networksManager.GetRouterManager().GetAllRoutersInNetwork(ctx, accountID, userID, networkID)
if err != nil {
return nil, nil, fmt.Errorf("failed to get routers in network: %w", err)
return nil, nil, 0, fmt.Errorf("failed to get routers in network: %w", err)
}
groups, err := h.groupsManager.GetAllGroups(ctx, accountID, userID)
if err != nil {
return nil, nil, 0, fmt.Errorf("failed to get groups: %w", err)
}
peerCounter := 0
var routerIDs []string
for _, router := range routers {
routerIDs = append(routerIDs, router.ID)
if router.Peer != "" {
peerCounter++
}
if len(router.PeerGroups) > 0 {
for _, groupID := range router.PeerGroups {
peerCounter += len(groups[groupID].Peers)
}
}
}
return routerIDs, resourceIDs, nil
return routerIDs, resourceIDs, peerCounter, nil
}
func (h *handler) generateNetworkResponse(networks []*types.Network, routers map[string][]*routerTypes.NetworkRouter, resourceIDs map[string][]string, groups map[string]*nbtypes.Group) []*api.Network {
var networkResponse []*api.Network
for _, network := range networks {
routerIDs := []string{}
peerCounter := 0
for _, router := range routers[network.ID] {
routerIDs = append(routerIDs, router.ID)
if router.Peer != "" {
peerCounter++
}
if len(router.PeerGroups) > 0 {
for _, groupID := range router.PeerGroups {
peerCounter += len(groups[groupID].Peers)
}
}
}
networkResponse = append(networkResponse, network.ToAPIResponse(routerIDs, resourceIDs[network.ID], peerCounter))
}
return networkResponse
}
@@ -7,33 +7,37 @@ import (
"github.com/gorilla/mux"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/http/configs"
"github.com/netbirdio/netbird/management/server/http/util"
"github.com/netbirdio/netbird/management/server/jwtclaims"
"github.com/netbirdio/netbird/management/server/networks/resources"
"github.com/netbirdio/netbird/management/server/networks/resources/types"
nbtypes "github.com/netbirdio/netbird/management/server/types"
)
type resourceHandler struct {
resourceManager resources.Manager
groupsManager groups.Manager
extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error)
claimsExtractor *jwtclaims.ClaimsExtractor
}
func addResourceEndpoints(resourcesManager resources.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
resourceHandler := newResourceHandler(resourcesManager, extractFromToken, authCfg)
func addResourceEndpoints(resourcesManager resources.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
resourceHandler := newResourceHandler(resourcesManager, groupsManager, extractFromToken, authCfg)
router.HandleFunc("/networks/resources", resourceHandler.getAllResourcesInAccount).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.getAllResourcesInNetwork).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.createResource).Methods("POST", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.getResource).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.updateResource).Methods("PUT", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.deleteResource).Methods("DELETE", "OPTIONS")
router.HandleFunc("/networks/resources", resourceHandler.getAllResourcesInAccount).Methods("GET", "OPTIONS")
}
func newResourceHandler(resourceManager resources.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *resourceHandler {
func newResourceHandler(resourceManager resources.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *resourceHandler {
return &resourceHandler{
resourceManager: resourceManager,
groupsManager: groupsManager,
extractFromToken: extractFromToken,
claimsExtractor: jwtclaims.NewClaimsExtractor(
jwtclaims.WithAudience(authCfg.Audience),
@@ -57,9 +61,16 @@ func (h *resourceHandler) getAllResourcesInNetwork(w http.ResponseWriter, r *htt
return
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
var resourcesResponse []*api.NetworkResource
for _, resource := range resources {
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse())
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse(groupMinimumInfo))
}
util.WriteJSONObject(r.Context(), w, resourcesResponse)
@@ -78,9 +89,16 @@ func (h *resourceHandler) getAllResourcesInAccount(w http.ResponseWriter, r *htt
return
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
var resourcesResponse []*api.NetworkResource
for _, resource := range resources {
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse())
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse(groupMinimumInfo))
}
util.WriteJSONObject(r.Context(), w, resourcesResponse)
@@ -112,7 +130,26 @@ func (h *resourceHandler) createResource(w http.ResponseWriter, r *http.Request)
return
}
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse())
res := nbtypes.Resource{
ID: resource.ID,
Type: resource.Type.String(),
}
for _, groupID := range req.Groups {
err = h.groupsManager.AddResourceToGroup(r.Context(), accountID, userID, groupID, &res)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse(groupMinimumInfo))
}
func (h *resourceHandler) getResource(w http.ResponseWriter, r *http.Request) {
@@ -131,7 +168,14 @@ func (h *resourceHandler) getResource(w http.ResponseWriter, r *http.Request) {
return
}
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse())
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse(groupMinimumInfo))
}
func (h *resourceHandler) updateResource(w http.ResponseWriter, r *http.Request) {
@@ -161,7 +205,26 @@ func (h *resourceHandler) updateResource(w http.ResponseWriter, r *http.Request)
return
}
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse())
res := nbtypes.Resource{
ID: resource.ID,
Type: resource.Type.String(),
}
for _, groupID := range req.Groups {
err = h.groupsManager.AddResourceToGroup(r.Context(), accountID, userID, groupID, &res)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse(groupMinimumInfo))
}
func (h *resourceHandler) deleteResource(w http.ResponseWriter, r *http.Request) {
@@ -10,6 +10,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/management/server"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/http/configs"
"github.com/netbirdio/netbird/management/server/http/util"
@@ -71,7 +72,7 @@ func (h *Handler) getPeer(ctx context.Context, account *types.Account, peerID, u
}
dnsDomain := h.accountManager.GetDNSDomain()
groupsInfo := toGroupsInfo(account.Groups, peer.ID)
groupsInfo := groups.ToGroupsInfo(account.Groups, peer.ID)
validPeers, err := h.accountManager.GetValidatedPeers(account)
if err != nil {
@@ -115,7 +116,7 @@ func (h *Handler) updatePeer(ctx context.Context, account *types.Account, userID
}
dnsDomain := h.accountManager.GetDNSDomain()
groupMinimumInfo := toGroupsInfo(account.Groups, peer.ID)
groupMinimumInfo := groups.ToGroupsInfo(account.Groups, peer.ID)
validPeers, err := h.accountManager.GetValidatedPeers(account)
if err != nil {
@@ -200,8 +201,8 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
}
groupsMap := map[string]*types.Group{}
groups, _ := h.accountManager.GetAllGroups(r.Context(), accountID, userID)
for _, group := range groups {
grps, _ := h.accountManager.GetAllGroups(r.Context(), accountID, userID)
for _, group := range grps {
groupsMap[group.ID] = group
}
@@ -212,7 +213,7 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := toGroupsInfo(groupsMap, peer.ID)
groupMinimumInfo := groups.ToGroupsInfo(groupsMap, peer.ID)
respBody = append(respBody, toPeerListItemResponse(peerToReturn, groupMinimumInfo, dnsDomain, 0))
}
@@ -324,30 +325,6 @@ func peerToAccessiblePeer(peer *nbpeer.Peer, dnsDomain string) api.AccessiblePee
}
}
func toGroupsInfo(groups map[string]*types.Group, peerID string) []api.GroupMinimum {
groupsInfo := []api.GroupMinimum{}
groupsChecked := make(map[string]struct{})
for _, group := range groups {
_, ok := groupsChecked[group.ID]
if ok {
continue
}
groupsChecked[group.ID] = struct{}{}
for _, pk := range group.Peers {
if pk == peerID {
info := api.GroupMinimum{
Id: group.ID,
Name: group.Name,
PeersCount: len(group.Peers),
}
groupsInfo = append(groupsInfo, info)
break
}
}
}
return groupsInfo
}
func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, approved bool) *api.Peer {
osVersion := peer.Meta.OSVersion
if osVersion == "" {