2024-04-23 14:42:53 +02:00
|
|
|
package routeselector
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"slices"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
|
|
"golang.org/x/exp/maps"
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
"github.com/netbirdio/netbird/client/errors"
|
2024-04-23 14:42:53 +02:00
|
|
|
route "github.com/netbirdio/netbird/route"
|
|
|
|
)
|
|
|
|
|
|
|
|
type RouteSelector struct {
|
2024-05-06 14:47:49 +02:00
|
|
|
selectedRoutes map[route.NetID]struct{}
|
2024-04-23 14:42:53 +02:00
|
|
|
selectAll bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRouteSelector() *RouteSelector {
|
|
|
|
return &RouteSelector{
|
2024-05-06 14:47:49 +02:00
|
|
|
selectedRoutes: map[route.NetID]struct{}{},
|
2024-04-23 14:42:53 +02:00
|
|
|
// default selects all routes
|
|
|
|
selectAll: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SelectRoutes updates the selected routes based on the provided route IDs.
|
2024-05-06 14:47:49 +02:00
|
|
|
func (rs *RouteSelector) SelectRoutes(routes []route.NetID, appendRoute bool, allRoutes []route.NetID) error {
|
2024-04-23 14:42:53 +02:00
|
|
|
if !appendRoute {
|
2024-05-06 14:47:49 +02:00
|
|
|
rs.selectedRoutes = map[route.NetID]struct{}{}
|
2024-04-23 14:42:53 +02:00
|
|
|
}
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
var err *multierror.Error
|
2024-04-23 14:42:53 +02:00
|
|
|
for _, route := range routes {
|
|
|
|
if !slices.Contains(allRoutes, route) {
|
2024-06-13 13:24:24 +02:00
|
|
|
err = multierror.Append(err, fmt.Errorf("route '%s' is not available", route))
|
2024-04-23 14:42:53 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
rs.selectedRoutes[route] = struct{}{}
|
|
|
|
}
|
|
|
|
rs.selectAll = false
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
return errors.FormatErrorOrNil(err)
|
2024-04-23 14:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SelectAllRoutes sets the selector to select all routes.
|
|
|
|
func (rs *RouteSelector) SelectAllRoutes() {
|
|
|
|
rs.selectAll = true
|
2024-05-06 14:47:49 +02:00
|
|
|
rs.selectedRoutes = map[route.NetID]struct{}{}
|
2024-04-23 14:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeselectRoutes removes specific routes from the selection.
|
|
|
|
// If the selector is in "select all" mode, it will transition to "select specific" mode.
|
2024-05-06 14:47:49 +02:00
|
|
|
func (rs *RouteSelector) DeselectRoutes(routes []route.NetID, allRoutes []route.NetID) error {
|
2024-04-23 14:42:53 +02:00
|
|
|
if rs.selectAll {
|
|
|
|
rs.selectAll = false
|
2024-05-06 14:47:49 +02:00
|
|
|
rs.selectedRoutes = map[route.NetID]struct{}{}
|
2024-04-23 14:42:53 +02:00
|
|
|
for _, route := range allRoutes {
|
|
|
|
rs.selectedRoutes[route] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
var err *multierror.Error
|
2024-04-23 14:42:53 +02:00
|
|
|
|
|
|
|
for _, route := range routes {
|
|
|
|
if !slices.Contains(allRoutes, route) {
|
2024-06-13 13:24:24 +02:00
|
|
|
err = multierror.Append(err, fmt.Errorf("route '%s' is not available", route))
|
2024-04-23 14:42:53 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
delete(rs.selectedRoutes, route)
|
|
|
|
}
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
return errors.FormatErrorOrNil(err)
|
2024-04-23 14:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeselectAllRoutes deselects all routes, effectively disabling route selection.
|
|
|
|
func (rs *RouteSelector) DeselectAllRoutes() {
|
|
|
|
rs.selectAll = false
|
2024-05-06 14:47:49 +02:00
|
|
|
rs.selectedRoutes = map[route.NetID]struct{}{}
|
2024-04-23 14:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// IsSelected checks if a specific route is selected.
|
2024-05-06 14:47:49 +02:00
|
|
|
func (rs *RouteSelector) IsSelected(routeID route.NetID) bool {
|
2024-04-23 14:42:53 +02:00
|
|
|
if rs.selectAll {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
_, selected := rs.selectedRoutes[routeID]
|
|
|
|
return selected
|
|
|
|
}
|
|
|
|
|
|
|
|
// FilterSelected removes unselected routes from the provided map.
|
2024-05-06 14:47:49 +02:00
|
|
|
func (rs *RouteSelector) FilterSelected(routes route.HAMap) route.HAMap {
|
2024-04-23 14:42:53 +02:00
|
|
|
if rs.selectAll {
|
|
|
|
return maps.Clone(routes)
|
|
|
|
}
|
|
|
|
|
2024-05-06 14:47:49 +02:00
|
|
|
filtered := route.HAMap{}
|
2024-04-23 14:42:53 +02:00
|
|
|
for id, rt := range routes {
|
2024-05-06 14:47:49 +02:00
|
|
|
if rs.IsSelected(id.NetID()) {
|
2024-04-23 14:42:53 +02:00
|
|
|
filtered[id] = rt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return filtered
|
|
|
|
}
|