mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-20 09:16:40 +00:00
Add network routes distribution groups (#606)
Updated tests, API, and account manager methods Sync routes to peers in the distribution groups Added store upgrade by adding the All group to routes that don't have them
This commit is contained in:
@@ -379,6 +379,11 @@ components:
|
||||
masquerade:
|
||||
description: Indicate if peer should masquerade traffic to this route's prefix
|
||||
type: boolean
|
||||
groups:
|
||||
description: Route group tag groups
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- description
|
||||
@@ -388,6 +393,7 @@ components:
|
||||
- network
|
||||
- metric
|
||||
- masquerade
|
||||
- groups
|
||||
Route:
|
||||
allOf:
|
||||
- type: object
|
||||
@@ -410,7 +416,7 @@ components:
|
||||
path:
|
||||
description: Route field to update in form /<field>
|
||||
type: string
|
||||
enum: [ "network","network_id","description","enabled","peer","metric","masquerade" ]
|
||||
enum: [ "network","network_id","description","enabled","peer","metric","masquerade", "groups" ]
|
||||
required:
|
||||
- path
|
||||
Nameserver:
|
||||
|
||||
@@ -65,6 +65,7 @@ const (
|
||||
const (
|
||||
RoutePatchOperationPathDescription RoutePatchOperationPath = "description"
|
||||
RoutePatchOperationPathEnabled RoutePatchOperationPath = "enabled"
|
||||
RoutePatchOperationPathGroups RoutePatchOperationPath = "groups"
|
||||
RoutePatchOperationPathMasquerade RoutePatchOperationPath = "masquerade"
|
||||
RoutePatchOperationPathMetric RoutePatchOperationPath = "metric"
|
||||
RoutePatchOperationPathNetwork RoutePatchOperationPath = "network"
|
||||
@@ -296,6 +297,9 @@ type Route struct {
|
||||
// Enabled Route status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Groups Route group tag groups
|
||||
Groups []string `json:"groups"`
|
||||
|
||||
// Id Route Id
|
||||
Id string `json:"id"`
|
||||
|
||||
@@ -344,6 +348,9 @@ type RouteRequest struct {
|
||||
// Enabled Route status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Groups Route group tag groups
|
||||
Groups []string `json:"groups"`
|
||||
|
||||
// Masquerade Indicate if peer should masquerade traffic to this route's prefix
|
||||
Masquerade bool `json:"masquerade"`
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func (h *Routes) CreateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
newRoute, err := h.accountManager.CreateRoute(account.Id, newPrefix.String(), peerKey, req.Description, req.NetworkId, req.Masquerade, req.Metric, req.Enabled)
|
||||
newRoute, err := h.accountManager.CreateRoute(account.Id, newPrefix.String(), peerKey, req.Description, req.NetworkId, req.Masquerade, req.Metric, req.Groups, req.Enabled)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
@@ -162,6 +162,7 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Metric: req.Metric,
|
||||
Description: req.Description,
|
||||
Enabled: req.Enabled,
|
||||
Groups: req.Groups,
|
||||
}
|
||||
|
||||
err = h.accountManager.SaveRoute(account.Id, newRoute)
|
||||
@@ -298,6 +299,16 @@ func (h *Routes) PatchRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Type: server.UpdateRouteEnabled,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.RoutePatchOperationPathGroups:
|
||||
if patch.Op != api.RoutePatchOperationOpReplace {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument,
|
||||
"groups field only accepts replace operation, got %s", patch.Op), w)
|
||||
return
|
||||
}
|
||||
operations = append(operations, server.RouteUpdateOperation{
|
||||
Type: server.UpdateRouteGroups,
|
||||
Values: patch.Value,
|
||||
})
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "invalid patch path"), w)
|
||||
return
|
||||
@@ -383,5 +394,6 @@ func toRouteResponse(account *server.Account, serverRoute *route.Route) *api.Rou
|
||||
NetworkType: serverRoute.NetworkType.String(),
|
||||
Masquerade: serverRoute.Masquerade,
|
||||
Metric: serverRoute.Metric,
|
||||
Groups: serverRoute.Groups,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ const (
|
||||
notFoundPeerID = "100.64.0.200"
|
||||
existingPeerKey = "existingPeerKey"
|
||||
testAccountID = "test_id"
|
||||
existingGroupID = "testGroup"
|
||||
)
|
||||
|
||||
var baseExistingRoute = &route.Route{
|
||||
@@ -39,6 +40,7 @@ var baseExistingRoute = &route.Route{
|
||||
Metric: 9999,
|
||||
Masquerade: false,
|
||||
Enabled: true,
|
||||
Groups: []string{existingGroupID},
|
||||
}
|
||||
|
||||
var testingAccount = &server.Account{
|
||||
@@ -64,7 +66,7 @@ func initRoutesTestData() *Routes {
|
||||
}
|
||||
return nil, status.Errorf(status.NotFound, "route with ID %s not found", routeID)
|
||||
},
|
||||
CreateRouteFunc: func(accountID string, network, peer, description, netID string, masquerade bool, metric int, enabled bool) (*route.Route, error) {
|
||||
CreateRouteFunc: func(accountID string, network, peer, description, netID string, masquerade bool, metric int, groups []string, enabled bool) (*route.Route, error) {
|
||||
networkType, p, _ := route.ParseNetwork(network)
|
||||
return &route.Route{
|
||||
ID: existingRouteID,
|
||||
@@ -75,6 +77,7 @@ func initRoutesTestData() *Routes {
|
||||
Description: description,
|
||||
Masquerade: masquerade,
|
||||
Enabled: enabled,
|
||||
Groups: groups,
|
||||
}, nil
|
||||
},
|
||||
SaveRouteFunc: func(_ string, _ *route.Route) error {
|
||||
@@ -116,6 +119,8 @@ func initRoutesTestData() *Routes {
|
||||
routeToUpdate.Masquerade, _ = strconv.ParseBool(operation.Values[0])
|
||||
case server.UpdateRouteEnabled:
|
||||
routeToUpdate.Enabled, _ = strconv.ParseBool(operation.Values[0])
|
||||
case server.UpdateRouteGroups:
|
||||
routeToUpdate.Groups = operation.Values
|
||||
default:
|
||||
return nil, fmt.Errorf("no operation")
|
||||
}
|
||||
@@ -181,7 +186,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID))),
|
||||
[]byte(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID))),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedRoute: &api.Route{
|
||||
@@ -193,13 +198,14 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
Enabled: false,
|
||||
Groups: []string{existingGroupID},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "POST Not Found Peer",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", notFoundPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", notFoundPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -207,7 +213,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "POST Invalid Network Identifier",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"12345678901234567890qwertyuiopqwertyuiop1\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"12345678901234567890qwertyuiopqwertyuiop1\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -215,7 +221,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "POST Invalid Network",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/34\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/34\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -223,7 +229,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT OK",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedRoute: &api.Route{
|
||||
@@ -235,13 +241,14 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
Enabled: false,
|
||||
Groups: []string{existingGroupID},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PUT Not Found Route",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + notFoundRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -249,7 +256,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT Not Found Peer",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", notFoundPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", notFoundPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -257,7 +264,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT Invalid Network Identifier",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"12345678901234567890qwertyuiopqwertyuiop1\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"12345678901234567890qwertyuiopqwertyuiop1\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -265,7 +272,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT Invalid Network",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/34\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/34\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\",\"groups\":[\"%s\"]}", existingPeerID, existingGroupID)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -285,6 +292,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Masquerade: baseExistingRoute.Masquerade,
|
||||
Enabled: baseExistingRoute.Enabled,
|
||||
Metric: baseExistingRoute.Metric,
|
||||
Groups: baseExistingRoute.Groups,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -304,6 +312,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
Masquerade: baseExistingRoute.Masquerade,
|
||||
Enabled: baseExistingRoute.Enabled,
|
||||
Metric: baseExistingRoute.Metric,
|
||||
Groups: baseExistingRoute.Groups,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user