306 lines
12 KiB
Go
306 lines
12 KiB
Go
|
package gateways
|
||
|
|
||
|
import (
|
||
|
"testing"
|
||
|
|
||
|
"github.com/hashicorp/consul/agent/structs"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
func TestBindRoutesToGateways(t *testing.T) {
|
||
|
type testCase struct {
|
||
|
gateways []*structs.BoundAPIGatewayConfigEntry
|
||
|
routes []structs.BoundRoute
|
||
|
expectedBoundAPIGateways []*structs.BoundAPIGatewayConfigEntry
|
||
|
expectedReferenceErrors map[structs.ResourceReference]error
|
||
|
}
|
||
|
|
||
|
cases := map[string]testCase{
|
||
|
"TCP Route binds to gateway": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route unbinds from gateway": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route binds to multiple gateways": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
makeRef(structs.APIGateway, "Other Test Bound API Gateway", "Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route binds to gateway with multiple listeners": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route binds to all listeners on a gateway": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", ""),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route binds to gateway with multiple listeners, one of which is already bound": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Other Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route binds to a listener on multiple gateways": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
makeRef(structs.APIGateway, "Other Test Bound API Gateway", "Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Route swaps from one listener to another on a gateway": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Other Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
"TCP Routes bind to each gateway": {
|
||
|
gateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{}),
|
||
|
}),
|
||
|
},
|
||
|
routes: []structs.BoundRoute{
|
||
|
makeRoute(structs.TCPRoute, "Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Test Bound API Gateway", "Test Listener"),
|
||
|
}),
|
||
|
makeRoute(structs.TCPRoute, "Other Test TCP Route", []structs.ResourceReference{
|
||
|
makeRef(structs.APIGateway, "Other Test Bound API Gateway", "Other Test Listener"),
|
||
|
}),
|
||
|
},
|
||
|
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||
|
makeGateway("Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
makeGateway("Other Test Bound API Gateway", []structs.BoundAPIGatewayListener{
|
||
|
makeListener("Other Test Listener", []structs.ResourceReference{
|
||
|
makeRef(structs.TCPRoute, "Other Test TCP Route", ""),
|
||
|
}),
|
||
|
}),
|
||
|
},
|
||
|
expectedReferenceErrors: map[structs.ResourceReference]error{},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for name, tc := range cases {
|
||
|
t.Run(name, func(t *testing.T) {
|
||
|
actualBoundAPIGateways, referenceErrors := BindRoutesToGateways(tc.gateways, tc.routes...)
|
||
|
|
||
|
require.Equal(t, tc.expectedBoundAPIGateways, actualBoundAPIGateways)
|
||
|
require.Equal(t, tc.expectedReferenceErrors, referenceErrors)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeRef(kind, name, sectionName string) structs.ResourceReference {
|
||
|
return structs.ResourceReference{
|
||
|
Kind: kind,
|
||
|
Name: name,
|
||
|
SectionName: sectionName,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeRoute(kind, name string, parents []structs.ResourceReference) structs.BoundRoute {
|
||
|
switch kind {
|
||
|
case structs.TCPRoute:
|
||
|
return &structs.TCPRouteConfigEntry{
|
||
|
Kind: structs.TCPRoute,
|
||
|
Name: name,
|
||
|
Parents: parents,
|
||
|
}
|
||
|
default:
|
||
|
panic("unknown route kind")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeListener(name string, routes []structs.ResourceReference) structs.BoundAPIGatewayListener {
|
||
|
return structs.BoundAPIGatewayListener{
|
||
|
Name: name,
|
||
|
Routes: routes,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func makeGateway(name string, listeners []structs.BoundAPIGatewayListener) *structs.BoundAPIGatewayConfigEntry {
|
||
|
return &structs.BoundAPIGatewayConfigEntry{
|
||
|
Kind: structs.BoundAPIGateway,
|
||
|
Name: name,
|
||
|
Listeners: listeners,
|
||
|
}
|
||
|
}
|