mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
Add Network ID and rename Prefix to Network (#432)
Adding network ID will allow us to group Renaming Prefix with Network will keep things more clear and Consistent
This commit is contained in:
@@ -282,14 +282,19 @@ components:
|
||||
description:
|
||||
description: Route description
|
||||
type: string
|
||||
network_id:
|
||||
description: Route network identifier, to group HA routes
|
||||
type: string
|
||||
maxLength: 40
|
||||
minLength: 1
|
||||
enabled:
|
||||
description: Route status
|
||||
type: boolean
|
||||
peer:
|
||||
description: Peer Identifier associated with route
|
||||
type: string
|
||||
prefix:
|
||||
description: Prefix or network range in CIDR format
|
||||
network:
|
||||
description: Network range in CIDR format
|
||||
type: string
|
||||
metric:
|
||||
description: Route metric number. Lowest number has higher priority
|
||||
@@ -302,9 +307,10 @@ components:
|
||||
required:
|
||||
- id
|
||||
- description
|
||||
- network_id
|
||||
- enabled
|
||||
- peer
|
||||
- prefix
|
||||
- network
|
||||
- metric
|
||||
- masquerade
|
||||
Route:
|
||||
@@ -314,12 +320,12 @@ components:
|
||||
id:
|
||||
description: Route Id
|
||||
type: string
|
||||
prefix_type:
|
||||
description: Prefix type indicating if it is IPv4 or IPv6
|
||||
network_type:
|
||||
description: Network type indicating if it is IPv4 or IPv6
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- prefix_type
|
||||
- network_type
|
||||
- $ref: '#/components/schemas/RouteRequest'
|
||||
RoutePatchOperation:
|
||||
allOf:
|
||||
@@ -329,7 +335,7 @@ components:
|
||||
path:
|
||||
description: Route field to update in form /<field>
|
||||
type: string
|
||||
enum: [ "prefix","description","enabled","peer","metric","masquerade" ]
|
||||
enum: [ "network","network_id","description","enabled","peer","metric","masquerade" ]
|
||||
required:
|
||||
- path
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ const (
|
||||
RoutePatchOperationPathEnabled RoutePatchOperationPath = "enabled"
|
||||
RoutePatchOperationPathMasquerade RoutePatchOperationPath = "masquerade"
|
||||
RoutePatchOperationPathMetric RoutePatchOperationPath = "metric"
|
||||
RoutePatchOperationPathNetwork RoutePatchOperationPath = "network"
|
||||
RoutePatchOperationPathNetworkId RoutePatchOperationPath = "network_id"
|
||||
RoutePatchOperationPathPeer RoutePatchOperationPath = "peer"
|
||||
RoutePatchOperationPathPrefix RoutePatchOperationPath = "prefix"
|
||||
)
|
||||
|
||||
// Defines values for RulePatchOperationOp.
|
||||
@@ -184,14 +185,17 @@ type Route struct {
|
||||
// Route metric number. Lowest number has higher priority
|
||||
Metric int `json:"metric"`
|
||||
|
||||
// Network range in CIDR format
|
||||
Network string `json:"network"`
|
||||
|
||||
// Route network identifier, to group HA routes
|
||||
NetworkId string `json:"network_id"`
|
||||
|
||||
// Network type indicating if it is IPv4 or IPv6
|
||||
NetworkType string `json:"network_type"`
|
||||
|
||||
// Peer Identifier associated with route
|
||||
Peer string `json:"peer"`
|
||||
|
||||
// Prefix or network range in CIDR format
|
||||
Prefix string `json:"prefix"`
|
||||
|
||||
// Prefix type indicating if it is IPv4 or IPv6
|
||||
PrefixType string `json:"prefix_type"`
|
||||
}
|
||||
|
||||
// RoutePatchOperation defines model for RoutePatchOperation.
|
||||
@@ -226,11 +230,14 @@ type RouteRequest struct {
|
||||
// Route metric number. Lowest number has higher priority
|
||||
Metric int `json:"metric"`
|
||||
|
||||
// Network range in CIDR format
|
||||
Network string `json:"network"`
|
||||
|
||||
// Route network identifier, to group HA routes
|
||||
NetworkId string `json:"network_id"`
|
||||
|
||||
// Peer Identifier associated with route
|
||||
Peer string `json:"peer"`
|
||||
|
||||
// Prefix or network range in CIDR format
|
||||
Prefix string `json:"prefix"`
|
||||
}
|
||||
|
||||
// Rule defines model for Rule.
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"net/http"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Routes is the routes handler of the account
|
||||
@@ -78,13 +79,18 @@ func (h *Routes) CreateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
peerKey = peer.Key
|
||||
}
|
||||
|
||||
_, newPrefix, err := route.ParsePrefix(req.Prefix)
|
||||
_, newPrefix, err := route.ParseNetwork(req.Network)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("couldn't parse update prefix %s", req.Prefix), http.StatusBadRequest)
|
||||
http.Error(w, fmt.Sprintf("couldn't parse update prefix %s", req.Network), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
newRoute, err := h.accountManager.CreateRoute(account.Id, newPrefix.String(), peerKey, req.Description, req.Masquerade, req.Metric, req.Enabled)
|
||||
if utf8.RuneCountInString(req.NetworkId) > route.MaxNetIDChar || req.NetworkId == "" {
|
||||
http.Error(w, fmt.Sprintf("identifier should be between 1 and %d", route.MaxNetIDChar), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
newRoute, err := h.accountManager.CreateRoute(account.Id, newPrefix.String(), peerKey, req.Description, req.NetworkId, req.Masquerade, req.Metric, req.Enabled)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
@@ -123,9 +129,9 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
prefixType, newPrefix, err := route.ParsePrefix(req.Prefix)
|
||||
prefixType, newPrefix, err := route.ParseNetwork(req.Network)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("couldn't parse update prefix %s for route ID %s", req.Prefix, routeID), http.StatusBadRequest)
|
||||
http.Error(w, fmt.Sprintf("couldn't parse update prefix %s for route ID %s", req.Network, routeID), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -140,10 +146,16 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
peerKey = peer.Key
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(req.NetworkId) > route.MaxNetIDChar || req.NetworkId == "" {
|
||||
http.Error(w, fmt.Sprintf("identifier should be between 1 and %d", route.MaxNetIDChar), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
newRoute := &route.Route{
|
||||
ID: routeID,
|
||||
Prefix: newPrefix,
|
||||
PrefixType: prefixType,
|
||||
Network: newPrefix,
|
||||
NetID: req.NetworkId,
|
||||
NetworkType: prefixType,
|
||||
Masquerade: req.Masquerade,
|
||||
Peer: peerKey,
|
||||
Metric: req.Metric,
|
||||
@@ -200,14 +212,14 @@ func (h *Routes) PatchRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
for _, patch := range req {
|
||||
switch patch.Path {
|
||||
case api.RoutePatchOperationPathPrefix:
|
||||
case api.RoutePatchOperationPathNetwork:
|
||||
if patch.Op != api.RoutePatchOperationOpReplace {
|
||||
http.Error(w, fmt.Sprintf("Prefix field only accepts replace operation, got %s", patch.Op),
|
||||
http.Error(w, fmt.Sprintf("Network field only accepts replace operation, got %s", patch.Op),
|
||||
http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
operations = append(operations, server.RouteUpdateOperation{
|
||||
Type: server.UpdateRoutePrefix,
|
||||
Type: server.UpdateRouteNetwork,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.RoutePatchOperationPathDescription:
|
||||
@@ -220,6 +232,16 @@ func (h *Routes) PatchRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Type: server.UpdateRouteDescription,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.RoutePatchOperationPathNetworkId:
|
||||
if patch.Op != api.RoutePatchOperationOpReplace {
|
||||
http.Error(w, fmt.Sprintf("Network Identifier field only accepts replace operation, got %s", patch.Op),
|
||||
http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
operations = append(operations, server.RouteUpdateOperation{
|
||||
Type: server.UpdateRouteNetworkIdentifier,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.RoutePatchOperationPathPeer:
|
||||
if patch.Op != api.RoutePatchOperationOpReplace {
|
||||
http.Error(w, fmt.Sprintf("Peer field only accepts replace operation, got %s", patch.Op),
|
||||
@@ -370,10 +392,11 @@ func toRouteResponse(account *server.Account, serverRoute *route.Route) *api.Rou
|
||||
return &api.Route{
|
||||
Id: serverRoute.ID,
|
||||
Description: serverRoute.Description,
|
||||
NetworkId: serverRoute.NetID,
|
||||
Enabled: serverRoute.Enabled,
|
||||
Peer: peerIP,
|
||||
Prefix: serverRoute.Prefix.String(),
|
||||
PrefixType: serverRoute.PrefixType.String(),
|
||||
Network: serverRoute.Network.String(),
|
||||
NetworkType: serverRoute.NetworkType.String(),
|
||||
Masquerade: serverRoute.Masquerade,
|
||||
Metric: serverRoute.Metric,
|
||||
}
|
||||
|
||||
@@ -34,8 +34,9 @@ const (
|
||||
var baseExistingRoute = &route.Route{
|
||||
ID: existingRouteID,
|
||||
Description: "base route",
|
||||
Prefix: netip.MustParsePrefix("192.168.0.0/24"),
|
||||
PrefixType: route.IPv4Prefix,
|
||||
NetID: "awesomeNet",
|
||||
Network: netip.MustParsePrefix("192.168.0.0/24"),
|
||||
NetworkType: route.IPv4Network,
|
||||
Metric: 9999,
|
||||
Masquerade: false,
|
||||
Enabled: true,
|
||||
@@ -61,13 +62,14 @@ func initRoutesTestData() *Routes {
|
||||
}
|
||||
return nil, status.Errorf(codes.NotFound, "route with ID %s not found", routeID)
|
||||
},
|
||||
CreateRouteFunc: func(accountID string, prefix, peer, description string, masquerade bool, metric int, enabled bool) (*route.Route, error) {
|
||||
prefixType, p, _ := route.ParsePrefix(prefix)
|
||||
CreateRouteFunc: func(accountID string, network, peer, description, netID string, masquerade bool, metric int, enabled bool) (*route.Route, error) {
|
||||
networkType, p, _ := route.ParseNetwork(network)
|
||||
return &route.Route{
|
||||
ID: existingRouteID,
|
||||
NetID: netID,
|
||||
Peer: peer,
|
||||
Prefix: p,
|
||||
PrefixType: prefixType,
|
||||
Network: p,
|
||||
NetworkType: networkType,
|
||||
Description: description,
|
||||
Masquerade: masquerade,
|
||||
Enabled: enabled,
|
||||
@@ -95,10 +97,12 @@ func initRoutesTestData() *Routes {
|
||||
}
|
||||
for _, operation := range operations {
|
||||
switch operation.Type {
|
||||
case server.UpdateRoutePrefix:
|
||||
routeToUpdate.PrefixType, routeToUpdate.Prefix, _ = route.ParsePrefix(operation.Values[0])
|
||||
case server.UpdateRouteNetwork:
|
||||
routeToUpdate.NetworkType, routeToUpdate.Network, _ = route.ParseNetwork(operation.Values[0])
|
||||
case server.UpdateRouteDescription:
|
||||
routeToUpdate.Description = operation.Values[0]
|
||||
case server.UpdateRouteNetworkIdentifier:
|
||||
routeToUpdate.NetID = operation.Values[0]
|
||||
case server.UpdateRoutePeer:
|
||||
routeToUpdate.Peer = operation.Values[0]
|
||||
case server.UpdateRouteMetric:
|
||||
@@ -172,15 +176,16 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/16\",\"Peer\":\"%s\"}", existingPeerID))),
|
||||
[]byte(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID))),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedRoute: &api.Route{
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
Prefix: "192.168.0.0/16",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: "192.168.0.0/16",
|
||||
Peer: existingPeerID,
|
||||
PrefixType: route.IPv4PrefixString,
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
Enabled: false,
|
||||
},
|
||||
@@ -189,15 +194,23 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "POST Not Found Peer",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/16\",\"Peer\":\"%s\"}", notFoundPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", notFoundPeerID)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
name: "POST Invalid Prefix",
|
||||
name: "POST Not Invalid Network Identifier",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/routes",
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/34\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"12345678901234567890qwertyuiopqwertyuiop1\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
expectedStatus: http.StatusBadRequest,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
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)),
|
||||
expectedStatus: http.StatusBadRequest,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -205,15 +218,16 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT OK",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/16\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedRoute: &api.Route{
|
||||
Id: existingRouteID,
|
||||
Description: "Post",
|
||||
Prefix: "192.168.0.0/16",
|
||||
NetworkId: "awesomeNet",
|
||||
Network: "192.168.0.0/16",
|
||||
Peer: existingPeerID,
|
||||
PrefixType: route.IPv4PrefixString,
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: false,
|
||||
Enabled: false,
|
||||
},
|
||||
@@ -222,7 +236,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT Not Found Route",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + notFoundRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/16\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -230,15 +244,23 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PUT Not Found Peer",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/16\",\"Peer\":\"%s\"}", notFoundPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"awesomeNet\",\"Peer\":\"%s\"}", notFoundPeerID)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
name: "PUT Invalid Prefix",
|
||||
name: "PUT Invalid Network Identifier",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/routes/" + existingRouteID,
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Prefix\":\"192.168.0.0/34\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
requestBody: bytes.NewBufferString(fmt.Sprintf("{\"Description\":\"Post\",\"Network\":\"192.168.0.0/16\",\"network_id\":\"12345678901234567890qwertyuiopqwertyuiop1\",\"Peer\":\"%s\"}", existingPeerID)),
|
||||
expectedStatus: http.StatusBadRequest,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
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)),
|
||||
expectedStatus: http.StatusBadRequest,
|
||||
expectedBody: false,
|
||||
},
|
||||
@@ -252,8 +274,9 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
expectedRoute: &api.Route{
|
||||
Id: existingRouteID,
|
||||
Description: "NewDesc",
|
||||
Prefix: baseExistingRoute.Prefix.String(),
|
||||
PrefixType: route.IPv4PrefixString,
|
||||
NetworkId: "awesomeNet",
|
||||
Network: baseExistingRoute.Network.String(),
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Masquerade: baseExistingRoute.Masquerade,
|
||||
Enabled: baseExistingRoute.Enabled,
|
||||
Metric: baseExistingRoute.Metric,
|
||||
@@ -269,8 +292,9 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
expectedRoute: &api.Route{
|
||||
Id: existingRouteID,
|
||||
Description: "NewDesc",
|
||||
Prefix: baseExistingRoute.Prefix.String(),
|
||||
PrefixType: route.IPv4PrefixString,
|
||||
NetworkId: "awesomeNet",
|
||||
Network: baseExistingRoute.Network.String(),
|
||||
NetworkType: route.IPv4NetworkString,
|
||||
Peer: existingPeerID,
|
||||
Masquerade: baseExistingRoute.Masquerade,
|
||||
Enabled: baseExistingRoute.Enabled,
|
||||
@@ -289,7 +313,7 @@ func TestRoutesHandlers(t *testing.T) {
|
||||
name: "PATCH Not Found Route",
|
||||
requestType: http.MethodPatch,
|
||||
requestPath: "/api/routes/" + notFoundRouteID,
|
||||
requestBody: bytes.NewBufferString("[{\"op\":\"replace\",\"path\":\"prefix\",\"value\":[\"192.168.0.0/34\"]}]"),
|
||||
requestBody: bytes.NewBufferString("[{\"op\":\"replace\",\"path\":\"network\",\"value\":[\"192.168.0.0/34\"]}]"),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user