From f142c779564785fa1303af58502e0313cab4c538 Mon Sep 17 00:00:00 2001 From: John Murret Date: Thu, 12 Oct 2023 10:16:12 -0600 Subject: [PATCH 01/14] NET-5397 - wire up golden tests from sidecar-proxy controller for xds controller and xdsv2 --- .../controllers/xds/controller_test.go | 76 ++++++++++++++++++- internal/testing/golden/golden.go | 10 ++- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 8d4799e2da28..4987995c57e2 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -7,10 +7,12 @@ import ( "context" "crypto/x509" "encoding/pem" - "testing" - + "fmt" + "github.com/hashicorp/consul/internal/testing/golden" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "google.golang.org/protobuf/encoding/protojson" + "testing" svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/agent/leafcert" @@ -998,3 +1000,73 @@ func (suite *xdsControllerTestSuite) TestReconcile_prevWatchesToCancel() { func TestXdsController(t *testing.T) { suite.Run(t, new(xdsControllerTestSuite)) } + +func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { + path := "../sidecarproxy/builder/testdata" + cases := []string{ + "destination/l4-single-destination-ip-port-bind-address", + "destination/l4-single-destination-unix-socket-bind-address", + "destination/l4-multi-destination", + "destination/mixed-multi-destination", + } + + for _, name := range cases { + suite.Run(name, func() { + // Create ProxyStateTemplate from the golden file. + pst := JSONToProxyTemplate(suite.T(), + golden.GetBytesAtFilePath(suite.T(), fmt.Sprintf("%s/%s.golden", path, name))) + + // Store the initial ProxyStateTemplate and track it in the mapper. + proxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test"). + WithData(suite.T(), pst). + Write(suite.T(), suite.client) + + suite.mapper.TrackItem(proxyStateTemplate.Id, []resource.ReferenceOrID{}) + for idx, ep := range pst.ProxyState.Endpoints { + resourcetest.Resource(pbcatalog.ServiceEndpointsType, fmt.Sprintf("test-%d", idx)). + WithData(suite.T(), ep). + Write(suite.T(), suite.client) + } + + // Run the reconcile, and since no ProxyStateTemplate is stored, this simulates a deletion. + err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ + ID: proxyStateTemplate.Id, + }) + require.NoError(suite.T(), err) + + require.NotNil(suite.T(), proxyStateTemplate) + //require.JSONEq(suite.T(), expected, actual) + }) + } +} + +func (suite *xdsControllerTestSuite) TestBuildImplicitDestinations() { + + cases := []string{ + "destination/l4-single-implicit-destination-tproxy", + "destination/l4-multiple-implicit-destinations-tproxy", + "destination/l4-implicit-and-explicit-destinations-tproxy", + } + + for _, name := range cases { + suite.Run(name, func() { + //proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", false, proxyCfg). + // BuildDestinations(c.destinations). + // Build() + // + //actual := protoToJSON(t, proxyTmpl) + //expected := golden.Get(t, actual, name+".golden") + // + //require.JSONEq(t, expected, actual) + }) + } +} + +func JSONToProxyTemplate(t *testing.T, json []byte) *pbmesh.ProxyStateTemplate { + t.Helper() + proxyTemplate := &pbmesh.ProxyStateTemplate{} + m := protojson.UnmarshalOptions{} + err := m.Unmarshal(json, proxyTemplate) + require.NoError(t, err) + return proxyTemplate +} diff --git a/internal/testing/golden/golden.go b/internal/testing/golden/golden.go index 8145d16814bf..a4d971d0d096 100644 --- a/internal/testing/golden/golden.go +++ b/internal/testing/golden/golden.go @@ -42,7 +42,15 @@ func GetBytes(t *testing.T, actual, filename string) []byte { require.NoError(t, err) } - expected, err := os.ReadFile(path) + return GetBytesAtFilePath(t, path) +} + +// GetBytes reads the expected value from the file at filepath and returns the +// value as a byte array. filepath is relative to the ./testdata directory. +func GetBytesAtFilePath(t *testing.T, filepath string) []byte { + t.Helper() + + expected, err := os.ReadFile(filepath) require.NoError(t, err) return expected } From 79eadd1afd947673fc70570a75f8646784f6b23b Mon Sep 17 00:00:00 2001 From: John Murret Date: Fri, 13 Oct 2023 10:51:58 -0600 Subject: [PATCH 02/14] WIP --- .../controllers/xds/controller_test.go | 79 ++++++++- ...le-destination-ip-port-bind-address.golden | 162 ++++++++++++++++++ 2 files changed, 232 insertions(+), 9 deletions(-) create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 4987995c57e2..cde26bdd0d86 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "google.golang.org/protobuf/encoding/protojson" + "strings" "testing" svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" @@ -1005,9 +1006,9 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { path := "../sidecarproxy/builder/testdata" cases := []string{ "destination/l4-single-destination-ip-port-bind-address", - "destination/l4-single-destination-unix-socket-bind-address", - "destination/l4-multi-destination", - "destination/mixed-multi-destination", + //"destination/l4-single-destination-unix-socket-bind-address", + //"destination/l4-multi-destination", + //"destination/mixed-multi-destination", } for _, name := range cases { @@ -1016,17 +1017,73 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { pst := JSONToProxyTemplate(suite.T(), golden.GetBytesAtFilePath(suite.T(), fmt.Sprintf("%s/%s.golden", path, name))) + //get service data + serviceData := &pbcatalog.Service{} + var vp uint32 = 7000 + svcNames := map[string]map[string]string + + // get service name and ports + for name := range pst.RequiredEndpoints { + vp++ + nameSplit := strings.Split(name, ".") + port := nameSplit[0] + svcNames[nameSplit[1]] = name + serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ + TargetPort: port, + VirtualPort: vp, + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, + }) + } + + svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). + WithData(suite.T(), &pbcatalog.Service{}). + Write(suite.T(), suite.client) + + eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ + { + Ports: map[string]*pbcatalog.WorkloadPort{ + "mesh": { + Port: 20000, + Protocol: pbcatalog.Protocol_PROTOCOL_MESH, + }, + }, + Addresses: []*pbcatalog.WorkloadAddress{ + { + Host: "10.1.1.1", + Ports: []string{"mesh"}, + }, + }, + }, + }}). + WithOwner(svc.Id). + Write(suite.T(), suite.client) + // + requiredEps := make(map[string]*pbproxystate.EndpointRef) + for epName := range pst.RequiredEndpoints { + requiredEps[epName] = &pbproxystate.EndpointRef{ + Id: eps.Id, + Port: "mesh", + } + } + + wiLeafs := make(map[string]*pbproxystate.LeafCertificateRef) + wiLeafs["wi-workload-identity"] = &pbproxystate.LeafCertificateRef{ + Name: "wi-workload-identity", + } + + pst.RequiredEndpoints = requiredEps + // Store the initial ProxyStateTemplate and track it in the mapper. proxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test"). WithData(suite.T(), pst). Write(suite.T(), suite.client) + retry.Run(suite.T(), func(r *retry.R) { + suite.client.RequireResourceExists(r, proxyStateTemplate.Id) + }) + suite.mapper.TrackItem(proxyStateTemplate.Id, []resource.ReferenceOrID{}) - for idx, ep := range pst.ProxyState.Endpoints { - resourcetest.Resource(pbcatalog.ServiceEndpointsType, fmt.Sprintf("test-%d", idx)). - WithData(suite.T(), ep). - Write(suite.T(), suite.client) - } // Run the reconcile, and since no ProxyStateTemplate is stored, this simulates a deletion. err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ @@ -1035,7 +1092,11 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { require.NoError(suite.T(), err) require.NotNil(suite.T(), proxyStateTemplate) - //require.JSONEq(suite.T(), expected, actual) + + actual := prototest.ProtoToJSON(suite.T(), proxyStateTemplate.Data) + expected := golden.Get(suite.T(), actual, name+".golden") + + require.JSONEq(suite.T(), expected, actual) }) } } diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden new file mode 100644 index 000000000000..7ba711123559 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden @@ -0,0 +1,162 @@ +{ + "proxyState": { + "clusters": { + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" + } + } + }, + "name": "null_route_cluster" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "default/local/default/api-1:tcp:1.1.1.1:1234", + "routers": [ + { + "l4": { + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + } + } + ] + } + ] + }, + "requiredEndpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "id": { + "name": "api-1", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v2beta1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "id": { + "name": "api-2", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "catalog", + "groupVersion": "v2beta1", + "kind": "ServiceEndpoints" + } + }, + "port": "mesh" + } + }, + "requiredLeafCertificates": { + "test-identity": { + "name": "test-identity", + "namespace": "default", + "partition": "default" + } + }, + "requiredTrustBundles": { + "local": { + "peer": "local" + } + } +} \ No newline at end of file From d269c63a99396b9bd62055a1f18b7842fd775326 Mon Sep 17 00:00:00 2001 From: John Murret Date: Fri, 13 Oct 2023 13:58:49 -0600 Subject: [PATCH 03/14] WIP --- .../controllers/xds/controller_test.go | 59 ++--- ...le-destination-ip-port-bind-address.golden | 236 +++++++----------- 2 files changed, 124 insertions(+), 171 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index cde26bdd0d86..bf0d96d0e1b4 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1020,48 +1020,47 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { //get service data serviceData := &pbcatalog.Service{} var vp uint32 = 7000 - svcNames := map[string]map[string]string + requiredEps := make(map[string]*pbproxystate.EndpointRef) // get service name and ports - for name := range pst.RequiredEndpoints { + for name := range pst.ProxyState.Clusters { + if name == "null_route_cluster" { + continue + } vp++ nameSplit := strings.Split(name, ".") port := nameSplit[0] - svcNames[nameSplit[1]] = name + svcName := nameSplit[1] serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ TargetPort: port, VirtualPort: vp, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, }) - } - svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, + svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). + WithData(suite.T(), &pbcatalog.Service{}). + Write(suite.T(), suite.client) + + eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ + { + Ports: map[string]*pbcatalog.WorkloadPort{ + "mesh": { + Port: 20000, + Protocol: pbcatalog.Protocol_PROTOCOL_MESH, + }, }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, + Addresses: []*pbcatalog.WorkloadAddress{ + { + Host: "10.1.1.1", + Ports: []string{"mesh"}, + }, }, }, - }, - }}). - WithOwner(svc.Id). - Write(suite.T(), suite.client) - // - requiredEps := make(map[string]*pbproxystate.EndpointRef) - for epName := range pst.RequiredEndpoints { - requiredEps[epName] = &pbproxystate.EndpointRef{ + }}). + WithOwner(svc.Id). + Write(suite.T(), suite.client) + requiredEps[name] = &pbproxystate.EndpointRef{ Id: eps.Id, Port: "mesh", } @@ -1093,7 +1092,9 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { require.NotNil(suite.T(), proxyStateTemplate) - actual := prototest.ProtoToJSON(suite.T(), proxyStateTemplate.Data) + reconciledPS := suite.updater.Get(proxyStateTemplate.Id.Name) + actual := prototest.ProtoToJSON(suite.T(), reconciledPS) + expected := golden.Get(suite.T(), actual, name+".golden") require.JSONEq(suite.T(), expected, actual) diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden index 7ba711123559..c614f009d695 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden @@ -1,162 +1,114 @@ { - "proxyState": { - "clusters": { - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } + "clusters": { + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" } - }, - "name": "null_route_cluster" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" + } }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } + "name": "null_route_cluster" }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" } } } - ] - } - ] - }, - "requiredEndpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" } }, - "port": "mesh" + "name": "tcp.api-1.default.dc1.internal.foo.consul" }, "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } } }, - "port": "mesh" + "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", + "identity": { + "name": "test-identity", + "tenancy": { "namespace": "default", - "partition": "default" + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" } }, - "requiredTrustBundles": { - "local": { - "peer": "local" + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "default/local/default/api-1:tcp:1.1.1.1:1234", + "routers": [ + { + "l4": { + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + } + } + ] } - } + ] } \ No newline at end of file From 532aad4dbfb6936aedde84cf519d07036100fdec Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 09:49:00 -0600 Subject: [PATCH 04/14] everything matching except leafCerts. need to mock those --- ...le-destination-ip-port-bind-address.golden | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden index c614f009d695..d63cfb62cd03 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden @@ -65,6 +65,30 @@ "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, "identity": { "name": "test-identity", "tenancy": { @@ -78,6 +102,12 @@ "kind": "WorkloadIdentity" } }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTU0MzQxWhcNMjMxMDE2MTU1MzQxWjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAECjAS1priKKg5DX2byiWj7rP/javtusIwUXXNZjLcL93d\nt1/TJ3BeGQjcye7Tj4fg7u1xKQe4zzzl9jzhNImDbqOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQgm9EL7d6QLgSa4XcBMrJe254kOIyY4qeEG1XkyHxgNqgw\nKwYDVR0jBCQwIoAgrxX5IdfjyCYUhGtC4FxnuPtk2WpVnEJvN7Tb+0dORfcwbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNIADBFAiEAsQylgvCf1TuK7Efng1VZ\nlYyP8fHV3ndNjq7DxGHBp9kCIHkDszWused6R5GAsRBNp3nwzK7fGWncrEQJGetp\nCNtQ\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIPYFUcC4ZIeQRE/PfF7DsK5CeL4uEh2C6aFIyLYg2734oAoGCCqGSM49\nAwEHoUQDQgAECjAS1priKKg5DX2byiWj7rP/javtusIwUXXNZjLcL93dt1/TJ3Be\nGQjcye7Tj4fg7u1xKQe4zzzl9jzhNImDbg==\n-----END EC PRIVATE KEY-----\n" + } + }, "listeners": [ { "direction": "DIRECTION_OUTBOUND", @@ -110,5 +140,14 @@ } ] } - ] + ], + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + } } \ No newline at end of file From 2de83d470fba555de31360770d383a635b33b200 Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 10:29:18 -0600 Subject: [PATCH 05/14] single port destinations working except mixed destinations --- .../controllers/xds/controller_test.go | 18 +- .../destination/l4-multi-destination.golden | 296 ++++++++++++++ ...le-destination-ip-port-bind-address.golden | 60 +-- ...estination-unix-socket-bind-address.golden | 92 +++++ .../mixed-multi-destination.golden | 371 ++++++++++++++++++ 5 files changed, 803 insertions(+), 34 deletions(-) create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index bf0d96d0e1b4..5b08562350ec 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1006,9 +1006,9 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { path := "../sidecarproxy/builder/testdata" cases := []string{ "destination/l4-single-destination-ip-port-bind-address", - //"destination/l4-single-destination-unix-socket-bind-address", - //"destination/l4-multi-destination", - //"destination/mixed-multi-destination", + "destination/l4-single-destination-unix-socket-bind-address", + "destination/l4-multi-destination", + "destination/mixed-multi-destination", } for _, name := range cases { @@ -1093,8 +1093,18 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { require.NotNil(suite.T(), proxyStateTemplate) reconciledPS := suite.updater.Get(proxyStateTemplate.Id.Name) - actual := prototest.ProtoToJSON(suite.T(), reconciledPS) + // Verify leaf cert contents then hard code them for comparison + // and downstream tests since they change from test run to test run. + require.NotEmpty(suite.T(), reconciledPS.LeafCertificates) + reconciledPS.LeafCertificates = map[string]*pbproxystate.LeafCertificate{ + "test-identity": { + Cert: "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + Key: "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n", + }, + } + + actual := prototest.ProtoToJSON(suite.T(), reconciledPS) expected := golden.Get(suite.T(), actual, name+".golden") require.JSONEq(suite.T(), expected, actual) diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden new file mode 100644 index 000000000000..50589a070201 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden @@ -0,0 +1,296 @@ +{ + "clusters": { + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" + } + } + }, + "name": "null_route_cluster" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "tcp2.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp2.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp2" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp2.api-1.default.dc1.internal.foo.consul" + }, + "tcp2.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp2.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp2" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp2.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "default/local/default/api-1:tcp:1.1.1.1:1234", + "routers": [ + { + "l4": { + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + } + } + ] + }, + { + "direction": "DIRECTION_OUTBOUND", + "name": "default/local/default/api-2:tcp:/path/to/socket", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + } + } + ], + "unixSocket": { + "mode": "0666", + "path": "/path/to/socket" + } + }, + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 2345 + }, + "name": "default/local/default/api-1:tcp2:1.1.1.1:2345", + "routers": [ + { + "l4": { + "statPrefix": "upstream.tcp2.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp2.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp2.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + } + } + ] + }, + { + "direction": "DIRECTION_OUTBOUND", + "name": "default/local/default/api-2:tcp2:/path/to/socket", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp2.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp2.api-2.default.default.dc1" + } + } + ], + "unixSocket": { + "mode": "0666", + "path": "/path/to/socket" + } + } + ], + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden index d63cfb62cd03..a1e052854d71 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden @@ -65,30 +65,6 @@ "name": "tcp.api-2.default.dc1.internal.foo.consul" } }, - "endpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, "identity": { "name": "test-identity", "tenancy": { @@ -102,12 +78,6 @@ "kind": "WorkloadIdentity" } }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTU0MzQxWhcNMjMxMDE2MTU1MzQxWjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAECjAS1priKKg5DX2byiWj7rP/javtusIwUXXNZjLcL93d\nt1/TJ3BeGQjcye7Tj4fg7u1xKQe4zzzl9jzhNImDbqOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQgm9EL7d6QLgSa4XcBMrJe254kOIyY4qeEG1XkyHxgNqgw\nKwYDVR0jBCQwIoAgrxX5IdfjyCYUhGtC4FxnuPtk2WpVnEJvN7Tb+0dORfcwbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNIADBFAiEAsQylgvCf1TuK7Efng1VZ\nlYyP8fHV3ndNjq7DxGHBp9kCIHkDszWused6R5GAsRBNp3nwzK7fGWncrEQJGetp\nCNtQ\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIPYFUcC4ZIeQRE/PfF7DsK5CeL4uEh2C6aFIyLYg2734oAoGCCqGSM49\nAwEHoUQDQgAECjAS1priKKg5DX2byiWj7rP/javtusIwUXXNZjLcL93dt1/TJ3Be\nGQjcye7Tj4fg7u1xKQe4zzzl9jzhNImDbg==\n-----END EC PRIVATE KEY-----\n" - } - }, "listeners": [ { "direction": "DIRECTION_OUTBOUND", @@ -141,6 +111,30 @@ ] } ], + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, "trustBundles": { "local": { "roots": [ @@ -149,5 +143,11 @@ ], "trustDomain": "some-trust-domain" } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } } } \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden new file mode 100644 index 000000000000..99a94f7efff3 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden @@ -0,0 +1,92 @@ +{ + "clusters": { + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "name": "default/local/default/api-2:tcp:/path/to/socket", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + } + } + ], + "unixSocket": { + "mode": "0666", + "path": "/path/to/socket" + } + } + ], + "endpoints": { + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden new file mode 100644 index 000000000000..7c5cab23d23a --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden @@ -0,0 +1,371 @@ +{ + "clusters": { + "http.api-1.default.dc1.internal.foo.consul": { + "altStatName": "http.api-1.default.dc1.internal.foo.consul", + "failoverGroup": { + "config": { + "connectTimeout": "55s", + "useAltStatName": true + }, + "endpointGroups": [ + { + "dynamic": { + "config": { + "connectTimeout": "55s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "backup-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/backup1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + }, + "name": "failover-target~0~http.api-1.default.dc1.internal.foo.consul" + } + ] + }, + "name": "http.api-1.default.dc1.internal.foo.consul" + }, + "http.api-2.default.dc1.internal.foo.consul": { + "altStatName": "http.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "http.api-2.default.dc1.internal.foo.consul" + }, + "null_route_cluster": { + "endpointGroup": { + "static": { + "config": { + "connectTimeout": "10s" + } + } + }, + "name": "null_route_cluster" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "default/local/default/api-1:tcp:1.1.1.1:1234", + "routers": [ + { + "l4": { + "statPrefix": "upstream.tcp.api-1.default.default.dc1", + "weightedClusters": { + "clusters": [ + { + "name": "tcp.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "tcp.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + } + } + ] + }, + { + "direction": "DIRECTION_OUTBOUND", + "name": "default/local/default/api-2:tcp:/path/to/socket", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + } + } + ], + "unixSocket": { + "mode": "0666", + "path": "/path/to/socket" + } + }, + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "default/local/default/api-1:http:1.1.1.1:1234", + "routers": [ + { + "l7": { + "route": { + "name": "default/local/default/api-1:http:1.1.1.1:1234" + }, + "statPrefix": "upstream." + } + } + ] + } + ], + "routes": { + "default/local/default/api-1:http:1.1.1.1:1234": { + "virtualHosts": [ + { + "name": "default/local/default/api-1:http:1.1.1.1:1234", + "routeRules": [ + { + "destination": { + "destinationConfiguration": { + "timeoutConfig": { + "timeout": "77s" + } + }, + "weightedClusters": { + "clusters": [ + { + "name": "http.api-2.default.dc1.internal.foo.consul", + "weight": 60 + }, + { + "name": "http.api-1.default.dc1.internal.foo.consul", + "weight": 40 + }, + { + "name": "null_route_cluster", + "weight": 10 + } + ] + } + }, + "match": { + "pathMatch": { + "prefix": "/split" + } + } + }, + { + "destination": { + "cluster": { + "name": "http.api-1.default.dc1.internal.foo.consul" + }, + "destinationConfiguration": { + "retryPolicy": { + "numRetries": 4, + "retryOn": "connect-failure" + }, + "timeoutConfig": { + "timeout": "606s" + } + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + }, + { + "destination": { + "cluster": { + "name": "null_route_cluster" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + } + }, + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file From c8af477a308677eacdc592d2e2896ea4e1a81ead Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 12:35:19 -0600 Subject: [PATCH 06/14] golden test input to xds controller tests for destinations --- .../controllers/xds/controller_test.go | 39 +- ...it-and-explicit-destinations-tproxy.golden | 182 +++++++ ...ltiple-implicit-destinations-tproxy.golden | 181 +++++++ ...-single-implicit-destination-tproxy.golden | 122 +++++ ...ltiple-implicit-destinations-tproxy.golden | 453 ++++++++++++++++++ ...-single-implicit-destination-tproxy.golden | 255 ++++++++++ ...tion-with-multiple-workloads-tproxy.golden | 255 ++++++++++ 7 files changed, 1462 insertions(+), 25 deletions(-) create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden create mode 100644 internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 5b08562350ec..8476b87c8c50 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1002,13 +1002,24 @@ func TestXdsController(t *testing.T) { suite.Run(t, new(xdsControllerTestSuite)) } -func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { +func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs() { path := "../sidecarproxy/builder/testdata" cases := []string{ + // destinations "destination/l4-single-destination-ip-port-bind-address", "destination/l4-single-destination-unix-socket-bind-address", + "destination/l4-single-implicit-destination-tproxy", "destination/l4-multi-destination", - "destination/mixed-multi-destination", + "destination/l4-multiple-implicit-destinations-tproxy", + "destination/l4-implicit-and-explicit-destinations-tproxy", + // TODO(jm): resolve the endpoint group naming issue + //"destination/mixed-multi-destination", + "destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy", + "destination/multiport-l4-and-l7-single-implicit-destination-tproxy", + "destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy", + + //sources + } for _, name := range cases { @@ -1024,7 +1035,7 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { // get service name and ports for name := range pst.ProxyState.Clusters { - if name == "null_route_cluster" { + if name == "null_route_cluster" || name == "original-destination" { continue } vp++ @@ -1112,28 +1123,6 @@ func (suite *xdsControllerTestSuite) TestBuildExplicitDestinations() { } } -func (suite *xdsControllerTestSuite) TestBuildImplicitDestinations() { - - cases := []string{ - "destination/l4-single-implicit-destination-tproxy", - "destination/l4-multiple-implicit-destinations-tproxy", - "destination/l4-implicit-and-explicit-destinations-tproxy", - } - - for _, name := range cases { - suite.Run(name, func() { - //proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", false, proxyCfg). - // BuildDestinations(c.destinations). - // Build() - // - //actual := protoToJSON(t, proxyTmpl) - //expected := golden.Get(t, actual, name+".golden") - // - //require.JSONEq(t, expected, actual) - }) - } -} - func JSONToProxyTemplate(t *testing.T, json []byte) *pbmesh.ProxyStateTemplate { t.Helper() proxyTemplate := &pbmesh.ProxyStateTemplate{} diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden new file mode 100644 index 000000000000..45b981a955d7 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden @@ -0,0 +1,182 @@ +{ + "clusters": { + "original-destination": { + "endpointGroup": { + "passthrough": { + "config": { + "connectTimeout": "5s" + } + } + }, + "name": "original-destination" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "1.1.1.1", + "port": 1234 + }, + "name": "default/local/default/api-1:tcp:1.1.1.1:1234", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-1.default.default.dc1" + } + } + ] + }, + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "defaultRouter": { + "l4": { + "cluster": { + "name": "original-destination" + }, + "statPrefix": "upstream.original-destination" + } + }, + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + } + ] + } + ], + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden new file mode 100644 index 000000000000..42561f15e7ec --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden @@ -0,0 +1,181 @@ +{ + "clusters": { + "original-destination": { + "endpointGroup": { + "passthrough": { + "config": { + "connectTimeout": "5s" + } + } + }, + "name": "original-destination" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "defaultRouter": { + "l4": { + "cluster": { + "name": "original-destination" + }, + "statPrefix": "upstream.original-destination" + } + }, + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-1.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp.api-2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-2.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + } + ] + } + ], + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden new file mode 100644 index 000000000000..6735fc7de59d --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden @@ -0,0 +1,122 @@ +{ + "clusters": { + "original-destination": { + "endpointGroup": { + "passthrough": { + "config": { + "connectTimeout": "5s" + } + } + }, + "name": "original-destination" + }, + "tcp.api-1.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-1.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-1.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "defaultRouter": { + "l4": { + "cluster": { + "name": "original-destination" + }, + "statPrefix": "upstream.original-destination" + } + }, + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-1.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-1.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + } + ] + } + ], + "endpoints": { + "tcp.api-1.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden new file mode 100644 index 000000000000..47911d19a9c9 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden @@ -0,0 +1,453 @@ +{ + "clusters": { + "http.api-app.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "http.api-app.default.dc1.internal.foo.consul" + }, + "http.api-app2.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "http.api-app2.default.dc1.internal.foo.consul" + }, + "original-destination": { + "endpointGroup": { + "passthrough": { + "config": { + "connectTimeout": "5s" + } + } + }, + "name": "original-destination" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "tcp.api-app2.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-app2.default.dc1.internal.foo.consul" + }, + "tcp2.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp2" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp2.api-app.default.dc1.internal.foo.consul" + }, + "tcp2.api-app2.default.dc1.internal.foo.consul": { + "altStatName": "tcp2.api-app2.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp2" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app2.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp2.api-app2.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "defaultRouter": { + "l4": { + "cluster": { + "name": "original-destination" + }, + "statPrefix": "upstream.original-destination" + } + }, + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp.api-app2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app2.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + }, + { + "l7": { + "route": { + "name": "default/local/default/api-app" + }, + "statPrefix": "upstream." + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l7": { + "route": { + "name": "default/local/default/api-app2" + }, + "statPrefix": "upstream." + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp2.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp2.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 8081, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp2.api-app2.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp2.api-app2.default.default.dc1" + }, + "match": { + "destinationPort": 8081, + "prefixRanges": [ + { + "addressPrefix": "2.2.2.2", + "prefixLen": 32 + }, + { + "addressPrefix": "3.3.3.3", + "prefixLen": 32 + } + ] + } + } + ] + } + ], + "routes": { + "default/local/default/api-app": { + "virtualHosts": [ + { + "name": "default/local/default/api-app", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + }, + "default/local/default/api-app2": { + "virtualHosts": [ + { + "name": "default/local/default/api-app2", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app2.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + } + }, + "endpoints": { + "tcp.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp.api-app2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-app2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "http.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "http.api-app2.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden new file mode 100644 index 000000000000..b4e04bd09919 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden @@ -0,0 +1,255 @@ +{ + "clusters": { + "http.api-app.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "http.api-app.default.dc1.internal.foo.consul" + }, + "original-destination": { + "endpointGroup": { + "passthrough": { + "config": { + "connectTimeout": "5s" + } + } + }, + "name": "original-destination" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "tcp2.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp2" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp2.api-app.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "defaultRouter": { + "l4": { + "cluster": { + "name": "original-destination" + }, + "statPrefix": "upstream.original-destination" + } + }, + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l7": { + "route": { + "name": "default/local/default/api-app" + }, + "statPrefix": "upstream." + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp2.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp2.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 8081, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + } + ] + } + ], + "routes": { + "default/local/default/api-app": { + "virtualHosts": [ + { + "name": "default/local/default/api-app", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + } + }, + "endpoints": { + "tcp.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "http.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden new file mode 100644 index 000000000000..b4e04bd09919 --- /dev/null +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden @@ -0,0 +1,255 @@ +{ + "clusters": { + "http.api-app.default.dc1.internal.foo.consul": { + "altStatName": "http.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~http" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "http.api-app.default.dc1.internal.foo.consul" + }, + "original-destination": { + "endpointGroup": { + "passthrough": { + "config": { + "connectTimeout": "5s" + } + } + }, + "name": "original-destination" + }, + "tcp.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "tcp2.api-app.default.dc1.internal.foo.consul": { + "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", + "endpointGroup": { + "dynamic": { + "config": { + "connectTimeout": "5s", + "disablePanicThreshold": true + }, + "outboundTls": { + "alpnProtocols": [ + "consul~tcp2" + ], + "outboundMesh": { + "identityKey": "test-identity", + "sni": "api-app.default.dc1.internal.foo.consul", + "validationContext": { + "spiffeIds": [ + "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" + ], + "trustBundlePeerNameKey": "local" + } + } + } + } + }, + "name": "tcp2.api-app.default.dc1.internal.foo.consul" + } + }, + "identity": { + "name": "test-identity", + "tenancy": { + "namespace": "default", + "partition": "default", + "peerName": "local" + }, + "type": { + "group": "auth", + "groupVersion": "v2beta1", + "kind": "WorkloadIdentity" + } + }, + "listeners": [ + { + "capabilities": [ + "CAPABILITY_TRANSPARENT" + ], + "defaultRouter": { + "l4": { + "cluster": { + "name": "original-destination" + }, + "statPrefix": "upstream.original-destination" + } + }, + "direction": "DIRECTION_OUTBOUND", + "hostPort": { + "host": "127.0.0.1", + "port": 15001 + }, + "name": "outbound_listener", + "routers": [ + { + "l4": { + "cluster": { + "name": "tcp.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 7070, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l7": { + "route": { + "name": "default/local/default/api-app" + }, + "statPrefix": "upstream." + }, + "match": { + "destinationPort": 8080, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + }, + { + "l4": { + "cluster": { + "name": "tcp2.api-app.default.dc1.internal.foo.consul" + }, + "statPrefix": "upstream.tcp2.api-app.default.default.dc1" + }, + "match": { + "destinationPort": 8081, + "prefixRanges": [ + { + "addressPrefix": "1.1.1.1", + "prefixLen": 32 + } + ] + } + } + ] + } + ], + "routes": { + "default/local/default/api-app": { + "virtualHosts": [ + { + "name": "default/local/default/api-app", + "routeRules": [ + { + "destination": { + "cluster": { + "name": "http.api-app.default.dc1.internal.foo.consul" + } + }, + "match": { + "pathMatch": { + "prefix": "/" + } + } + } + ] + } + ] + } + }, + "endpoints": { + "tcp.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "tcp2.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + }, + "http.api-app.default.dc1.internal.foo.consul": { + "endpoints": [ + { + "healthStatus": "HEALTH_STATUS_HEALTHY", + "hostPort": { + "host": "10.1.1.1", + "port": 20000 + } + } + ] + } + }, + "trustBundles": { + "local": { + "roots": [ + "some-root", + "some-other-root" + ], + "trustDomain": "some-trust-domain" + } + }, + "leafCertificates": { + "test-identity": { + "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", + "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" + } + } +} \ No newline at end of file From 88221094f6de80c2d08ccc2de4e3919470eec9fe Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 15:30:13 -0600 Subject: [PATCH 07/14] proposed fix for failover group naming errors --- .../controllers/sidecarproxy/builder/destinations.go | 1 - .../mesh/internal/controllers/xds/controller_test.go | 3 +-- .../testdata/destination/mixed-multi-destination.golden | 9 +++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go index 6031d72cfd96..ac6015a73835 100644 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go +++ b/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go @@ -290,7 +290,6 @@ func (b *Builder) buildDestination( clusterName := fmt.Sprintf("%s.%s", portName, sni) egName := "" - if details.FailoverConfig != nil { egName = fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, 0, clusterName) } diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 8476b87c8c50..ae5535e35589 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1012,8 +1012,7 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( "destination/l4-multi-destination", "destination/l4-multiple-implicit-destinations-tproxy", "destination/l4-implicit-and-explicit-destinations-tproxy", - // TODO(jm): resolve the endpoint group naming issue - //"destination/mixed-multi-destination", + "destination/mixed-multi-destination", "destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy", "destination/multiport-l4-and-l7-single-implicit-destination-tproxy", "destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy", diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden index 7c5cab23d23a..3c227e99dae4 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden @@ -29,7 +29,8 @@ } } } - } + }, + "name": "failover-target~0~http.api-1.default.dc1.internal.foo.consul" }, { "dynamic": { @@ -53,7 +54,7 @@ } } }, - "name": "failover-target~0~http.api-1.default.dc1.internal.foo.consul" + "name": "failover-target~1~http.api-1.default.dc1.internal.foo.consul" } ] }, @@ -330,7 +331,7 @@ } ] }, - "tcp2.api-1.default.dc1.internal.foo.consul": { + "http.api-1.default.dc1.internal.foo.consul": { "endpoints": [ { "healthStatus": "HEALTH_STATUS_HEALTHY", @@ -341,7 +342,7 @@ } ] }, - "tcp2.api-2.default.dc1.internal.foo.consul": { + "http.api-2.default.dc1.internal.foo.consul": { "endpoints": [ { "healthStatus": "HEALTH_STATUS_HEALTHY", From 6a1e6c346e86522768fe3fb3911b2d3f1516dd8d Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 16:18:44 -0600 Subject: [PATCH 08/14] clean up test to use helper. --- .../controllers/xds/controller_test.go | 122 ++++++++++-------- 1 file changed, 65 insertions(+), 57 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index ae5535e35589..eb406ec423f2 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1027,71 +1027,23 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( pst := JSONToProxyTemplate(suite.T(), golden.GetBytesAtFilePath(suite.T(), fmt.Sprintf("%s/%s.golden", path, name))) - //get service data - serviceData := &pbcatalog.Service{} - var vp uint32 = 7000 - requiredEps := make(map[string]*pbproxystate.EndpointRef) - - // get service name and ports - for name := range pst.ProxyState.Clusters { - if name == "null_route_cluster" || name == "original-destination" { - continue - } - vp++ - nameSplit := strings.Split(name, ".") - port := nameSplit[0] - svcName := nameSplit[1] - serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ - TargetPort: port, - VirtualPort: vp, - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }) - - svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(svc.Id). - Write(suite.T(), suite.client) - requiredEps[name] = &pbproxystate.EndpointRef{ - Id: eps.Id, - Port: "mesh", - } - } - - wiLeafs := make(map[string]*pbproxystate.LeafCertificateRef) - wiLeafs["wi-workload-identity"] = &pbproxystate.LeafCertificateRef{ - Name: "wi-workload-identity", + // Destinations will need endpoint refs set up. + proxyType := strings.Split(name, "/")[0] + if proxyType == "destination" && len(pst.ProxyState.Endpoints) == 0 { + suite.addRequiredEndpointsAndRefs(pst, proxyType) } - pst.RequiredEndpoints = requiredEps - - // Store the initial ProxyStateTemplate and track it in the mapper. + // Store the initial ProxyStateTemplate. proxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test"). WithData(suite.T(), pst). Write(suite.T(), suite.client) + // Check with resource service that it exists. retry.Run(suite.T(), func(r *retry.R) { suite.client.RequireResourceExists(r, proxyStateTemplate.Id) }) + // Track it in the mapper. suite.mapper.TrackItem(proxyStateTemplate.Id, []resource.ReferenceOrID{}) // Run the reconcile, and since no ProxyStateTemplate is stored, this simulates a deletion. @@ -1099,9 +1051,9 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( ID: proxyStateTemplate.Id, }) require.NoError(suite.T(), err) - require.NotNil(suite.T(), proxyStateTemplate) + // Get the reconciled proxyStateTemplate to check the reconcile results. reconciledPS := suite.updater.Get(proxyStateTemplate.Id.Name) // Verify leaf cert contents then hard code them for comparison @@ -1114,14 +1066,70 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( }, } + // Compare actual vs expected. actual := prototest.ProtoToJSON(suite.T(), reconciledPS) expected := golden.Get(suite.T(), actual, name+".golden") - require.JSONEq(suite.T(), expected, actual) }) } } +func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.ProxyStateTemplate, proxyType string) { + //get service data + serviceData := &pbcatalog.Service{} + var vp uint32 = 7000 + requiredEps := make(map[string]*pbproxystate.EndpointRef) + + // get service name and ports + for clusterName := range pst.ProxyState.Clusters { + if clusterName == "null_route_cluster" || clusterName == "original-destination" { + continue + } + vp++ + separator := "." + if proxyType == "source" { + separator = ":" + } + clusterNameSplit := strings.Split(clusterName, separator) + port := clusterNameSplit[0] + svcName := clusterNameSplit[1] + serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ + TargetPort: port, + VirtualPort: vp, + Protocol: pbcatalog.Protocol_PROTOCOL_TCP, + }) + + svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). + WithData(suite.T(), &pbcatalog.Service{}). + Write(suite.T(), suite.client) + + eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ + { + Ports: map[string]*pbcatalog.WorkloadPort{ + "mesh": { + Port: 20000, + Protocol: pbcatalog.Protocol_PROTOCOL_MESH, + }, + }, + Addresses: []*pbcatalog.WorkloadAddress{ + { + Host: "10.1.1.1", + Ports: []string{"mesh"}, + }, + }, + }, + }}). + WithOwner(svc.Id). + Write(suite.T(), suite.client) + requiredEps[clusterName] = &pbproxystate.EndpointRef{ + Id: eps.Id, + Port: "mesh", + } + } + + pst.RequiredEndpoints = requiredEps +} func JSONToProxyTemplate(t *testing.T, json []byte) *pbmesh.ProxyStateTemplate { t.Helper() proxyTemplate := &pbmesh.ProxyStateTemplate{} From f8c81b61208fd6cc8c6c8caf05aa8dff78ba301a Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 16:18:44 -0600 Subject: [PATCH 09/14] clean up test to use helper. --- .../controllers/xds/controller_test.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index eb406ec423f2..7d5076573fb8 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1080,11 +1080,16 @@ func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.Pro var vp uint32 = 7000 requiredEps := make(map[string]*pbproxystate.EndpointRef) +<<<<<<< HEAD // get service name and ports +======= + // iterate through clusters and set up endpoints for cluster/mesh port. +>>>>>>> 158caa2516 (clean up test to use helper.) for clusterName := range pst.ProxyState.Clusters { if clusterName == "null_route_cluster" || clusterName == "original-destination" { continue } +<<<<<<< HEAD vp++ separator := "." if proxyType == "source" { @@ -1093,16 +1098,33 @@ func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.Pro clusterNameSplit := strings.Split(clusterName, separator) port := clusterNameSplit[0] svcName := clusterNameSplit[1] +======= + //increment the random port number. + vp++ + clusterNameSplit := strings.Split(clusterName, ".") + port := clusterNameSplit[0] + svcName := clusterNameSplit[1] + + // set up service data with port info. +>>>>>>> 158caa2516 (clean up test to use helper.) serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ TargetPort: port, VirtualPort: vp, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, }) +<<<<<<< HEAD +======= + // create service. +>>>>>>> 158caa2516 (clean up test to use helper.) svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). WithData(suite.T(), &pbcatalog.Service{}). Write(suite.T(), suite.client) +<<<<<<< HEAD +======= + // create endpoints with svc as owner. +>>>>>>> 158caa2516 (clean up test to use helper.) eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ { @@ -1122,14 +1144,18 @@ func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.Pro }}). WithOwner(svc.Id). Write(suite.T(), suite.client) + + // add to working list of required endpoints. requiredEps[clusterName] = &pbproxystate.EndpointRef{ Id: eps.Id, Port: "mesh", } } + // set working list of required endpoints as proxy state's RequiredEndpoints. pst.RequiredEndpoints = requiredEps } + func JSONToProxyTemplate(t *testing.T, json []byte) *pbmesh.ProxyStateTemplate { t.Helper() proxyTemplate := &pbmesh.ProxyStateTemplate{} From ec5af3c8963f0d85cfc60dbac50652b24af42755 Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 16:58:31 -0600 Subject: [PATCH 10/14] fix test file --- .../controllers/xds/controller_test.go | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 7d5076573fb8..3366cfbe1d56 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1080,25 +1080,12 @@ func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.Pro var vp uint32 = 7000 requiredEps := make(map[string]*pbproxystate.EndpointRef) -<<<<<<< HEAD - // get service name and ports -======= // iterate through clusters and set up endpoints for cluster/mesh port. ->>>>>>> 158caa2516 (clean up test to use helper.) for clusterName := range pst.ProxyState.Clusters { if clusterName == "null_route_cluster" || clusterName == "original-destination" { continue } -<<<<<<< HEAD - vp++ - separator := "." - if proxyType == "source" { - separator = ":" - } - clusterNameSplit := strings.Split(clusterName, separator) - port := clusterNameSplit[0] - svcName := clusterNameSplit[1] -======= + //increment the random port number. vp++ clusterNameSplit := strings.Split(clusterName, ".") @@ -1106,25 +1093,18 @@ func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.Pro svcName := clusterNameSplit[1] // set up service data with port info. ->>>>>>> 158caa2516 (clean up test to use helper.) serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ TargetPort: port, VirtualPort: vp, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, }) -<<<<<<< HEAD -======= // create service. ->>>>>>> 158caa2516 (clean up test to use helper.) svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). WithData(suite.T(), &pbcatalog.Service{}). Write(suite.T(), suite.client) -<<<<<<< HEAD -======= // create endpoints with svc as owner. ->>>>>>> 158caa2516 (clean up test to use helper.) eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ { From 854a6e16aba71089a22e871c8ef7e03c559d775e Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 17:07:59 -0600 Subject: [PATCH 11/14] add docstring for test function. --- .../internal/controllers/xds/controller_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 3366cfbe1d56..2061d3a240f2 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1002,6 +1002,19 @@ func TestXdsController(t *testing.T) { suite.Run(t, new(xdsControllerTestSuite)) } +// TestReconcile_SidecarProxyGoldenFileInputs tests the Reconcile() by using +// the golden test output/expected files from the sidecar proxy tests as inputs +// to the XDS controller reconciliation. +// XDS controller reconciles the full ProxyStateTemplate object. The fields +// that things that it focuses on are leaf certs, endpoints, and trust bundles, +// which is just a subset of the ProxyStateTemplate struct. Prior to XDS controller +// reconciliation, the sidecar proxy controller will have reconciled the other parts +// of the ProxyStateTempalte. +// Since the XDS controller does act on the ProxyStateTemplate, the tests +// utilize that entire object rather than just the parts that XDS controller +// internals reconciles. Namely, by using checking the full ProxyStateTemplate +// rather than just endpoints,leafs, and trust bundles, the test also ensures +// side effects or change in scope to XDS controller are not introduce mistakenly. func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs() { path := "../sidecarproxy/builder/testdata" cases := []string{ From 2b01f73e4e846c46a3592b7a23c4c1025c65eb51 Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 17:07:59 -0600 Subject: [PATCH 12/14] add docstring for test function. --- .../mesh/internal/controllers/xds/controller_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index 2061d3a240f2..b48309bc435a 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -8,12 +8,13 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "strings" + "testing" + "github.com/hashicorp/consul/internal/testing/golden" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "google.golang.org/protobuf/encoding/protojson" - "strings" - "testing" svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/agent/leafcert" @@ -1009,11 +1010,11 @@ func TestXdsController(t *testing.T) { // that things that it focuses on are leaf certs, endpoints, and trust bundles, // which is just a subset of the ProxyStateTemplate struct. Prior to XDS controller // reconciliation, the sidecar proxy controller will have reconciled the other parts -// of the ProxyStateTempalte. +// of the ProxyStateTemplate. // Since the XDS controller does act on the ProxyStateTemplate, the tests // utilize that entire object rather than just the parts that XDS controller // internals reconciles. Namely, by using checking the full ProxyStateTemplate -// rather than just endpoints,leafs, and trust bundles, the test also ensures +// rather than just endpoints, leaf certs, and trust bundles, the test also ensures // side effects or change in scope to XDS controller are not introduce mistakenly. func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs() { path := "../sidecarproxy/builder/testdata" From b5fa4f29c8f606ee91f0f6df35462564d1521070 Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 16 Oct 2023 19:34:37 -0600 Subject: [PATCH 13/14] fix linting error --- internal/mesh/internal/controllers/xds/controller_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go index b48309bc435a..21b71b8a8c3f 100644 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ b/internal/mesh/internal/controllers/xds/controller_test.go @@ -1042,9 +1042,8 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( golden.GetBytesAtFilePath(suite.T(), fmt.Sprintf("%s/%s.golden", path, name))) // Destinations will need endpoint refs set up. - proxyType := strings.Split(name, "/")[0] - if proxyType == "destination" && len(pst.ProxyState.Endpoints) == 0 { - suite.addRequiredEndpointsAndRefs(pst, proxyType) + if strings.Split(name, "/")[0] == "destination" && len(pst.ProxyState.Endpoints) == 0 { + suite.addRequiredEndpointsAndRefs(pst) } // Store the initial ProxyStateTemplate. @@ -1088,7 +1087,7 @@ func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs( } } -func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.ProxyStateTemplate, proxyType string) { +func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.ProxyStateTemplate) { //get service data serviceData := &pbcatalog.Service{} var vp uint32 = 7000 From e7ff94b3a6cdc04a9d31f14781ef39d6ab309c48 Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 23 Oct 2023 20:39:48 -0600 Subject: [PATCH 14/14] fixing test after route fix merged into main --- .../destination/mixed-multi-destination.golden | 1 + ...l7-multiple-implicit-destinations-tproxy.golden | 14 ++++++++------ ...nd-l7-single-implicit-destination-tproxy.golden | 7 ++++--- ...stination-with-multiple-workloads-tproxy.golden | 7 ++++--- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden index 3c227e99dae4..78953c017b95 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden @@ -238,6 +238,7 @@ "default/local/default/api-1:http:1.1.1.1:1234": { "virtualHosts": [ { + "domains": ["*"], "name": "default/local/default/api-1:http:1.1.1.1:1234", "routeRules": [ { diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden index 47911d19a9c9..900eb95744b0 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden @@ -247,7 +247,7 @@ { "l7": { "route": { - "name": "default/local/default/api-app" + "name": "default/local/default/api-app:http" }, "statPrefix": "upstream." }, @@ -264,7 +264,7 @@ { "l7": { "route": { - "name": "default/local/default/api-app2" + "name": "default/local/default/api-app2:http" }, "statPrefix": "upstream." }, @@ -324,10 +324,11 @@ } ], "routes": { - "default/local/default/api-app": { + "default/local/default/api-app:http": { "virtualHosts": [ { - "name": "default/local/default/api-app", + "domains": ["*"], + "name": "default/local/default/api-app:http", "routeRules": [ { "destination": { @@ -345,10 +346,11 @@ } ] }, - "default/local/default/api-app2": { + "default/local/default/api-app2:http": { "virtualHosts": [ { - "name": "default/local/default/api-app2", + "domains": ["*"], + "name": "default/local/default/api-app2:http", "routeRules": [ { "destination": { diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden index b4e04bd09919..3647d43cab6f 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden @@ -145,7 +145,7 @@ { "l7": { "route": { - "name": "default/local/default/api-app" + "name": "default/local/default/api-app:http" }, "statPrefix": "upstream." }, @@ -180,10 +180,11 @@ } ], "routes": { - "default/local/default/api-app": { + "default/local/default/api-app:http": { "virtualHosts": [ { - "name": "default/local/default/api-app", + "domains": ["*"], + "name": "default/local/default/api-app:http", "routeRules": [ { "destination": { diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden index b4e04bd09919..3647d43cab6f 100644 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden @@ -145,7 +145,7 @@ { "l7": { "route": { - "name": "default/local/default/api-app" + "name": "default/local/default/api-app:http" }, "statPrefix": "upstream." }, @@ -180,10 +180,11 @@ } ], "routes": { - "default/local/default/api-app": { + "default/local/default/api-app:http": { "virtualHosts": [ { - "name": "default/local/default/api-app", + "domains": ["*"], + "name": "default/local/default/api-app:http", "routeRules": [ { "destination": {