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:
Maycon Santos
2022-08-22 14:10:24 +02:00
committed by GitHub
parent 762a26dcea
commit 09312b3e6d
12 changed files with 405 additions and 216 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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,
}

View File

@@ -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,
},