From d0905db23a6cd063e7e31f0f278be675c3e9d3c1 Mon Sep 17 00:00:00 2001 From: Jakub Dyszkiewicz Date: Wed, 12 Feb 2020 13:16:32 +0100 Subject: [PATCH] gateway metrics --- api/mesh/v1alpha1/dataplane_helpers.go | 64 +++++++++-- api/mesh/v1alpha1/dataplane_helpers_test.go | 104 +++++++++++++++++- pkg/core/permissions/matcher.go | 19 ++-- pkg/core/permissions/matcher_test.go | 15 ++- .../resources/apis/mesh/dataplane_helpers.go | 24 ++-- .../apis/mesh/dataplane_helpers_test.go | 15 ++- pkg/mads/reconcile/snapshot_generator_test.go | 6 +- .../k8s/controllers/pod_controller_test.go | 14 ++- .../k8s/controllers/pod_converter.go | 16 +-- .../k8s/controllers/pod_converter_test.go | 33 ++++-- .../generator/inbound_proxy_generator_test.go | 6 +- .../outbound_proxy_generator_test.go | 2 +- pkg/xds/generator/proxy_template.go | 15 ++- pkg/xds/server/snapshot_generator_test.go | 6 +- pkg/xds/topology/outbound.go | 16 +-- 15 files changed, 270 insertions(+), 85 deletions(-) diff --git a/api/mesh/v1alpha1/dataplane_helpers.go b/api/mesh/v1alpha1/dataplane_helpers.go index 132064ab2c06..2372b554fe63 100644 --- a/api/mesh/v1alpha1/dataplane_helpers.go +++ b/api/mesh/v1alpha1/dataplane_helpers.go @@ -128,6 +128,33 @@ func ParseOutboundInterface(text string) (OutboundInterface, error) { }, nil } +func (n *Dataplane_Networking) GetOutboundInterfaces() ([]OutboundInterface, error) { + if n == nil { + return nil, nil + } + ofaces := make([]OutboundInterface, len(n.Outbound)) + for i, outbound := range n.Outbound { + if outbound.Interface != "" { // legacy format + oface, err := ParseOutboundInterface(outbound.Interface) + if err != nil { + return nil, err + } + ofaces[i] = oface + } else { + oface := OutboundInterface{ + DataplanePort: outbound.Port, + } + if outbound.Address != "" { + oface.DataplaneIP = outbound.Address + } else { + oface.DataplaneIP = "127.0.0.1" + } + ofaces[i] = oface + } + } + return ofaces, nil +} + func ParsePort(text string) (uint32, error) { port, err := strconv.ParseUint(text, 10, 32) if err != nil { @@ -147,15 +174,15 @@ func ParseIP(text string) (string, error) { } func (n *Dataplane_Networking) GetInboundInterface(service string) (*InboundInterface, error) { - for _, inbound := range n.Inbound { + ifaces, err := n.GetInboundInterfaces() + if err != nil { + return nil, err + } + for i, inbound := range n.Inbound { if inbound.Tags[ServiceTag] != service { continue } - iface, err := ParseInboundInterface(inbound.Interface) - if err != nil { - return nil, err - } - return &iface, nil + return &ifaces[i], nil } return nil, errors.Errorf("Dataplane has no Inbound Interface for service %q", service) } @@ -166,11 +193,28 @@ func (n *Dataplane_Networking) GetInboundInterfaces() ([]InboundInterface, error } ifaces := make([]InboundInterface, len(n.Inbound)) for i, inbound := range n.Inbound { - iface, err := ParseInboundInterface(inbound.Interface) - if err != nil { - return nil, err + if inbound.Interface != "" { + iface, err := ParseInboundInterface(inbound.Interface) + if err != nil { + return nil, err + } + ifaces[i] = iface + } else { + iface := InboundInterface{ + DataplanePort: inbound.Port, + } + if inbound.Address != "" { + iface.DataplaneIP = inbound.Address + } else { + iface.DataplaneIP = n.Address + } + if inbound.ServicePort != 0 { + iface.WorkloadPort = inbound.ServicePort + } else { + iface.WorkloadPort = inbound.Port + } + ifaces[i] = iface } - ifaces[i] = iface } return ifaces, nil } diff --git a/api/mesh/v1alpha1/dataplane_helpers_test.go b/api/mesh/v1alpha1/dataplane_helpers_test.go index 5f3f6d28a3d4..4dca333e5871 100644 --- a/api/mesh/v1alpha1/dataplane_helpers_test.go +++ b/api/mesh/v1alpha1/dataplane_helpers_test.go @@ -319,6 +319,89 @@ var _ = Describe("ParseOutboundInterface(..)", func() { var _ = Describe("Dataplane_Networking", func() { + Describe("GetOutboundInterfaces()", func() { + Context("valid input values", func() { + type testCase struct { + input *Dataplane_Networking + expected []OutboundInterface + } + + DescribeTable("should parse valid input values", + func(given testCase) { + // when + ofaces, err := given.input.GetOutboundInterfaces() + // then + Expect(err).ToNot(HaveOccurred()) + // and + Expect(ofaces).To(Equal(given.expected)) + }, + Entry("nil", testCase{ + input: nil, + expected: nil, + }), + Entry("empty", testCase{ + input: &Dataplane_Networking{}, + expected: []OutboundInterface{}, + }), + Entry("legacy - 2 outbound interfaces", testCase{ + input: &Dataplane_Networking{ + Outbound: []*Dataplane_Networking_Outbound{ + {Interface: ":8080"}, + {Interface: "192.168.0.1:443"}, + }, + }, + expected: []OutboundInterface{ + {DataplaneIP: "127.0.0.1", DataplanePort: 8080}, + {DataplaneIP: "192.168.0.1", DataplanePort: 443}, + }, + }), + Entry("2 outbound interfaces", testCase{ + input: &Dataplane_Networking{ + Outbound: []*Dataplane_Networking_Outbound{ + { + Port: 8080, + }, + { + Address: "192.168.0.1", + Port: 443, + }, + }, + }, + expected: []OutboundInterface{ + {DataplaneIP: "127.0.0.1", DataplanePort: 8080}, + {DataplaneIP: "192.168.0.1", DataplanePort: 443}, + }, + }), + ) + }) + + Context("invalid input values", func() { + type testCase struct { + input *Dataplane_Networking + expectedErr gomega_types.GomegaMatcher + } + + DescribeTable("should fail on invalid input values", + func(given testCase) { + // when + ifaces, err := given.input.GetOutboundInterfaces() + // then + Expect(ifaces).To(BeNil()) + // and + Expect(err.Error()).To(given.expectedErr) + }, + Entry("dataplane IP address is missing", testCase{ + input: &Dataplane_Networking{ + Outbound: []*Dataplane_Networking_Outbound{ + {Interface: ":443:8443"}, + }, + }, + expectedErr: Equal(`invalid format: expected "[ IPv4 | '[' IPv6 ']' ] ':' DATAPLANE_PORT", got ":443:8443"`), + }), + ) + }) + }) + Describe("GetInboundInterfaces()", func() { Context("valid input values", func() { @@ -344,7 +427,7 @@ var _ = Describe("Dataplane_Networking", func() { input: &Dataplane_Networking{}, expected: []InboundInterface{}, }), - Entry("2 inbound interfaces", testCase{ + Entry("legacy - 2 inbound interfaces", testCase{ input: &Dataplane_Networking{ Inbound: []*Dataplane_Networking_Inbound{ {Interface: "192.168.0.1:80:8080"}, @@ -356,6 +439,25 @@ var _ = Describe("Dataplane_Networking", func() { {DataplaneIP: "192.168.0.1", DataplanePort: 443, WorkloadPort: 8443}, }, }), + Entry("2 inbound interfaces", testCase{ + input: &Dataplane_Networking{ + Address: "192.168.0.1", + Inbound: []*Dataplane_Networking_Inbound{ + { + Port: 80, + }, + { + Address: "192.168.0.1", + Port: 443, + ServicePort: 8443, + }, + }, + }, + expected: []InboundInterface{ + {DataplaneIP: "192.168.0.1", DataplanePort: 80, WorkloadPort: 80}, + {DataplaneIP: "192.168.0.1", DataplanePort: 443, WorkloadPort: 8443}, + }, + }), ) }) diff --git a/pkg/core/permissions/matcher.go b/pkg/core/permissions/matcher.go index 7700f02d06c3..26c2f1b1f663 100644 --- a/pkg/core/permissions/matcher.go +++ b/pkg/core/permissions/matcher.go @@ -12,9 +12,9 @@ type TrafficPermissionsMatcher struct { ResourceManager manager.ResourceManager } -type MatchedPermissions map[string]*mesh_core.TrafficPermissionResourceList +type MatchedPermissions map[mesh_proto.InboundInterface]*mesh_core.TrafficPermissionResourceList -func (m MatchedPermissions) Get(inbound string) *mesh_core.TrafficPermissionResourceList { +func (m MatchedPermissions) Get(inbound mesh_proto.InboundInterface) *mesh_core.TrafficPermissionResourceList { matched, ok := m[inbound] if ok { return matched @@ -28,24 +28,27 @@ func (m *TrafficPermissionsMatcher) Match(ctx context.Context, dataplane *mesh_c if err := m.ResourceManager.List(ctx, permissions, store.ListByMesh(dataplane.GetMeta().GetMesh())); err != nil { return nil, err } - return MatchDataplaneTrafficPermissions(&dataplane.Spec, permissions), nil + return MatchDataplaneTrafficPermissions(&dataplane.Spec, permissions) } -func MatchDataplaneTrafficPermissions(dataplane *mesh_proto.Dataplane, permissions *mesh_core.TrafficPermissionResourceList) MatchedPermissions { +func MatchDataplaneTrafficPermissions(dataplane *mesh_proto.Dataplane, permissions *mesh_core.TrafficPermissionResourceList) (MatchedPermissions, error) { matchedPermissions := make(MatchedPermissions) - for _, inbound := range dataplane.GetNetworking().GetInbound() { - matchedPermissions[inbound.Interface] = &mesh_core.TrafficPermissionResourceList{ + ifaces, err := dataplane.GetNetworking().GetInboundInterfaces() + if err != nil { + return nil, err + } + for i, inbound := range dataplane.GetNetworking().GetInbound() { + matchedPermissions[ifaces[i]] = &mesh_core.TrafficPermissionResourceList{ Items: matchInbound(inbound, permissions), } } - return matchedPermissions + return matchedPermissions, nil } func matchInbound(inbound *mesh_proto.Dataplane_Networking_Inbound, trafficPermissions *mesh_core.TrafficPermissionResourceList) []*mesh_core.TrafficPermissionResource { matchedPerms := []*mesh_core.TrafficPermissionResource{} for _, perm := range trafficPermissions.Items { if len(perm.Spec.Sources) == 0 { - // todo(jakubdyszkiewicz) there shouldn't be any rule with 0 sources. Move to validation logic in a manager continue } for _, dest := range perm.Spec.Destinations { diff --git a/pkg/core/permissions/matcher_test.go b/pkg/core/permissions/matcher_test.go index cf0966d824d2..b9eed88b0926 100644 --- a/pkg/core/permissions/matcher_test.go +++ b/pkg/core/permissions/matcher_test.go @@ -145,10 +145,15 @@ var _ = Describe("Matcher", func() { } // when - matchedPerms := MatchDataplaneTrafficPermissions(&dataplane, &permissions) + matchedPerms, err := MatchDataplaneTrafficPermissions(&dataplane, &permissions) // then - backendMatches := matchedPerms.Get("192.168.0.1:8080:80") + Expect(err).ToNot(HaveOccurred()) + backendMatches := matchedPerms.Get(mesh_proto.InboundInterface{ + DataplaneIP: "192.168.0.1", + DataplanePort: 8080, + WorkloadPort: 80, + }) expectedBackendMatches := core_mesh.TrafficPermissionResourceList{ Items: []*core_mesh.TrafficPermissionResource{ { @@ -204,7 +209,11 @@ var _ = Describe("Matcher", func() { }, }, } - webMatches := matchedPerms.Get("192.168.0.1:8090:90") + webMatches := matchedPerms.Get(mesh_proto.InboundInterface{ + DataplaneIP: "192.168.0.1", + DataplanePort: 8090, + WorkloadPort: 90, + }) Expect(*webMatches).To(Equal(expectedWebMatches)) }) }) diff --git a/pkg/core/resources/apis/mesh/dataplane_helpers.go b/pkg/core/resources/apis/mesh/dataplane_helpers.go index be4357446c3c..04ac314b4b3e 100644 --- a/pkg/core/resources/apis/mesh/dataplane_helpers.go +++ b/pkg/core/resources/apis/mesh/dataplane_helpers.go @@ -56,11 +56,11 @@ func (d *DataplaneResource) UsesInboundInterface(address net.IP, port uint32) bo if d == nil { return false } - for _, inbound := range d.Spec.Networking.GetInbound() { - iface, err := mesh_proto.ParseInboundInterface(inbound.Interface) - if err != nil { - continue - } + ifaces, err := d.Spec.Networking.GetInboundInterfaces() + if err != nil { + return false + } + for _, iface := range ifaces { // compare against port and IP address of the dataplane if port == iface.DataplanePort && overlap(address, net.ParseIP(iface.DataplaneIP)) { return true @@ -77,11 +77,11 @@ func (d *DataplaneResource) UsesOutboundInterface(address net.IP, port uint32) b if d == nil { return false } - for _, outbound := range d.Spec.Networking.GetOutbound() { - oface, err := mesh_proto.ParseOutboundInterface(outbound.Interface) - if err != nil { - continue - } + ofaces, err := d.Spec.Networking.GetOutboundInterfaces() + if err != nil { + return false + } + for _, oface := range ofaces { // compare against port and IP address of the dataplane if port == oface.DataplanePort && overlap(address, net.ParseIP(oface.DataplaneIP)) { return true @@ -113,6 +113,10 @@ func (d *DataplaneResource) GetIP() string { if d == nil { return "" } + if d.Spec.Networking.Address != "" { + return d.Spec.Networking.Address + } + // fallback to legacy format ifaces, err := d.Spec.Networking.GetInboundInterfaces() if err != nil { return "" diff --git a/pkg/core/resources/apis/mesh/dataplane_helpers_test.go b/pkg/core/resources/apis/mesh/dataplane_helpers_test.go index d5fa25fc3626..ddf48f8b1add 100644 --- a/pkg/core/resources/apis/mesh/dataplane_helpers_test.go +++ b/pkg/core/resources/apis/mesh/dataplane_helpers_test.go @@ -373,7 +373,18 @@ var _ = Describe("Dataplane", func() { `, expected: "", }), - Entry("dataplane with 1 inbound interface", testCase{ + Entry("dataplane with address in networking", testCase{ + dataplane: ` + networking: + address: 192.168.0.1 + inbound: + - port: 8080 + tags: + service: backend +`, + expected: "192.168.0.1", + }), + Entry("legacy - dataplane with 1 inbound interface", testCase{ dataplane: ` networking: inbound: @@ -383,7 +394,7 @@ var _ = Describe("Dataplane", func() { `, expected: "192.168.0.1", }), - Entry("dataplane with 2 inbound interfaces", testCase{ + Entry("legacy - dataplane with 2 inbound interfaces", testCase{ dataplane: ` networking: inbound: diff --git a/pkg/mads/reconcile/snapshot_generator_test.go b/pkg/mads/reconcile/snapshot_generator_test.go index b62524539375..3c18778caef3 100644 --- a/pkg/mads/reconcile/snapshot_generator_test.go +++ b/pkg/mads/reconcile/snapshot_generator_test.go @@ -210,13 +210,13 @@ var _ = Describe("snapshotGenerator", func() { }, Spec: mesh_proto.Dataplane{ Networking: &mesh_proto.Dataplane_Networking{ - Inbound: []*mesh_proto.Dataplane_Networking_Inbound{{ - Interface: "192.168.0.3:3000:3000", + Address: "192.168.0.3", + Gateway: &mesh_proto.Dataplane_Networking_Gateway{ Tags: map[string]string{ "service": "web", "env": "test", }, - }}, + }, }, Metrics: &mesh_proto.Metrics{ Prometheus: &mesh_proto.Metrics_Prometheus{ diff --git a/pkg/plugins/discovery/k8s/controllers/pod_controller_test.go b/pkg/plugins/discovery/k8s/controllers/pod_controller_test.go index 3350cc3c8c1a..c4126626cc95 100644 --- a/pkg/plugins/discovery/k8s/controllers/pod_controller_test.go +++ b/pkg/plugins/discovery/k8s/controllers/pod_controller_test.go @@ -246,12 +246,13 @@ var _ = Describe("PodReconciler", func() { uid: "" spec: networking: + address: 192.168.0.1 inbound: - - interface: 192.168.0.1:8080:8080 + - port: 8080 tags: - service: example.demo.svc:80 protocol: http - - interface: 192.168.0.1:6060:6060 + service: example.demo.svc:80 + - port: 6060 tags: service: example.demo.svc:6061 protocol: tcp @@ -312,12 +313,13 @@ var _ = Describe("PodReconciler", func() { uid: "" spec: networking: + address: 192.168.0.1 inbound: - - interface: 192.168.0.1:8080:8080 + - port: 8080 tags: - service: example.demo.svc:80 protocol: http - - interface: 192.168.0.1:6060:6060 + service: example.demo.svc:80 + - port: 6060 tags: service: example.demo.svc:6061 protocol: tcp diff --git a/pkg/plugins/discovery/k8s/controllers/pod_converter.go b/pkg/plugins/discovery/k8s/controllers/pod_converter.go index 73fed170682d..17554b46d77b 100644 --- a/pkg/plugins/discovery/k8s/controllers/pod_converter.go +++ b/pkg/plugins/discovery/k8s/controllers/pod_converter.go @@ -56,6 +56,7 @@ func DataplaneFor(pod *kube_core.Pod, services []*kube_core.Service, others []*m } } + dataplane.Networking.Address = pod.Status.PodIP if injector_metadata.HasGatewayEnabled(pod) { gateway, err := GatewayFor(pod, services) if err != nil { @@ -107,16 +108,11 @@ func InboundInterfacesFor(pod *kube_core.Pod, services []*kube_core.Service, isG continue } - iface := mesh_proto.InboundInterface{ - DataplaneIP: pod.Status.PodIP, - DataplanePort: uint32(containerPort), - WorkloadPort: uint32(containerPort), - } tags := InboundTagsFor(pod, svc, &svcPort, isGateway) ifaces = append(ifaces, &mesh_proto.Dataplane_Networking_Inbound{ - Interface: iface.String(), - Tags: tags, + Port: uint32(containerPort), + Tags: tags, }) } } @@ -163,10 +159,8 @@ func OutboundInterfacesFor(others []*mesh_k8s.Dataplane, serviceGetter kube_clie dataplanePort := port ofaces = append(ofaces, &mesh_proto.Dataplane_Networking_Outbound{ - Interface: mesh_proto.OutboundInterface{ - DataplaneIP: dataplaneIP, - DataplanePort: dataplanePort, - }.String(), + Address: dataplaneIP, + Port: dataplanePort, Service: serviceTag, }) } diff --git a/pkg/plugins/discovery/k8s/controllers/pod_converter_test.go b/pkg/plugins/discovery/k8s/controllers/pod_converter_test.go index 8fc413908daa..f2f07118bc4c 100644 --- a/pkg/plugins/discovery/k8s/controllers/pod_converter_test.go +++ b/pkg/plugins/discovery/k8s/controllers/pod_converter_test.go @@ -136,7 +136,8 @@ var _ = Describe("PodToDataplane(..)", func() { metadata: creationTimestamp: null spec: - networking: {} + networking: + address: 192.168.0.1 `, }), Entry("Pod with a Service but mismatching ports", testCase{ @@ -186,7 +187,8 @@ var _ = Describe("PodToDataplane(..)", func() { metadata: creationTimestamp: null spec: - networking: {} + networking: + address: 192.168.0.1 `, }), Entry("Pod with 2 Services", testCase{ @@ -257,26 +259,27 @@ var _ = Describe("PodToDataplane(..)", func() { creationTimestamp: null spec: networking: + address: 192.168.0.1 inbound: - - interface: 192.168.0.1:8080:8080 + - port: 8080 tags: app: example protocol: http service: example.demo.svc:80 version: "0.1" - - interface: 192.168.0.1:8443:8443 + - port: 8443 tags: app: example protocol: tcp service: example.demo.svc:443 version: "0.1" - - interface: 192.168.0.1:7070:7070 + - port: 7070 tags: app: example protocol: MONGO service: sample.playground.svc:7071 version: "0.1" - - interface: 192.168.0.1:6060:6060 + - port: 6060 tags: app: example protocol: tcp @@ -315,13 +318,14 @@ var _ = Describe("PodToDataplane(..)", func() { namespace: playground spec: networking: + address: 10.244.0.25 inbound: - - interface: 10.244.0.25:80:80 + - port: 80 tags: app: test-app pod-template-hash: 8646b8bbc8 service: test-app.playground.svc:80 - - interface: 10.244.0.25:443:443 + - port: 443 tags: app: test-app pod-template-hash: 8646b8bbc8 @@ -362,17 +366,20 @@ var _ = Describe("PodToDataplane(..)", func() { creationTimestamp: null spec: networking: + address: 192.168.0.1 inbound: - - interface: 192.168.0.1:8080:8080 + - port: 8080 tags: app: example protocol: tcp service: example.demo.svc:80 version: "0.1" outbound: - - interface: 10.108.144.24:443 + - address: 10.108.144.24 + port: 443 service: test-app.playground.svc:443 - - interface: 10.108.144.24:80 + - address: 10.108.144.24 + port: 80 service: test-app.playground.svc:80 `, }), @@ -415,6 +422,7 @@ var _ = Describe("PodToDataplane(..)", func() { creationTimestamp: null spec: networking: + address: 192.168.0.1 gateway: tags: app: example @@ -430,7 +438,8 @@ var _ = Describe("PodToDataplane(..)", func() { metadata: creationTimestamp: null spec: - networking: {} + networking: + address: 192.168.0.1 `, }), ) diff --git a/pkg/xds/generator/inbound_proxy_generator_test.go b/pkg/xds/generator/inbound_proxy_generator_test.go index 11d0130c283c..6705c4977f92 100644 --- a/pkg/xds/generator/inbound_proxy_generator_test.go +++ b/pkg/xds/generator/inbound_proxy_generator_test.go @@ -60,7 +60,11 @@ var _ = Describe("InboundProxyGenerator", func() { Spec: dataplane, }, TrafficPermissions: permissions.MatchedPermissions{ - "192.168.0.1:80:8080": &mesh_core.TrafficPermissionResourceList{ + mesh_proto.InboundInterface{ + DataplaneIP: "192.168.0.1", + DataplanePort: 80, + WorkloadPort: 8080, + }: &mesh_core.TrafficPermissionResourceList{ Items: []*mesh_core.TrafficPermissionResource{ { Meta: &test_model.ResourceMeta{ diff --git a/pkg/xds/generator/outbound_proxy_generator_test.go b/pkg/xds/generator/outbound_proxy_generator_test.go index acf33f86f291..b266a9298e7b 100644 --- a/pkg/xds/generator/outbound_proxy_generator_test.go +++ b/pkg/xds/generator/outbound_proxy_generator_test.go @@ -391,7 +391,7 @@ var _ = Describe("OutboundProxyGenerator", func() { service: backend `, chaos: noExtraChaos, - expectedErrMatcher: HavePrefix(`dataplane.networking.outbound[0].interface: value is not valid: "127:not-a-port"`), + expectedErrMatcher: HavePrefix(`invalid DATAPLANE_IP in "127:not-a-port": "127" is not a valid IP address`), }), Entry("dataplane with an outbound interface that has no route", testCase{ ctx: plainCtx, diff --git a/pkg/xds/generator/proxy_template.go b/pkg/xds/generator/proxy_template.go index deb990c020a9..6cf566c69d79 100644 --- a/pkg/xds/generator/proxy_template.go +++ b/pkg/xds/generator/proxy_template.go @@ -115,7 +115,7 @@ func (g InboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.Pr Configure(envoy_listeners.InboundListener(inboundListenerName, endpoint.DataplaneIP, endpoint.DataplanePort)). Configure(envoy_listeners.ServerSideMTLS(ctx, proxy.Metadata)). Configure(g.protocolSpecificOpts(service, protocol, envoy_listeners.ClusterInfo{Name: localClusterName})...). - Configure(envoy_listeners.NetworkRBAC(ctx.Mesh.Resource.Spec.GetMtls().GetEnabled(), proxy.TrafficPermissions.Get(endpoint.String()))). + Configure(envoy_listeners.NetworkRBAC(ctx.Mesh.Resource.Spec.GetMtls().GetEnabled(), proxy.TrafficPermissions.Get(endpoint))). Configure(envoy_listeners.TransparentProxying(proxy.Dataplane.Spec.Networking.GetTransparentProxying())). Build() if err != nil { @@ -156,12 +156,11 @@ func (g OutboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.P } resources := &model.ResourceSet{} sourceService := proxy.Dataplane.Spec.GetIdentifyingService() + endpoints, err := proxy.Dataplane.Spec.Networking.GetOutboundInterfaces() + if err != nil { + return nil, err + } for i, oface := range ofaces { - endpoint, err := kuma_mesh.ParseOutboundInterface(oface.Interface) - if err != nil { - return nil, errors.Wrapf(err, "%s: value is not valid: %q", validators.RootedAt("dataplane").Field("networking").Field("outbound").Index(i).Field("interface"), oface.Interface) - } - // pick a route route := proxy.TrafficRoutes[oface.Service] if route == nil { @@ -182,11 +181,11 @@ func (g OutboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.P resources.Add(edsResources...) // generate LDS resource - outboundListenerName := fmt.Sprintf("outbound:%s:%d", endpoint.DataplaneIP, endpoint.DataplanePort) + outboundListenerName := fmt.Sprintf("outbound:%s:%d", endpoints[i].DataplaneIP, endpoints[i].DataplanePort) destinationService := oface.Service listener, err := envoy_listeners.NewListenerBuilder(). - Configure(envoy_listeners.OutboundListener(outboundListenerName, endpoint.DataplaneIP, endpoint.DataplanePort)). + Configure(envoy_listeners.OutboundListener(outboundListenerName, endpoints[i].DataplaneIP, endpoints[i].DataplanePort)). Configure(envoy_listeners.TcpProxy(oface.Service, clusters...)). Configure(envoy_listeners.NetworkAccessLog(sourceService, destinationService, proxy.Logs[oface.Service], proxy)). Configure(envoy_listeners.TransparentProxying(proxy.Dataplane.Spec.Networking.GetTransparentProxying())). diff --git a/pkg/xds/server/snapshot_generator_test.go b/pkg/xds/server/snapshot_generator_test.go index dcfd57be65c6..deac12cba8a4 100644 --- a/pkg/xds/server/snapshot_generator_test.go +++ b/pkg/xds/server/snapshot_generator_test.go @@ -69,7 +69,11 @@ var _ = Describe("Reconcile", func() { Spec: dataplane, }, TrafficPermissions: permissions.MatchedPermissions{ - "192.168.0.1:80:8080": &mesh_core.TrafficPermissionResourceList{ + mesh_proto.InboundInterface{ + DataplaneIP: "192.168.0.1", + DataplanePort: 80, + WorkloadPort: 8080, + }: &mesh_core.TrafficPermissionResourceList{ Items: []*mesh_core.TrafficPermissionResource{ &mesh_core.TrafficPermissionResource{ Meta: &test_model.ResourceMeta{ diff --git a/pkg/xds/topology/outbound.go b/pkg/xds/topology/outbound.go index 3c0f4bf387df..e44fc1aaef66 100644 --- a/pkg/xds/topology/outbound.go +++ b/pkg/xds/topology/outbound.go @@ -29,7 +29,12 @@ func BuildEndpointMap(destinations core_xds.DestinationMap, dataplanes []*mesh_c } outbound := core_xds.EndpointMap{} for _, dataplane := range dataplanes { - for _, inbound := range dataplane.Spec.Networking.GetInbound() { + ifaces, err := dataplane.Spec.Networking.GetInboundInterfaces() + if err != nil { + // skip dataplanes with invalid configuration + continue + } + for i, inbound := range dataplane.Spec.Networking.GetInbound() { service := inbound.Tags[mesh_proto.ServiceTag] selectors, ok := destinations[service] if !ok { @@ -45,16 +50,11 @@ func BuildEndpointMap(destinations core_xds.DestinationMap, dataplanes []*mesh_c if !matches { continue } - iface, err := mesh_proto.ParseInboundInterface(inbound.Interface) - if err != nil { - // skip dataplanes with invalid configuration - continue - } // TODO(yskopets): do we need to dedup? // TODO(yskopets): sort ? outbound[service] = append(outbound[service], core_xds.Endpoint{ - Target: iface.DataplaneIP, - Port: iface.DataplanePort, + Target: ifaces[i].DataplaneIP, + Port: ifaces[i].DataplanePort, Tags: inbound.Tags, }) }