[NET-6765] Audit the routes controller and add missing tenancy tests (#20016)

- moved resources to different tenancies.
This commit is contained in:
Kumar Kavish 2023-12-28 16:00:18 +05:30 committed by GitHub
parent 2f335113f8
commit 9c8e9cebaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 208 additions and 155 deletions

View File

@ -6,6 +6,7 @@ package routes
import ( import (
"context" "context"
"fmt" "fmt"
"sort"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -32,6 +33,14 @@ type controllerSuite struct {
client *rtest.Client client *rtest.Client
rt controller.Runtime rt controller.Runtime
tenancies []*pbresource.Tenancy tenancies []*pbresource.Tenancy
refs *testResourceRef
}
type testResourceRef struct {
apiServiceRef *pbresource.Reference
fooServiceRef *pbresource.Reference
barServiceRef *pbresource.Reference
} }
func (suite *controllerSuite) SetupTest() { func (suite *controllerSuite) SetupTest() {
@ -55,25 +64,19 @@ func (suite *controllerSuite) TestController() {
mgr.SetRaftLeader(true) mgr.SetRaftLeader(true)
go mgr.Run(suite.ctx) go mgr.Run(suite.ctx)
suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { suite.runTestCaseWithTenancies(func(refs *testResourceRef) {
backendName := func(name, port string) string { backendName := func(name, port string, tenancy *pbresource.Tenancy) string {
return fmt.Sprintf("catalog.v2beta1.Service/%s.local.%s/%s?port=%s", tenancy.Partition, tenancy.Namespace, name, port) return fmt.Sprintf("catalog.v2beta1.Service/%s.local.%s/%s?port=%s", tenancy.Partition, tenancy.Namespace, name, port)
} }
var ( var (
apiServiceRef = rtest.Resource(pbcatalog.ServiceType, "api"). apiServiceRef = refs.apiServiceRef
WithTenancy(tenancy). fooServiceRef = refs.fooServiceRef
Reference("") barServiceRef = refs.barServiceRef
fooServiceRef = rtest.Resource(pbcatalog.ServiceType, "foo").
WithTenancy(tenancy).
Reference("")
barServiceRef = rtest.Resource(pbcatalog.ServiceType, "bar").
WithTenancy(tenancy).
Reference("")
computedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "api"). computedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "api").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
ID() ID()
) )
@ -92,7 +95,7 @@ func (suite *controllerSuite) TestController() {
} }
_ = rtest.Resource(pbcatalog.ServiceType, "api"). _ = rtest.Resource(pbcatalog.ServiceType, "api").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), apiServiceData). WithData(suite.T(), apiServiceData).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
@ -110,7 +113,7 @@ func (suite *controllerSuite) TestController() {
Tcp: &pbmesh.ComputedTCPRoute{ Tcp: &pbmesh.ComputedTCPRoute{
Rules: []*pbmesh.ComputedTCPRouteRule{{ Rules: []*pbmesh.ComputedTCPRouteRule{{
BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{
BackendTarget: backendName("api", "tcp"), BackendTarget: backendName("api", "tcp", apiServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -118,7 +121,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "tcp"), ParentRef: newParentRef(apiServiceRef, "tcp"),
Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "tcp"): { backendName("api", "tcp", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "tcp", ""), BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
@ -148,7 +151,7 @@ func (suite *controllerSuite) TestController() {
} }
_ = rtest.Resource(pbcatalog.ServiceType, "api"). _ = rtest.Resource(pbcatalog.ServiceType, "api").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), apiServiceData). WithData(suite.T(), apiServiceData).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
@ -167,7 +170,7 @@ func (suite *controllerSuite) TestController() {
} }
fooService := rtest.Resource(pbcatalog.ServiceType, "foo"). fooService := rtest.Resource(pbcatalog.ServiceType, "foo").
WithTenancy(tenancy). WithTenancy(fooServiceRef.Tenancy).
WithData(suite.T(), fooServiceData). WithData(suite.T(), fooServiceData).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
@ -183,7 +186,7 @@ func (suite *controllerSuite) TestController() {
Tcp: &pbmesh.ComputedTCPRoute{ Tcp: &pbmesh.ComputedTCPRoute{
Rules: []*pbmesh.ComputedTCPRouteRule{{ Rules: []*pbmesh.ComputedTCPRouteRule{{
BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{
BackendTarget: backendName("api", "tcp"), BackendTarget: backendName("api", "tcp", apiServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -191,7 +194,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "tcp"), ParentRef: newParentRef(apiServiceRef, "tcp"),
Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "tcp"): { backendName("api", "tcp", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "tcp", ""), BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
@ -211,7 +214,7 @@ func (suite *controllerSuite) TestController() {
}, },
}}, }},
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("api", "http"), BackendTarget: backendName("api", "http", apiServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -219,7 +222,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http"), ParentRef: newParentRef(apiServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "http"): { backendName("api", "http", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "http", ""), BackendRef: newBackendRef(apiServiceRef, "http", ""),
@ -239,7 +242,7 @@ func (suite *controllerSuite) TestController() {
}, },
}}, }},
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("api", "http2"), BackendTarget: backendName("api", "http2", apiServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -247,7 +250,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http2"), ParentRef: newParentRef(apiServiceRef, "http2"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "http2"): { backendName("api", "http2", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "http2", ""), BackendRef: newBackendRef(apiServiceRef, "http2", ""),
@ -262,7 +265,7 @@ func (suite *controllerSuite) TestController() {
Rules: []*pbmesh.ComputedGRPCRouteRule{{ Rules: []*pbmesh.ComputedGRPCRouteRule{{
Matches: []*pbmesh.GRPCRouteMatch{{}}, Matches: []*pbmesh.GRPCRouteMatch{{}},
BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{
BackendTarget: backendName("api", "grpc"), BackendTarget: backendName("api", "grpc", apiServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -270,7 +273,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "grpc"), ParentRef: newParentRef(apiServiceRef, "grpc"),
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "grpc"): { backendName("api", "grpc", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "grpc", ""), BackendRef: newBackendRef(apiServiceRef, "grpc", ""),
@ -288,7 +291,7 @@ func (suite *controllerSuite) TestController() {
tcpRoute1 := &pbmesh.TCPRoute{ tcpRoute1 := &pbmesh.TCPRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "tcp"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "tcp"),
}, },
Rules: []*pbmesh.TCPRouteRule{{ Rules: []*pbmesh.TCPRouteRule{{
BackendRefs: []*pbmesh.TCPBackendRef{{ BackendRefs: []*pbmesh.TCPBackendRef{{
@ -297,15 +300,15 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
tcpRoute1ID := rtest.Resource(pbmesh.TCPRouteType, "api-tcp-route1"). tcpRoute1ID := rtest.Resource(pbmesh.TCPRouteType, "api-tcp-route1").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), tcpRoute1). WithData(suite.T(), tcpRoute1).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
httpRoute1 := &pbmesh.HTTPRoute{ httpRoute1 := &pbmesh.HTTPRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http"),
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http2"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http2"),
}, },
Rules: []*pbmesh.HTTPRouteRule{{ Rules: []*pbmesh.HTTPRouteRule{{
BackendRefs: []*pbmesh.HTTPBackendRef{{ BackendRefs: []*pbmesh.HTTPBackendRef{{
@ -314,14 +317,14 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
httpRoute1ID := rtest.Resource(pbmesh.HTTPRouteType, "api-http-route1"). httpRoute1ID := rtest.Resource(pbmesh.HTTPRouteType, "api-http-route1").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), httpRoute1). WithData(suite.T(), httpRoute1).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
grpcRoute1 := &pbmesh.GRPCRoute{ grpcRoute1 := &pbmesh.GRPCRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "grpc"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "grpc"),
}, },
Rules: []*pbmesh.GRPCRouteRule{{ Rules: []*pbmesh.GRPCRouteRule{{
BackendRefs: []*pbmesh.GRPCBackendRef{{ BackendRefs: []*pbmesh.GRPCBackendRef{{
@ -330,27 +333,32 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
grpcRoute1ID := rtest.Resource(pbmesh.GRPCRouteType, "api-grpc-route1"). grpcRoute1ID := rtest.Resource(pbmesh.GRPCRouteType, "api-grpc-route1").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), grpcRoute1). WithData(suite.T(), grpcRoute1).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
testutil.RunStep(suite.T(), "one of each", func(t *testing.T) { testutil.RunStep(suite.T(), "one of each", func(t *testing.T) {
expect := &pbmesh.ComputedRoutes{ boundRefs := []*pbresource.Reference{
BoundReferences: []*pbresource.Reference{
apiServiceRef,
fooServiceRef, fooServiceRef,
apiServiceRef,
resource.Reference(grpcRoute1ID, ""), resource.Reference(grpcRoute1ID, ""),
resource.Reference(httpRoute1ID, ""), resource.Reference(httpRoute1ID, ""),
resource.Reference(tcpRoute1ID, ""), resource.Reference(tcpRoute1ID, ""),
}, }
sort.Slice(boundRefs, func(i, j int) bool {
return resource.LessReference(boundRefs[i], boundRefs[j])
})
expect := &pbmesh.ComputedRoutes{
BoundReferences: boundRefs,
PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{
"tcp": { "tcp": {
Config: &pbmesh.ComputedPortRoutes_Tcp{ Config: &pbmesh.ComputedPortRoutes_Tcp{
Tcp: &pbmesh.ComputedTCPRoute{ Tcp: &pbmesh.ComputedTCPRoute{
Rules: []*pbmesh.ComputedTCPRouteRule{{ Rules: []*pbmesh.ComputedTCPRouteRule{{
BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{
BackendTarget: backendName("foo", "tcp"), BackendTarget: backendName("foo", "tcp", fooServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -358,7 +366,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "tcp"), ParentRef: newParentRef(apiServiceRef, "tcp"),
Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "tcp"): { backendName("foo", "tcp", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "tcp", ""), BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
@ -373,7 +381,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http"), BackendTarget: backendName("foo", "http", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -388,7 +396,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http"), ParentRef: newParentRef(apiServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http"): { backendName("foo", "http", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http", ""), BackendRef: newBackendRef(fooServiceRef, "http", ""),
@ -403,7 +411,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: []*pbmesh.GRPCRouteMatch{{}}, Matches: []*pbmesh.GRPCRouteMatch{{}},
BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{
BackendTarget: backendName("foo", "grpc"), BackendTarget: backendName("foo", "grpc", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -418,7 +426,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "grpc"), ParentRef: newParentRef(apiServiceRef, "grpc"),
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "grpc"): { backendName("foo", "grpc", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "grpc", ""), BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
@ -433,7 +441,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http2"), BackendTarget: backendName("foo", "http2", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -448,7 +456,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http2"), ParentRef: newParentRef(apiServiceRef, "http2"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http2"): { backendName("foo", "http2", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http2", ""), BackendRef: newBackendRef(fooServiceRef, "http2", ""),
@ -470,7 +478,7 @@ func (suite *controllerSuite) TestController() {
tcpRoute2 := &pbmesh.TCPRoute{ tcpRoute2 := &pbmesh.TCPRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "tcp"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "tcp"),
}, },
Rules: []*pbmesh.TCPRouteRule{{ Rules: []*pbmesh.TCPRouteRule{{
BackendRefs: []*pbmesh.TCPBackendRef{{ BackendRefs: []*pbmesh.TCPBackendRef{{
@ -479,15 +487,15 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
tcpRoute2ID := rtest.Resource(pbmesh.TCPRouteType, "api-tcp-route2"). tcpRoute2ID := rtest.Resource(pbmesh.TCPRouteType, "api-tcp-route2").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), tcpRoute2). WithData(suite.T(), tcpRoute2).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
httpRoute2 := &pbmesh.HTTPRoute{ httpRoute2 := &pbmesh.HTTPRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http"),
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http2"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http2"),
}, },
Rules: []*pbmesh.HTTPRouteRule{{ Rules: []*pbmesh.HTTPRouteRule{{
Matches: []*pbmesh.HTTPRouteMatch{{ Matches: []*pbmesh.HTTPRouteMatch{{
@ -502,14 +510,14 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
httpRoute2ID := rtest.Resource(pbmesh.HTTPRouteType, "api-http-route2"). httpRoute2ID := rtest.Resource(pbmesh.HTTPRouteType, "api-http-route2").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), httpRoute2). WithData(suite.T(), httpRoute2).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
grpcRoute2 := &pbmesh.GRPCRoute{ grpcRoute2 := &pbmesh.GRPCRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "grpc"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "grpc"),
}, },
Rules: []*pbmesh.GRPCRouteRule{{ Rules: []*pbmesh.GRPCRouteRule{{
Matches: []*pbmesh.GRPCRouteMatch{{ Matches: []*pbmesh.GRPCRouteMatch{{
@ -525,23 +533,28 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
grpcRoute2ID := rtest.Resource(pbmesh.GRPCRouteType, "api-grpc-route2"). grpcRoute2ID := rtest.Resource(pbmesh.GRPCRouteType, "api-grpc-route2").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), grpcRoute2). WithData(suite.T(), grpcRoute2).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
testutil.RunStep(suite.T(), "one good one bad route", func(t *testing.T) { testutil.RunStep(suite.T(), "one good one bad route", func(t *testing.T) {
expect := &pbmesh.ComputedRoutes{ boundRefs := []*pbresource.Reference{
BoundReferences: []*pbresource.Reference{
apiServiceRef,
fooServiceRef, fooServiceRef,
apiServiceRef,
resource.Reference(grpcRoute1ID, ""), resource.Reference(grpcRoute1ID, ""),
resource.Reference(grpcRoute2ID, ""), resource.Reference(grpcRoute2ID, ""),
resource.Reference(httpRoute1ID, ""), resource.Reference(httpRoute1ID, ""),
resource.Reference(httpRoute2ID, ""), resource.Reference(httpRoute2ID, ""),
resource.Reference(tcpRoute1ID, ""), resource.Reference(tcpRoute1ID, ""),
resource.Reference(tcpRoute2ID, ""), resource.Reference(tcpRoute2ID, ""),
}, }
sort.Slice(boundRefs, func(i, j int) bool {
return resource.LessReference(boundRefs[i], boundRefs[j])
})
expect := &pbmesh.ComputedRoutes{
BoundReferences: boundRefs,
PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{
"tcp": { "tcp": {
Config: &pbmesh.ComputedPortRoutes_Tcp{ Config: &pbmesh.ComputedPortRoutes_Tcp{
@ -549,7 +562,7 @@ func (suite *controllerSuite) TestController() {
Rules: []*pbmesh.ComputedTCPRouteRule{ Rules: []*pbmesh.ComputedTCPRouteRule{
{ {
BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{
BackendTarget: backendName("foo", "tcp"), BackendTarget: backendName("foo", "tcp", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -563,7 +576,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "tcp"), ParentRef: newParentRef(apiServiceRef, "tcp"),
Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "tcp"): { backendName("foo", "tcp", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "tcp", ""), BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
@ -589,7 +602,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http"), BackendTarget: backendName("foo", "http", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -604,7 +617,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http"), ParentRef: newParentRef(apiServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http"): { backendName("foo", "http", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http", ""), BackendRef: newBackendRef(fooServiceRef, "http", ""),
@ -619,7 +632,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: []*pbmesh.GRPCRouteMatch{{}}, Matches: []*pbmesh.GRPCRouteMatch{{}},
BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{
BackendTarget: backendName("foo", "grpc"), BackendTarget: backendName("foo", "grpc", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -646,7 +659,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "grpc"), ParentRef: newParentRef(apiServiceRef, "grpc"),
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "grpc"): { backendName("foo", "grpc", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "grpc", ""), BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
@ -672,7 +685,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http2"), BackendTarget: backendName("foo", "http2", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -687,7 +700,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http2"), ParentRef: newParentRef(apiServiceRef, "http2"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http2"): { backendName("foo", "http2", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http2", ""), BackendRef: newBackendRef(fooServiceRef, "http2", ""),
@ -705,11 +718,11 @@ func (suite *controllerSuite) TestController() {
suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK) suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK)
suite.client.WaitForStatusCondition(t, tcpRoute2ID, StatusKey, suite.client.WaitForStatusCondition(t, tcpRoute2ID, StatusKey,
ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar", tenancy))) ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar", barServiceRef.Tenancy)))
suite.client.WaitForStatusCondition(t, httpRoute2ID, StatusKey, suite.client.WaitForStatusCondition(t, httpRoute2ID, StatusKey,
ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar", tenancy))) ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar", barServiceRef.Tenancy)))
suite.client.WaitForStatusCondition(t, grpcRoute2ID, StatusKey, suite.client.WaitForStatusCondition(t, grpcRoute2ID, StatusKey,
ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar", tenancy))) ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar", barServiceRef.Tenancy)))
}) })
// Update the route2 routes to point to a real service, but overlap in // Update the route2 routes to point to a real service, but overlap in
@ -723,7 +736,7 @@ func (suite *controllerSuite) TestController() {
tcpRoute2 = &pbmesh.TCPRoute{ tcpRoute2 = &pbmesh.TCPRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http"),
}, },
Rules: []*pbmesh.TCPRouteRule{{ Rules: []*pbmesh.TCPRouteRule{{
BackendRefs: []*pbmesh.TCPBackendRef{{ BackendRefs: []*pbmesh.TCPBackendRef{{
@ -732,13 +745,13 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
rtest.ResourceID(tcpRoute2ID). rtest.ResourceID(tcpRoute2ID).
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), tcpRoute2). WithData(suite.T(), tcpRoute2).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
httpRoute2 = &pbmesh.HTTPRoute{ httpRoute2 = &pbmesh.HTTPRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "grpc"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "grpc"),
}, },
Rules: []*pbmesh.HTTPRouteRule{{ Rules: []*pbmesh.HTTPRouteRule{{
Matches: []*pbmesh.HTTPRouteMatch{{ Matches: []*pbmesh.HTTPRouteMatch{{
@ -753,13 +766,13 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
rtest.ResourceID(httpRoute2ID). rtest.ResourceID(httpRoute2ID).
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), httpRoute2). WithData(suite.T(), httpRoute2).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
grpcRoute2 = &pbmesh.GRPCRoute{ grpcRoute2 = &pbmesh.GRPCRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "tcp"), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "tcp"),
}, },
Rules: []*pbmesh.GRPCRouteRule{{ Rules: []*pbmesh.GRPCRouteRule{{
Matches: []*pbmesh.GRPCRouteMatch{{ Matches: []*pbmesh.GRPCRouteMatch{{
@ -775,13 +788,12 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
rtest.ResourceID(grpcRoute2ID). rtest.ResourceID(grpcRoute2ID).
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), grpcRoute2). WithData(suite.T(), grpcRoute2).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
testutil.RunStep(suite.T(), "overlapping xRoutes generate conflicts", func(t *testing.T) { testutil.RunStep(suite.T(), "overlapping xRoutes generate conflicts", func(t *testing.T) {
expect := &pbmesh.ComputedRoutes{ boundRefs := []*pbresource.Reference{
BoundReferences: []*pbresource.Reference{
apiServiceRef, apiServiceRef,
fooServiceRef, fooServiceRef,
resource.Reference(grpcRoute1ID, ""), resource.Reference(grpcRoute1ID, ""),
@ -790,14 +802,20 @@ func (suite *controllerSuite) TestController() {
resource.Reference(httpRoute2ID, ""), resource.Reference(httpRoute2ID, ""),
resource.Reference(tcpRoute1ID, ""), resource.Reference(tcpRoute1ID, ""),
resource.Reference(tcpRoute2ID, ""), resource.Reference(tcpRoute2ID, ""),
}, }
sort.Slice(boundRefs, func(i, j int) bool {
return resource.LessReference(boundRefs[i], boundRefs[j])
})
expect := &pbmesh.ComputedRoutes{
BoundReferences: boundRefs,
PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{
"tcp": { "tcp": {
Config: &pbmesh.ComputedPortRoutes_Tcp{ Config: &pbmesh.ComputedPortRoutes_Tcp{
Tcp: &pbmesh.ComputedTCPRoute{ Tcp: &pbmesh.ComputedTCPRoute{
Rules: []*pbmesh.ComputedTCPRouteRule{{ Rules: []*pbmesh.ComputedTCPRouteRule{{
BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{
BackendTarget: backendName("foo", "tcp"), BackendTarget: backendName("foo", "tcp", fooServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -805,7 +823,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "tcp"), ParentRef: newParentRef(apiServiceRef, "tcp"),
Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "tcp"): { backendName("foo", "tcp", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "tcp", ""), BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
@ -820,7 +838,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http"), BackendTarget: backendName("foo", "http", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -835,7 +853,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http"), ParentRef: newParentRef(apiServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http"): { backendName("foo", "http", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http", ""), BackendRef: newBackendRef(fooServiceRef, "http", ""),
@ -850,7 +868,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: []*pbmesh.GRPCRouteMatch{{}}, Matches: []*pbmesh.GRPCRouteMatch{{}},
BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{
BackendTarget: backendName("foo", "grpc"), BackendTarget: backendName("foo", "grpc", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -865,7 +883,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "grpc"), ParentRef: newParentRef(apiServiceRef, "grpc"),
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "grpc"): { backendName("foo", "grpc", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "grpc", ""), BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
@ -880,7 +898,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http2"), BackendTarget: backendName("foo", "http2", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -895,7 +913,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http2"), ParentRef: newParentRef(apiServiceRef, "http2"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http2"): { backendName("foo", "http2", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http2", ""), BackendRef: newBackendRef(fooServiceRef, "http2", ""),
@ -913,11 +931,11 @@ func (suite *controllerSuite) TestController() {
suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK) suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK)
suite.client.WaitForStatusCondition(t, tcpRoute2ID, StatusKey, suite.client.WaitForStatusCondition(t, tcpRoute2ID, StatusKey,
ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http", pbmesh.HTTPRouteType)) ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http", pbmesh.HTTPRouteType))
suite.client.WaitForStatusCondition(t, httpRoute2ID, StatusKey, suite.client.WaitForStatusCondition(t, httpRoute2ID, StatusKey,
ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "grpc", pbmesh.GRPCRouteType)) ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "grpc", pbmesh.GRPCRouteType))
suite.client.WaitForStatusCondition(t, grpcRoute2ID, StatusKey, suite.client.WaitForStatusCondition(t, grpcRoute2ID, StatusKey,
ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "tcp", pbmesh.TCPRouteType)) ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "tcp", pbmesh.TCPRouteType))
}) })
// - Delete the bad routes // - Delete the bad routes
@ -938,7 +956,7 @@ func (suite *controllerSuite) TestController() {
// Re-create with newarly the same data (wildcard port now) with a newer name. // Re-create with newarly the same data (wildcard port now) with a newer name.
grpcRoute1 = &pbmesh.GRPCRoute{ grpcRoute1 = &pbmesh.GRPCRoute{
ParentRefs: []*pbmesh.ParentReference{ ParentRefs: []*pbmesh.ParentReference{
newParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), ""), newParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), ""),
}, },
Rules: []*pbmesh.GRPCRouteRule{{ Rules: []*pbmesh.GRPCRouteRule{{
BackendRefs: []*pbmesh.GRPCBackendRef{{ BackendRefs: []*pbmesh.GRPCBackendRef{{
@ -947,27 +965,32 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
grpcRoute1ID = rtest.Resource(pbmesh.GRPCRouteType, "zzz-bad-route"). grpcRoute1ID = rtest.Resource(pbmesh.GRPCRouteType, "zzz-bad-route").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), grpcRoute1). WithData(suite.T(), grpcRoute1).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
testutil.RunStep(suite.T(), "overlapping xRoutes due to port wildcarding", func(t *testing.T) { testutil.RunStep(suite.T(), "overlapping xRoutes due to port wildcarding", func(t *testing.T) {
expect := &pbmesh.ComputedRoutes{ boundRefs := []*pbresource.Reference{
BoundReferences: []*pbresource.Reference{
apiServiceRef, apiServiceRef,
fooServiceRef, fooServiceRef,
resource.Reference(grpcRoute1ID, ""), resource.Reference(grpcRoute1ID, ""),
resource.Reference(httpRoute1ID, ""), resource.Reference(httpRoute1ID, ""),
resource.Reference(tcpRoute1ID, ""), resource.Reference(tcpRoute1ID, ""),
}, }
sort.Slice(boundRefs, func(i, j int) bool {
return resource.LessReference(boundRefs[i], boundRefs[j])
})
expect := &pbmesh.ComputedRoutes{
BoundReferences: boundRefs,
PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{
"tcp": { "tcp": {
Config: &pbmesh.ComputedPortRoutes_Tcp{ Config: &pbmesh.ComputedPortRoutes_Tcp{
Tcp: &pbmesh.ComputedTCPRoute{ Tcp: &pbmesh.ComputedTCPRoute{
Rules: []*pbmesh.ComputedTCPRouteRule{{ Rules: []*pbmesh.ComputedTCPRouteRule{{
BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ BackendRefs: []*pbmesh.ComputedTCPBackendRef{{
BackendTarget: backendName("foo", "tcp"), BackendTarget: backendName("foo", "tcp", fooServiceRef.Tenancy),
}}, }},
}}, }},
}, },
@ -975,7 +998,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "tcp"), ParentRef: newParentRef(apiServiceRef, "tcp"),
Protocol: pbcatalog.Protocol_PROTOCOL_TCP, Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "tcp"): { backendName("foo", "tcp", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "tcp", ""), BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
@ -990,7 +1013,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http"), BackendTarget: backendName("foo", "http", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -1005,7 +1028,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http"), ParentRef: newParentRef(apiServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http"): { backendName("foo", "http", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http", ""), BackendRef: newBackendRef(fooServiceRef, "http", ""),
@ -1020,7 +1043,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: []*pbmesh.GRPCRouteMatch{{}}, Matches: []*pbmesh.GRPCRouteMatch{{}},
BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{
BackendTarget: backendName("foo", "grpc"), BackendTarget: backendName("foo", "grpc", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -1035,7 +1058,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "grpc"), ParentRef: newParentRef(apiServiceRef, "grpc"),
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "grpc"): { backendName("foo", "grpc", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "grpc", ""), BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
@ -1050,7 +1073,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("foo", "http2"), BackendTarget: backendName("foo", "http2", fooServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -1065,7 +1088,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(apiServiceRef, "http2"), ParentRef: newParentRef(apiServiceRef, "http2"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("foo", "http2"): { backendName("foo", "http2", fooServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(fooServiceRef, "http2", ""), BackendRef: newBackendRef(fooServiceRef, "http2", ""),
@ -1077,9 +1100,9 @@ func (suite *controllerSuite) TestController() {
} }
suite.client.WaitForStatusConditions(t, grpcRoute1ID, StatusKey, suite.client.WaitForStatusConditions(t, grpcRoute1ID, StatusKey,
ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http", pbmesh.HTTPRouteType), ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http", pbmesh.HTTPRouteType),
ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "http2", pbmesh.HTTPRouteType), ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "http2", pbmesh.HTTPRouteType),
ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", tenancy), "tcp", pbmesh.TCPRouteType)) ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy), "tcp", pbmesh.TCPRouteType))
lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, "" /*no change*/, expect) lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, "" /*no change*/, expect)
@ -1103,7 +1126,7 @@ func (suite *controllerSuite) TestController() {
} }
apiService := rtest.Resource(pbcatalog.ServiceType, "api"). apiService := rtest.Resource(pbcatalog.ServiceType, "api").
WithTenancy(tenancy). WithTenancy(apiServiceRef.Tenancy).
WithData(suite.T(), apiServiceData). WithData(suite.T(), apiServiceData).
Write(suite.T(), suite.client) Write(suite.T(), suite.client)
@ -1111,20 +1134,20 @@ func (suite *controllerSuite) TestController() {
suite.client.WaitForDeletion(t, computedRoutesID) suite.client.WaitForDeletion(t, computedRoutesID)
suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey, suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey,
ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api", tenancy))) ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy)))
suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey,
ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api", tenancy))) ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy)))
suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey,
ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api", tenancy))) ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api", apiServiceRef.Tenancy)))
}) })
// Get down to just 2 ports for all relevant services. // Get down to just 2 ports for all relevant services.
for _, name := range []string{"foo", "bar", "api"} { for _, ref := range []*pbresource.Reference{apiServiceRef, fooServiceRef, barServiceRef} {
_ = rtest.Resource(pbcatalog.ServiceType, name). _ = rtest.Resource(pbcatalog.ServiceType, ref.Name).
WithTenancy(tenancy). WithTenancy(ref.Tenancy).
WithData(suite.T(), &pbcatalog.Service{ WithData(suite.T(), &pbcatalog.Service{
Workloads: &pbcatalog.WorkloadSelector{ Workloads: &pbcatalog.WorkloadSelector{
Prefixes: []string{name + "-"}, Prefixes: []string{ref.Name + "-"},
}, },
Ports: []*pbcatalog.ServicePort{ Ports: []*pbcatalog.ServicePort{
{TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH},
@ -1146,7 +1169,7 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
httpRoute1ID = rtest.Resource(pbmesh.HTTPRouteType, "route1"). httpRoute1ID = rtest.Resource(pbmesh.HTTPRouteType, "route1").
WithTenancy(tenancy). WithTenancy(fooServiceRef.Tenancy).
WithData(suite.T(), httpRoute1). WithData(suite.T(), httpRoute1).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
@ -1156,20 +1179,37 @@ func (suite *controllerSuite) TestController() {
barLastVersion string barLastVersion string
fooComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "foo"). fooComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "foo").
WithTenancy(tenancy). WithTenancy(fooServiceRef.Tenancy).
ID() ID()
barComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "bar"). barComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "bar").
WithTenancy(tenancy). WithTenancy(barServiceRef.Tenancy).
ID() ID()
) )
testutil.RunStep(suite.T(), "create a route linked to two parents", func(t *testing.T) { testutil.RunStep(suite.T(), "create a route linked to two parents", func(t *testing.T) {
expectFoo := &pbmesh.ComputedRoutes{ boundRefsFoo := []*pbresource.Reference{
BoundReferences: []*pbresource.Reference{
apiServiceRef, apiServiceRef,
fooServiceRef, fooServiceRef,
resource.Reference(httpRoute1ID, ""), resource.Reference(httpRoute1ID, ""),
}, }
sort.Slice(boundRefsFoo, func(i, j int) bool {
return resource.LessReference(boundRefsFoo[i], boundRefsFoo[j])
})
boundRefsBar := []*pbresource.Reference{
apiServiceRef,
barServiceRef,
resource.Reference(httpRoute1ID, ""),
}
sort.Slice(boundRefsFoo, func(i, j int) bool {
return resource.LessReference(boundRefsFoo[i], boundRefsFoo[j])
})
sort.Slice(boundRefsBar, func(i, j int) bool {
return resource.LessReference(boundRefsBar[i], boundRefsBar[j])
})
expectFoo := &pbmesh.ComputedRoutes{
BoundReferences: boundRefsFoo,
PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{
"http": { "http": {
Config: &pbmesh.ComputedPortRoutes_Http{ Config: &pbmesh.ComputedPortRoutes_Http{
@ -1178,7 +1218,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("api", "http"), BackendTarget: backendName("api", "http", apiServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -1193,7 +1233,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(fooServiceRef, "http"), ParentRef: newParentRef(fooServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "http"): { backendName("api", "http", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "http", ""), BackendRef: newBackendRef(apiServiceRef, "http", ""),
@ -1204,11 +1244,7 @@ func (suite *controllerSuite) TestController() {
}, },
} }
expectBar := &pbmesh.ComputedRoutes{ expectBar := &pbmesh.ComputedRoutes{
BoundReferences: []*pbresource.Reference{ BoundReferences: boundRefsBar,
apiServiceRef,
barServiceRef,
resource.Reference(httpRoute1ID, ""),
},
PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{
"http": { "http": {
Config: &pbmesh.ComputedPortRoutes_Http{ Config: &pbmesh.ComputedPortRoutes_Http{
@ -1217,7 +1253,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("api", "http"), BackendTarget: backendName("api", "http", apiServiceRef.Tenancy),
}}, }},
}, },
{ {
@ -1232,7 +1268,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(barServiceRef, "http"), ParentRef: newParentRef(barServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("api", "http"): { backendName("api", "http", apiServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(apiServiceRef, "http", ""), BackendRef: newBackendRef(apiServiceRef, "http", ""),
@ -1261,7 +1297,7 @@ func (suite *controllerSuite) TestController() {
}}, }},
} }
httpRoute1ID = rtest.Resource(pbmesh.HTTPRouteType, "route1"). httpRoute1ID = rtest.Resource(pbmesh.HTTPRouteType, "route1").
WithTenancy(tenancy). WithTenancy(fooServiceRef.Tenancy).
WithData(suite.T(), httpRoute1). WithData(suite.T(), httpRoute1).
Write(suite.T(), suite.client). Write(suite.T(), suite.client).
Id Id
@ -1279,7 +1315,7 @@ func (suite *controllerSuite) TestController() {
{ {
Matches: defaultHTTPRouteMatches(), Matches: defaultHTTPRouteMatches(),
BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{
BackendTarget: backendName("bar", "http"), BackendTarget: backendName("bar", "http", barServiceRef.Tenancy),
}}, }},
}, },
}, },
@ -1289,7 +1325,7 @@ func (suite *controllerSuite) TestController() {
ParentRef: newParentRef(barServiceRef, "http"), ParentRef: newParentRef(barServiceRef, "http"),
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
Targets: map[string]*pbmesh.BackendTargetDetails{ Targets: map[string]*pbmesh.BackendTargetDetails{
backendName("bar", "http"): { backendName("bar", "http", barServiceRef.Tenancy): {
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
MeshPort: "mesh", MeshPort: "mesh",
BackendRef: newBackendRef(barServiceRef, "http", ""), BackendRef: newBackendRef(barServiceRef, "http", ""),
@ -1364,11 +1400,28 @@ func TestController(t *testing.T) {
suite.Run(t, new(controllerSuite)) suite.Run(t, new(controllerSuite))
} }
func (suite *controllerSuite) runTestCaseWithTenancies(testFunc func(*pbresource.Tenancy)) { func (suite *controllerSuite) runTestCaseWithTenancies(testFunc func(ref *testResourceRef)) {
for _, tenancy := range suite.tenancies { for _, mainServiceTenancy := range suite.tenancies {
suite.Run(suite.appendTenancyInfo(tenancy), func() { for _, otherServiceTenancy := range suite.tenancies {
testFunc(tenancy)
apiServiceRef := rtest.Resource(pbcatalog.ServiceType, "api").
WithTenancy(mainServiceTenancy).
Reference("")
fooServiceRef := rtest.Resource(pbcatalog.ServiceType, "foo").
WithTenancy(otherServiceTenancy).
Reference("")
barServiceRef := rtest.Resource(pbcatalog.ServiceType, "bar").
WithTenancy(otherServiceTenancy).
Reference("")
suite.Run(suite.appendTenancyInfo(mainServiceTenancy), func() {
testFunc(&testResourceRef{
apiServiceRef: apiServiceRef,
fooServiceRef: fooServiceRef,
barServiceRef: barServiceRef,
}) })
})
}
} }
} }