76 lines
2.9 KiB
Go
76 lines
2.9 KiB
Go
package gateways
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/hashicorp/consul/agent/configentry"
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
)
|
|
|
|
// referenceSet stores an O(1) accessible set of ResourceReference objects.
|
|
type referenceSet = map[structs.ResourceReference]any
|
|
|
|
// gatewayRefs maps a gateway kind/name to a set of resource references.
|
|
type gatewayRefs = map[configentry.KindName][]structs.ResourceReference
|
|
|
|
// BindRoutesToGateways takes a slice of bound API gateways and a variadic number of routes.
|
|
// It iterates over the parent references for each route. These parents are gateways the
|
|
// route should be bound to. If the parent matches a bound gateway, the route is bound to the
|
|
// gateway. Otherwise, the route is unbound from the gateway if it was previously bound.
|
|
//
|
|
// The function returns a list of references to the modified BoundAPIGatewayConfigEntry objects,
|
|
// a map of resource references to errors that occurred when they were attempted to be
|
|
// bound to a gateway.
|
|
func BindRoutesToGateways(gateways []*structs.BoundAPIGatewayConfigEntry, routes ...structs.BoundRoute) ([]*structs.BoundAPIGatewayConfigEntry, map[structs.ResourceReference]error) {
|
|
modified := make([]*structs.BoundAPIGatewayConfigEntry, 0, len(gateways))
|
|
|
|
// errored stores the errors from events where a resource reference failed to bind to a gateway.
|
|
errored := make(map[structs.ResourceReference]error)
|
|
|
|
for _, route := range routes {
|
|
parentRefs, gatewayRefs := getReferences(route)
|
|
|
|
// Iterate over all BoundAPIGateway config entries and try to bind them to the route if they are a parent.
|
|
for _, gateway := range gateways {
|
|
references, routeReferencesGateway := gatewayRefs[configentry.NewKindNameForEntry(gateway)]
|
|
if routeReferencesGateway {
|
|
didUpdate, errors := gateway.UpdateRouteBinding(references, route)
|
|
if didUpdate {
|
|
modified = append(modified, gateway)
|
|
}
|
|
for ref, err := range errors {
|
|
errored[ref] = err
|
|
}
|
|
for _, ref := range references {
|
|
delete(parentRefs, ref)
|
|
}
|
|
} else {
|
|
if gateway.UnbindRoute(route) {
|
|
modified = append(modified, gateway)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add all references that aren't bound at this point to the error set.
|
|
for reference := range parentRefs {
|
|
errored[reference] = errors.New("invalid reference to missing parent")
|
|
}
|
|
}
|
|
|
|
return modified, errored
|
|
}
|
|
|
|
// getReferences returns a set of all the resource references for a given route as well as
|
|
// a map of gateway kind/name to a list of resource references for that gateway.
|
|
func getReferences(route structs.BoundRoute) (referenceSet, gatewayRefs) {
|
|
parentRefs := make(referenceSet)
|
|
gatewayRefs := make(gatewayRefs)
|
|
for _, ref := range route.GetParents() {
|
|
parentRefs[ref] = struct{}{}
|
|
kindName := configentry.NewKindName(structs.BoundAPIGateway, ref.Name, &ref.EnterpriseMeta)
|
|
gatewayRefs[kindName] = append(gatewayRefs[kindName], ref)
|
|
}
|
|
|
|
return parentRefs, gatewayRefs
|
|
}
|