Add multi tenancy to sidecar proxy controller
This commit is contained in:
Ashesh Vidyut 2023-12-01 21:28:57 +05:30 committed by GitHub
parent ac9261ac3e
commit 82f6a8d7f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -44,15 +44,9 @@ type controllerTestSuite struct {
ctl *reconciler
ctx context.Context
apiWorkloadID *pbresource.ID
apiWorkload *pbcatalog.Workload
apiComputedTrafficPermissions *pbresource.Resource
apiComputedTrafficPermissionsData *pbauth.ComputedTrafficPermissions
apiService *pbresource.Resource
apiServiceData *pbcatalog.Service
apiEndpoints *pbresource.Resource
apiEndpointsData *pbcatalog.ServiceEndpoints
webWorkload *pbresource.Resource
webWorkload *pbresource.Resource
api map[tenancyKey]apiData
dbWorkloadID *pbresource.ID
dbWorkload *pbcatalog.Workload
@ -60,8 +54,33 @@ type controllerTestSuite struct {
dbEndpoints *pbresource.Resource
dbEndpointsData *pbcatalog.ServiceEndpoints
proxyStateTemplate *pbmesh.ProxyStateTemplate
tenancies []*pbresource.Tenancy
tenancies []*pbresource.Tenancy
}
type tenancyKey struct {
Namespace string
Partition string
}
func toTenancyKey(t *pbresource.Tenancy) tenancyKey {
return tenancyKey{
Namespace: t.Namespace,
Partition: t.Partition,
}
}
type apiData struct {
workloadID *pbresource.ID
workload *pbcatalog.Workload
computedTrafficPermissions *pbresource.Resource
computedTrafficPermissionsData *pbauth.ComputedTrafficPermissions
service *pbresource.Resource
destinationListenerName string
destinationClusterName string
serviceData *pbcatalog.Service
endpoints *pbresource.Resource
endpointsData *pbcatalog.ServiceEndpoints
proxyStateTemplate *pbmesh.ProxyStateTemplate
}
func (suite *controllerTestSuite) SetupTest() {
@ -98,48 +117,9 @@ func (suite *controllerTestSuite) SetupTest() {
"mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH},
},
}
suite.apiServiceData = &pbcatalog.Service{
Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}},
VirtualIps: []string{"1.1.1.1"},
Ports: []*pbcatalog.ServicePort{
{TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP},
{TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH},
},
}
suite.apiComputedTrafficPermissionsData = &pbauth.ComputedTrafficPermissions{
IsDefault: false,
AllowPermissions: []*pbauth.Permission{
{
Sources: []*pbauth.Source{
{
IdentityName: "foo",
Namespace: "default",
Partition: "default",
Peer: "local",
},
},
},
},
}
}
func (suite *controllerTestSuite) setupSuiteWithTenancy(tenancy *pbresource.Tenancy) {
suite.apiWorkload = &pbcatalog.Workload{
Identity: "api-identity",
Addresses: []*pbcatalog.WorkloadAddress{
{
Host: "10.0.0.1",
},
},
Ports: map[string]*pbcatalog.WorkloadPort{
"tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP},
"mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH},
},
}
webWorkloadData := &pbcatalog.Workload{
Identity: "web-identity",
Addresses: []*pbcatalog.WorkloadAddress{
@ -181,42 +161,101 @@ func (suite *controllerTestSuite) setupSuiteWithTenancy(tenancy *pbresource.Tena
},
},
}
suite.dbEndpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "db-service").
WithData(suite.T(), suite.dbEndpointsData).
WithTenancy(tenancy).
Write(suite.T(), suite.client)
suite.apiWorkloadID = resourcetest.Resource(pbcatalog.WorkloadType, "api-abc").
WithTenancy(tenancy).
WithData(suite.T(), suite.apiWorkload).
Write(suite.T(), suite.client.ResourceServiceClient).Id
suite.api = make(map[tenancyKey]apiData)
suite.apiComputedTrafficPermissions = resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, suite.apiWorkload.Identity).
WithData(suite.T(), suite.apiComputedTrafficPermissionsData).
WithTenancy(tenancy).
Write(suite.T(), suite.client.ResourceServiceClient)
for i, t := range suite.tenancies {
var a apiData
suite.apiService = resourcetest.Resource(pbcatalog.ServiceType, "api-service").
WithData(suite.T(), suite.apiServiceData).
WithTenancy(tenancy).
Write(suite.T(), suite.client.ResourceServiceClient)
suite.apiEndpointsData = &pbcatalog.ServiceEndpoints{
Endpoints: []*pbcatalog.Endpoint{
{
TargetRef: suite.apiWorkloadID,
Addresses: suite.apiWorkload.Addresses,
Ports: suite.apiWorkload.Ports,
Identity: "api-identity",
a.computedTrafficPermissionsData = &pbauth.ComputedTrafficPermissions{
IsDefault: false,
AllowPermissions: []*pbauth.Permission{
{
Sources: []*pbauth.Source{
{
IdentityName: "foo",
Namespace: "default",
Partition: "default",
Peer: "local",
},
},
},
},
},
}
}
suite.apiEndpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-service").
WithData(suite.T(), suite.apiEndpointsData).
WithTenancy(tenancy).
Write(suite.T(), suite.client.ResourceServiceClient)
a.workload = &pbcatalog.Workload{
Identity: "api-identity",
Addresses: []*pbcatalog.WorkloadAddress{
{
Host: "10.0.0.1",
},
},
Ports: map[string]*pbcatalog.WorkloadPort{
"tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP},
"mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH},
},
}
a.serviceData = &pbcatalog.Service{
Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}},
VirtualIps: []string{"1.1.1.1"},
Ports: []*pbcatalog.ServicePort{
{TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP},
{TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH},
},
}
a.workloadID = resourcetest.Resource(pbcatalog.WorkloadType, "api-abc").
WithTenancy(t).
WithData(suite.T(), a.workload).
Write(suite.T(), suite.client.ResourceServiceClient).Id
a.endpointsData = &pbcatalog.ServiceEndpoints{
Endpoints: []*pbcatalog.Endpoint{
{
TargetRef: a.workloadID,
Addresses: a.workload.Addresses,
Ports: a.workload.Ports,
Identity: "api-identity",
},
},
}
a.computedTrafficPermissions = resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, a.workload.Identity).
WithData(suite.T(), a.computedTrafficPermissionsData).
WithTenancy(t).
Write(suite.T(), suite.client.ResourceServiceClient)
a.service = resourcetest.Resource(pbcatalog.ServiceType, "api-service").
WithData(suite.T(), a.serviceData).
WithTenancy(t).
Write(suite.T(), suite.client.ResourceServiceClient)
a.endpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-service").
WithData(suite.T(), a.endpointsData).
WithTenancy(t).
Write(suite.T(), suite.client.ResourceServiceClient)
identityRef := &pbresource.Reference{
Name: a.workload.Identity,
Tenancy: a.workloadID.Tenancy,
Type: pbauth.WorkloadIdentityType,
}
a.destinationListenerName = builder.DestinationListenerName(resource.Reference(a.service.Id, ""), "tcp", "127.0.0.1", uint32(1234+i))
a.destinationClusterName = builder.DestinationSNI(resource.Reference(a.service.Id, ""), "dc1", "test.consul")
a.proxyStateTemplate = builder.New(resource.ReplaceType(pbmesh.ProxyStateTemplateType, a.workloadID),
identityRef, "test.consul", "dc1", false, nil).
BuildLocalApp(a.workload, a.computedTrafficPermissionsData).
Build()
suite.api[toTenancyKey(t)] = a
}
suite.webWorkload = resourcetest.Resource(pbcatalog.WorkloadType, "web-def").
WithData(suite.T(), webWorkloadData).
@ -250,17 +289,6 @@ func (suite *controllerTestSuite) setupSuiteWithTenancy(tenancy *pbresource.Tena
},
},
}).Write(suite.T(), suite.client)
identityRef := &pbresource.Reference{
Name: suite.apiWorkload.Identity,
Tenancy: suite.apiWorkloadID.Tenancy,
Type: pbauth.WorkloadIdentityType,
}
suite.proxyStateTemplate = builder.New(resource.ReplaceType(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID),
identityRef, "test.consul", "dc1", false, nil).
BuildLocalApp(suite.apiWorkload, suite.apiComputedTrafficPermissionsData).
Build()
}
func (suite *controllerTestSuite) TestWorkloadPortProtocolsFromService_NoServicesInCache() {
@ -465,35 +493,38 @@ func (suite *controllerTestSuite) TestReconcile_NonMeshWorkload() {
func (suite *controllerTestSuite) TestReconcile_NoExistingProxyStateTemplate() {
suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) {
api := suite.api[toTenancyKey(tenancy)]
err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{
ID: resourceID(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID.Name, tenancy),
ID: resourceID(pbmesh.ProxyStateTemplateType, api.workloadID.Name, tenancy),
})
require.NoError(suite.T(), err)
res := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID.Name, tenancy))
res := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, api.workloadID.Name, tenancy))
require.NoError(suite.T(), err)
require.NotNil(suite.T(), res.Data)
prototest.AssertDeepEqual(suite.T(), suite.apiWorkloadID, res.Owner)
prototest.AssertDeepEqual(suite.T(), api.workloadID, res.Owner)
})
}
func (suite *controllerTestSuite) TestReconcile_ExistingProxyStateTemplate_WithUpdates() {
suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) {
// This test ensures that we write a new proxy state template when there are changes.
api := suite.api[toTenancyKey(tenancy)]
// Write the original.
resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc").
WithData(suite.T(), suite.proxyStateTemplate).
WithOwner(suite.apiWorkloadID).
WithData(suite.T(), api.proxyStateTemplate).
WithOwner(api.workloadID).
WithTenancy(tenancy).
Write(suite.T(), suite.client.ResourceServiceClient)
// Update the apiWorkload and check that we default the port to tcp if it's unspecified.
suite.apiWorkload.Ports["tcp"].Protocol = pbcatalog.Protocol_PROTOCOL_UNSPECIFIED
api.workload.Ports["tcp"].Protocol = pbcatalog.Protocol_PROTOCOL_UNSPECIFIED
updatedWorkloadID := resourcetest.Resource(pbcatalog.WorkloadType, "api-abc").
WithTenancy(tenancy).
WithData(suite.T(), suite.apiWorkload).
WithData(suite.T(), api.workload).
Write(suite.T(), suite.client.ResourceServiceClient).Id
err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{
@ -523,17 +554,18 @@ func (suite *controllerTestSuite) TestReconcile_ExistingProxyStateTemplate_WithU
func (suite *controllerTestSuite) TestReconcile_ExistingProxyStateTemplate_NoUpdates() {
suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) {
// This test ensures that we skip writing of the proxy state template when there are no changes to it.
api := suite.api[toTenancyKey(tenancy)]
// Write the original.
originalProxyState := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc").
WithData(suite.T(), suite.proxyStateTemplate).
WithOwner(suite.apiWorkloadID).
WithData(suite.T(), api.proxyStateTemplate).
WithOwner(api.workloadID).
WithTenancy(tenancy).
Write(suite.T(), suite.client.ResourceServiceClient)
// Update the metadata on the apiWorkload which should result in no changes.
updatedWorkloadID := resourcetest.Resource(pbcatalog.WorkloadType, "api-abc").
WithData(suite.T(), suite.apiWorkload).
WithData(suite.T(), api.workload).
WithMeta("some", "meta").
Write(suite.T(), suite.client.ResourceServiceClient).Id
@ -542,7 +574,7 @@ func (suite *controllerTestSuite) TestReconcile_ExistingProxyStateTemplate_NoUpd
})
require.NoError(suite.T(), err)
updatedProxyState := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID.Name, tenancy))
updatedProxyState := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, api.workloadID.Name, tenancy))
resourcetest.RequireVersionUnchanged(suite.T(), updatedProxyState, originalProxyState.Version)
})
}
@ -563,13 +595,15 @@ func (suite *controllerTestSuite) TestController() {
// This should test interactions between the reconciler, the mappers, and the destinationsCache to ensure they work
// together and produce expected result.
api := suite.api[toTenancyKey(tenancy)]
// Run the controller manager
var (
// Create proxy state template IDs to check against in this test.
apiProxyStateTemplateID = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc").WithTenancy(tenancy).ID()
webProxyStateTemplateID = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "web-def").WithTenancy(tenancy).ID()
apiComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.apiService.Id)
apiComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, api.service.Id)
dbComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.dbService.Id)
apiProxyStateTemplate *pbresource.Resource
@ -585,33 +619,43 @@ func (suite *controllerTestSuite) TestController() {
})
// Write a default ComputedRoutes for api.
routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID,
resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.apiService),
)
for _, api := range suite.api {
crID := resource.ReplaceType(pbmesh.ComputedRoutesType, api.service.Id)
routestest.ReconcileComputedRoutes(suite.T(), suite.client, crID,
resourcetest.MustDecode[*pbcatalog.Service](suite.T(), api.service),
)
}
var destinations []*pbmesh.Destination
var i uint32
for _, t := range suite.tenancies {
destinations = append(destinations, &pbmesh.Destination{
DestinationRef: resource.Reference(suite.api[toTenancyKey(t)].service.Id, ""),
DestinationPort: "tcp",
ListenAddr: &pbmesh.Destination_IpPort{
IpPort: &pbmesh.IPPortAddress{
Ip: "127.0.0.1",
Port: 1234 + i,
},
},
})
i++
}
// Add a source service and check that a new proxy state is generated.
webComputedDestinations = resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webWorkload.Id.Name).
WithTenancy(tenancy).
WithData(suite.T(), &pbmesh.ComputedExplicitDestinations{
Destinations: []*pbmesh.Destination{
{
DestinationRef: resource.Reference(suite.apiService.Id, ""),
DestinationPort: "tcp",
ListenAddr: &pbmesh.Destination_IpPort{
IpPort: &pbmesh.IPPortAddress{
Ip: "127.0.0.1",
Port: 1234,
},
},
},
},
Destinations: destinations,
}).Write(suite.T(), suite.client)
testutil.RunStep(suite.T(), "add explicit destinations and check that new proxy state is generated", func(t *testing.T) {
webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version)
suite.waitForProxyStateTemplateState(t, webProxyStateTemplateID, func(rt resourcetest.T, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinationsFound(rt, "api", tmpl)
for _, data := range suite.api {
requireExplicitDestinationsFound(t, data.destinationListenerName, data.destinationClusterName, tmpl)
}
})
})
@ -632,11 +676,11 @@ func (suite *controllerTestSuite) TestController() {
WithTenancy(tenancy).
WithData(suite.T(), &pbcatalog.Workload{
Identity: "api-identity",
Addresses: suite.apiWorkload.Addresses,
Addresses: api.workload.Addresses,
Ports: nonMeshPorts}).
Write(suite.T(), suite.client)
suite.apiService = resourcetest.ResourceID(suite.apiService.Id).
api.service = resourcetest.ResourceID(api.service.Id).
WithTenancy(tenancy).
WithData(t, &pbcatalog.Service{
Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}},
@ -653,8 +697,8 @@ func (suite *controllerTestSuite) TestController() {
WithData(suite.T(), &pbcatalog.ServiceEndpoints{
Endpoints: []*pbcatalog.Endpoint{
{
TargetRef: suite.apiWorkloadID,
Addresses: suite.apiWorkload.Addresses,
TargetRef: api.workloadID,
Addresses: api.workload.Addresses,
Ports: nonMeshPorts,
Identity: "api-identity",
},
@ -664,7 +708,7 @@ func (suite *controllerTestSuite) TestController() {
// Refresh the computed routes in light of api losing a mesh port.
routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID,
resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService),
resourcetest.MustDecode[*pbcatalog.Service](t, api.service),
)
// Check that api proxy template is gone.
@ -676,7 +720,7 @@ func (suite *controllerTestSuite) TestController() {
webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version)
suite.waitForProxyStateTemplateState(t, webProxyStateTemplateID, func(rt resourcetest.T, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinationsNotFound(rt, "api", tmpl)
requireExplicitDestinationsNotFound(t, api.destinationListenerName, api.destinationClusterName, tmpl)
})
})
@ -687,29 +731,31 @@ func (suite *controllerTestSuite) TestController() {
resourcetest.Resource(pbcatalog.WorkloadType, "api-abc").
WithTenancy(tenancy).
WithData(suite.T(), suite.apiWorkload).
WithData(suite.T(), api.workload).
Write(suite.T(), suite.client)
suite.apiService = resourcetest.Resource(pbcatalog.ServiceType, "api-service").
WithData(suite.T(), suite.apiServiceData).
api.service = resourcetest.Resource(pbcatalog.ServiceType, "api-service").
WithData(suite.T(), api.serviceData).
WithTenancy(tenancy).
Write(suite.T(), suite.client.ResourceServiceClient)
resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-service").
WithTenancy(tenancy).
WithData(suite.T(), suite.apiEndpointsData).
WithData(suite.T(), api.endpointsData).
Write(suite.T(), suite.client.ResourceServiceClient)
// Refresh the computed routes in light of api losing a mesh port.
routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID,
resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService),
resourcetest.MustDecode[*pbcatalog.Service](t, api.service),
)
// We should also get a new web proxy template resource as this destination should be added again.
webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version)
suite.waitForProxyStateTemplateState(t, webProxyStateTemplateID, func(rt resourcetest.T, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinationsFound(rt, "api", tmpl)
for _, data := range suite.api {
requireExplicitDestinationsFound(t, data.destinationListenerName, data.destinationClusterName, tmpl)
}
})
})
@ -722,7 +768,9 @@ func (suite *controllerTestSuite) TestController() {
webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version)
suite.waitForProxyStateTemplateState(t, webProxyStateTemplateID, func(rt resourcetest.T, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinationsFound(rt, "api", tmpl)
for _, data := range suite.api {
requireExplicitDestinationsFound(t, data.destinationListenerName, data.destinationClusterName, tmpl)
}
})
})
@ -756,8 +804,13 @@ func (suite *controllerTestSuite) TestController() {
apiProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), apiProxyStateTemplateID, apiProxyStateTemplate.Version)
suite.waitForProxyStateTemplateState(t, webProxyStateTemplateID, func(rt resourcetest.T, tmpl *pbmesh.ProxyStateTemplate) {
requireImplicitDestinationsFound(rt, "api", tmpl)
requireImplicitDestinationsFound(rt, "db", tmpl)
listenerNameDb := fmt.Sprintf("%s/local/%s/db-service", tenancy.Partition, tenancy.Namespace)
clusterNameDb := fmt.Sprintf("db-service.%s.%s", tenancy.Namespace, tenancy.Partition)
if tenancy.Partition == "default" {
clusterNameDb = fmt.Sprintf("db-service.%s", tenancy.Namespace)
}
requireImplicitDestinationsFound(t, api.destinationListenerName, api.destinationClusterName, tmpl)
requireImplicitDestinationsFound(t, listenerNameDb, clusterNameDb, tmpl)
})
})
@ -767,16 +820,16 @@ func (suite *controllerTestSuite) TestController() {
assertTrafficPermissionDefaultPolicy(t, false, webProxyStateTemplate)
suite.runtime.Logger.Trace("deleting computed traffic permissions")
_, err := suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: suite.apiComputedTrafficPermissions.Id})
_, err := suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: api.computedTrafficPermissions.Id})
require.NoError(t, err)
suite.client.WaitForDeletion(t, suite.apiComputedTrafficPermissions.Id)
suite.client.WaitForDeletion(t, api.computedTrafficPermissions.Id)
apiProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), apiProxyStateTemplateID, apiProxyStateTemplate.Version)
suite.runtime.Logger.Trace("creating computed traffic permissions")
resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, suite.apiWorkload.Identity).
resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, api.workload.Identity).
WithTenancy(tenancy).
WithData(t, suite.apiComputedTrafficPermissionsData).
WithData(t, api.computedTrafficPermissionsData).
Write(t, suite.client)
suite.client.WaitForNewVersion(t, apiProxyStateTemplateID, apiProxyStateTemplate.Version)
@ -797,7 +850,7 @@ func (suite *controllerTestSuite) TestController() {
BackendRefs: []*pbmesh.HTTPBackendRef{
{
BackendRef: &pbmesh.BackendReference{
Ref: resource.Reference(suite.apiService.Id, ""),
Ref: resource.Reference(api.service.Id, ""),
Port: "tcp",
},
Weight: 60,
@ -824,15 +877,20 @@ func (suite *controllerTestSuite) TestController() {
dbCR := routestest.ReconcileComputedRoutes(suite.T(), suite.client, dbCRID,
resourcetest.MustDecode[*pbmesh.HTTPRoute](t, route),
resourcetest.MustDecode[*pbcatalog.Service](t, suite.dbService),
resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService),
resourcetest.MustDecode[*pbcatalog.Service](t, api.service),
)
require.NotNil(t, dbCR, "computed routes for db was deleted instead of created")
webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version)
suite.waitForProxyStateTemplateState(t, webProxyStateTemplateID, func(rt resourcetest.T, tmpl *pbmesh.ProxyStateTemplate) {
requireImplicitDestinationsFound(rt, "api", tmpl)
requireImplicitDestinationsFound(rt, "db", tmpl)
listenerNameDb := fmt.Sprintf("%s/local/%s/db-service", tenancy.Partition, tenancy.Namespace)
clusterNameDb := fmt.Sprintf("db-service.%s.%s", tenancy.Namespace, tenancy.Partition)
if tenancy.Partition == "default" {
clusterNameDb = fmt.Sprintf("db-service.%s", tenancy.Namespace)
}
requireImplicitDestinationsFound(t, api.destinationListenerName, api.destinationClusterName, tmpl)
requireImplicitDestinationsFound(t, listenerNameDb, clusterNameDb, tmpl)
})
})
})
@ -872,21 +930,21 @@ func TestMeshController(t *testing.T) {
suite.Run(t, new(controllerTestSuite))
}
func requireExplicitDestinationsFound(t resourcetest.T, name string, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinations(t, name, tmpl, true)
func requireExplicitDestinationsFound(t *testing.T, listenerName, clusterName string, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinations(t, listenerName, clusterName, tmpl, true)
}
func requireExplicitDestinationsNotFound(t resourcetest.T, name string, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinations(t, name, tmpl, false)
func requireExplicitDestinationsNotFound(t *testing.T, listenerName, clusterName string, tmpl *pbmesh.ProxyStateTemplate) {
requireExplicitDestinations(t, listenerName, clusterName, tmpl, false)
}
func requireExplicitDestinations(t resourcetest.T, name string, tmpl *pbmesh.ProxyStateTemplate, found bool) {
func requireExplicitDestinations(t resourcetest.T, listenerName string, clusterName string, tmpl *pbmesh.ProxyStateTemplate, found bool) {
t.Helper()
// Check outbound listener.
var foundListener bool
for _, l := range tmpl.ProxyState.Listeners {
if strings.Contains(l.Name, name) && l.Direction == pbproxystate.Direction_DIRECTION_OUTBOUND {
if l.Name == listenerName && l.Direction == pbproxystate.Direction_DIRECTION_OUTBOUND {
foundListener = true
break
}
@ -894,10 +952,10 @@ func requireExplicitDestinations(t resourcetest.T, name string, tmpl *pbmesh.Pro
require.Equal(t, found, foundListener)
requireClustersAndEndpoints(t, name, tmpl, found)
requireClustersAndEndpoints(t, clusterName, tmpl, found)
}
func requireImplicitDestinationsFound(t resourcetest.T, name string, tmpl *pbmesh.ProxyStateTemplate) {
func requireImplicitDestinationsFound(t resourcetest.T, listenerName string, clusterName string, tmpl *pbmesh.ProxyStateTemplate) {
t.Helper()
// Check outbound listener.
@ -920,7 +978,7 @@ func requireImplicitDestinationsFound(t resourcetest.T, name string, tmpl *pbmes
case *pbproxystate.Router_L7:
require.NotNil(t, x.L7.Route)
routerName := x.L7.Route.Name
foundByName = strings.Contains(routerName, name)
foundByName = strings.Contains(routerName, listenerName)
default:
t.Fatalf("unexpected type of destination: %T", r.Destination)
}
@ -937,15 +995,15 @@ func requireImplicitDestinationsFound(t resourcetest.T, name string, tmpl *pbmes
}
require.True(t, foundListener)
requireClustersAndEndpoints(t, name, tmpl, true)
requireClustersAndEndpoints(t, clusterName, tmpl, true)
}
func requireClustersAndEndpoints(t resourcetest.T, name string, tmpl *pbmesh.ProxyStateTemplate, found bool) {
func requireClustersAndEndpoints(t resourcetest.T, clusterName string, tmpl *pbmesh.ProxyStateTemplate, found bool) {
t.Helper()
var foundCluster bool
for c := range tmpl.ProxyState.Clusters {
if strings.Contains(c, name) {
if strings.Contains(c, clusterName) {
foundCluster = true
break
}
@ -955,7 +1013,7 @@ func requireClustersAndEndpoints(t resourcetest.T, name string, tmpl *pbmesh.Pro
var foundEndpoints bool
for c := range tmpl.RequiredEndpoints {
if strings.Contains(c, name) {
if strings.Contains(c, clusterName) {
foundEndpoints = true
break
}
@ -1003,10 +1061,12 @@ func (suite *controllerTestSuite) appendTenancyInfo(tenancy *pbresource.Tenancy)
func (suite *controllerTestSuite) cleanupResources() {
suite.client.MustDelete(suite.T(), suite.apiWorkloadID)
suite.client.MustDelete(suite.T(), suite.apiComputedTrafficPermissions.Id)
suite.client.MustDelete(suite.T(), suite.apiService.Id)
suite.client.MustDelete(suite.T(), suite.apiEndpoints.Id)
for _, api := range suite.api {
suite.client.MustDelete(suite.T(), api.workloadID)
suite.client.MustDelete(suite.T(), api.computedTrafficPermissions.Id)
suite.client.MustDelete(suite.T(), api.service.Id)
suite.client.MustDelete(suite.T(), api.endpoints.Id)
}
suite.client.MustDelete(suite.T(), suite.webWorkload.Id)
suite.client.MustDelete(suite.T(), suite.dbWorkloadID)
suite.client.MustDelete(suite.T(), suite.dbService.Id)