open-consul/agent/consul/gateways/bind_test.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,
}
}