From 53e0f1681dc41c61b3aaea9fa9afd93f16b89d1b Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 10:16:34 +0100 Subject: [PATCH 01/21] targetable: GCRPRoute Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index bd720fd..71a1ccb 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -213,6 +213,25 @@ func (p *ServicePort) Policies() []Policy { return p.attachedPolicies } +type GRPCRoute struct { + *gwapiv1.GRPCRoute + + attachedPolicies []Policy +} + +var _ Targetable = &GRPCRoute{} + +func (r *GRPCRoute) GetURL() string { + return UrlFromObject(r) +} +func (r *GRPCRoute) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *GRPCRoute) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From 79e1fb7ebe5894d324d91647df8c817d34cd774a Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 10:17:05 +0100 Subject: [PATCH 02/21] targetable: GCRPRouteRule Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index 71a1ccb..4331ff1 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -232,6 +232,46 @@ func (r *GRPCRoute) Policies() []Policy { return r.attachedPolicies } +type GRPCRouteRule struct { + *gwapiv1.GRPCRouteRule + + GRPCRoute *GRPCRoute + Name gwapiv1.SectionName // TODO: Use the `name` field of the HTTPRouteRule once it's implemented - https://github.com/kubernetes-sigs/gateway-api/pull/2985 + attachedPolicies []Policy +} + +var _ Targetable = &GRPCRouteRule{} + +func (r *GRPCRouteRule) GroupVersionKind() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: gwapiv1.GroupName, + Version: gwapiv1.GroupVersion.Version, + Kind: "GRPCRouteRule", + } +} + +func (r *GRPCRouteRule) SetGroupVersionKind(schema.GroupVersionKind) {} + +func (r *GRPCRouteRule) GetURL() string { + return namespacedSectionName(UrlFromObject(r.GRPCRoute), r.Name) +} + +func (r *GRPCRouteRule) GetNamespace() string { + return r.GRPCRoute.GetNamespace() +} + +func (r *GRPCRouteRule) GetName() string { + return namespacedSectionName(r.GRPCRoute.Name, r.Name) +} + +func (r *GRPCRouteRule) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *GRPCRouteRule) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From c5517ed36c63062c4ee605b405f731709837a6a4 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 10:38:10 +0100 Subject: [PATCH 03/21] object: ReferenceGrant Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index 4331ff1..53918c8 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -8,6 +8,7 @@ import ( "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) const nameSectionNameURLSeparator = '#' @@ -374,6 +375,18 @@ func (t LocalPolicyTargetReferenceWithSectionName) GetName() string { return namespacedSectionName(string(t.LocalPolicyTargetReference.Name), *t.SectionName) } +// These are wrappers for Gateway API types so instances can be used as objects in the topology. + +type ReferenceGrant struct { + *gwapiv1beta1.ReferenceGrant +} + +var _ Object = &ReferenceGrant{} + +func (o *ReferenceGrant) GetURL() string { + return UrlFromObject(o) +} + func namespacedSectionName(namespace string, sectionName gwapiv1.SectionName) string { return fmt.Sprintf("%s%s%s", namespace, string(nameSectionNameURLSeparator), sectionName) } From 12d082cc0d6f3825644db6b7f4546278c03ef8e9 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 10:54:34 +0100 Subject: [PATCH 04/21] policy: BackendTLSPolicy Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index 53918c8..b06d41f 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -3,11 +3,13 @@ package machinery import ( "fmt" + "github.com/samber/lo" core "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwapiv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" gwapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -387,6 +389,39 @@ func (o *ReferenceGrant) GetURL() string { return UrlFromObject(o) } +// These are wrappers for Gateway API types so instances can be used as policies in the topology. + +type BackendTLSPolicy struct { + *gwapiv1alpha3.BackendTLSPolicy +} + +var _ Policy = &BackendTLSPolicy{} + +func (p *BackendTLSPolicy) GetURL() string { + return UrlFromObject(p) +} + +func (p *BackendTLSPolicy) GetTargetRefs() []PolicyTargetReference { + return lo.Map(p.Spec.TargetRefs, func(item gwapiv1alpha2.LocalPolicyTargetReferenceWithSectionName, _ int) PolicyTargetReference { + return LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReferenceWithSectionName: item, + PolicyNamespace: p.Namespace, + } + }) +} + +func (p *BackendTLSPolicy) GetMergeStrategy() MergeStrategy { + return DefaultMergeStrategy +} + +func (p *BackendTLSPolicy) Merge(other Policy) Policy { + source, ok := other.(*BackendTLSPolicy) + if !ok { + return p + } + return source.GetMergeStrategy()(source, p) +} + func namespacedSectionName(namespace string, sectionName gwapiv1.SectionName) string { return fmt.Sprintf("%s%s%s", namespace, string(nameSectionNameURLSeparator), sectionName) } From 4c39daea80fd966fb1bfca598d8a3bb8290feee3 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:02:04 +0100 Subject: [PATCH 05/21] targetable: TCPRoute Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index b06d41f..a0f9c03 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -239,7 +239,7 @@ type GRPCRouteRule struct { *gwapiv1.GRPCRouteRule GRPCRoute *GRPCRoute - Name gwapiv1.SectionName // TODO: Use the `name` field of the HTTPRouteRule once it's implemented - https://github.com/kubernetes-sigs/gateway-api/pull/2985 + Name gwapiv1.SectionName // TODO: Use the `name` field of the GRPCRouteRule once it's implemented - https://github.com/kubernetes-sigs/gateway-api/pull/2985 attachedPolicies []Policy } @@ -275,6 +275,26 @@ func (r *GRPCRouteRule) Policies() []Policy { return r.attachedPolicies } +type TCPRoute struct { + *gwapiv1alpha2.TCPRoute + + attachedPolicies []Policy +} + +var _ Targetable = &TCPRoute{} + +func (r *TCPRoute) GetURL() string { + return UrlFromObject(r) +} + +func (r *TCPRoute) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *TCPRoute) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From bd1e8c3d93fcbb7f109e03159c78a3e6be5e7d57 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:05:14 +0100 Subject: [PATCH 06/21] targetable: TCPRouteRule Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index a0f9c03..a82ab23 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -295,6 +295,46 @@ func (r *TCPRoute) Policies() []Policy { return r.attachedPolicies } +type TCPRouteRule struct { + *gwapiv1alpha2.TCPRouteRule + + TCPRoute *TCPRoute + Name gwapiv1.SectionName // TODO: Use the `name` field of the TCPRouteRule once it's implemented - https://github.com/kubernetes-sigs/gateway-api/pull/2985 + attachedPolicies []Policy +} + +var _ Targetable = &TCPRouteRule{} + +func (r *TCPRouteRule) GroupVersionKind() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: gwapiv1alpha2.GroupName, + Version: gwapiv1alpha2.GroupVersion.Version, + Kind: "TCPRouteRule", + } +} + +func (r *TCPRouteRule) SetGroupVersionKind(schema.GroupVersionKind) {} + +func (r *TCPRouteRule) GetURL() string { + return namespacedSectionName(UrlFromObject(r.TCPRoute), r.Name) +} + +func (r *TCPRouteRule) GetNamespace() string { + return r.TCPRoute.GetNamespace() +} + +func (r *TCPRouteRule) GetName() string { + return namespacedSectionName(r.TCPRoute.Name, r.Name) +} + +func (r *TCPRouteRule) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *TCPRouteRule) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From 1d17482a8d09fbfe77ebc22f2008743cd31dfe5f Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:10:28 +0100 Subject: [PATCH 07/21] targetable: TLSRoute Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index a82ab23..c515420 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -335,6 +335,26 @@ func (r *TCPRouteRule) Policies() []Policy { return r.attachedPolicies } +type TLSRoute struct { + *gwapiv1alpha2.TLSRoute + + attachedPolicies []Policy +} + +var _ Targetable = &TLSRoute{} + +func (r *TLSRoute) GetURL() string { + return UrlFromObject(r) +} + +func (r *TLSRoute) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *TLSRoute) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From bd41ce5e53e6725712cc10e5fa642ada4ee97652 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:12:42 +0100 Subject: [PATCH 08/21] targetable: TLSRouteRule Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index c515420..a6182d8 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -355,6 +355,46 @@ func (r *TLSRoute) Policies() []Policy { return r.attachedPolicies } +type TLSRouteRule struct { + *gwapiv1alpha2.TLSRouteRule + + TLSRoute *TLSRoute + Name gwapiv1.SectionName // TODO: Use the `name` field of the TLSRouteRule once it's implemented - https://github.com/kubernetes-sigs/gateway-api/pull/2985 + attachedPolicies []Policy +} + +var _ Targetable = &TLSRouteRule{} + +func (r *TLSRouteRule) GroupVersionKind() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: gwapiv1alpha2.GroupName, + Version: gwapiv1alpha2.GroupVersion.Version, + Kind: "TLSRouteRule", + } +} + +func (r *TLSRouteRule) SetGroupVersionKind(schema.GroupVersionKind) {} + +func (r *TLSRouteRule) GetURL() string { + return namespacedSectionName(UrlFromObject(r.TLSRoute), r.Name) +} + +func (r *TLSRouteRule) GetNamespace() string { + return r.TLSRoute.GetNamespace() +} + +func (r *TLSRouteRule) GetName() string { + return namespacedSectionName(r.TLSRoute.Name, r.Name) +} + +func (r *TLSRouteRule) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *TLSRouteRule) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From 2c5b14fb47905b38f3eae66207b479b33182471f Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:13:54 +0100 Subject: [PATCH 09/21] targetable: UCPRoute Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index a6182d8..9f825cd 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -395,6 +395,26 @@ func (r *TLSRouteRule) Policies() []Policy { return r.attachedPolicies } +type UDPRoute struct { + *gwapiv1alpha2.UDPRoute + + attachedPolicies []Policy +} + +var _ Targetable = &UDPRoute{} + +func (r *UDPRoute) GetURL() string { + return UrlFromObject(r) +} + +func (r *UDPRoute) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *UDPRoute) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From 4ac33aab8877aa0ef70784d621207485391bdfd5 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:16:10 +0100 Subject: [PATCH 10/21] targetable: UDPRouteRule Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index 9f825cd..03be70c 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -415,6 +415,46 @@ func (r *UDPRoute) Policies() []Policy { return r.attachedPolicies } +type UDPRouteRule struct { + *gwapiv1alpha2.UDPRouteRule + + UDPRoute *UDPRoute + Name gwapiv1.SectionName // TODO: Use the `name` field of the UDPRouteRule once it's implemented - https://github.com/kubernetes-sigs/gateway-api/pull/2985 + attachedPolicies []Policy +} + +var _ Targetable = &UDPRouteRule{} + +func (r *UDPRouteRule) GroupVersionKind() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: gwapiv1alpha2.GroupName, + Version: gwapiv1alpha2.GroupVersion.Version, + Kind: "UDPRouteRule", + } +} + +func (r *UDPRouteRule) SetGroupVersionKind(schema.GroupVersionKind) {} + +func (r *UDPRouteRule) GetURL() string { + return namespacedSectionName(UrlFromObject(r.UDPRoute), r.Name) +} + +func (r *UDPRouteRule) GetNamespace() string { + return r.UDPRoute.GetNamespace() +} + +func (r *UDPRouteRule) GetName() string { + return namespacedSectionName(r.UDPRoute.Name, r.Name) +} + +func (r *UDPRouteRule) SetPolicies(policies []Policy) { + r.attachedPolicies = policies +} + +func (r *UDPRouteRule) Policies() []Policy { + return r.attachedPolicies +} + // These are Gateway API target reference types that implement the PolicyTargetReference interface, so policies' // targetRef instances can be treated as Objects whose GetURL() functions return the unique identifier of the // corresponding targetable the reference points to. From 1f2e7793dbfd7ecb005dc5dfa70c38f9c144ce0c Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:20:50 +0100 Subject: [PATCH 11/21] policy: BackendLBPolicy Gateway API kind wrapper Signed-off-by: KevFan --- machinery/gateway_api_types.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index 03be70c..b5356a2 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -602,6 +602,37 @@ func (p *BackendTLSPolicy) Merge(other Policy) Policy { return source.GetMergeStrategy()(source, p) } +type BackendLBPolicy struct { + *gwapiv1alpha2.BackendLBPolicy +} + +var _ Policy = &BackendLBPolicy{} + +func (p *BackendLBPolicy) GetURL() string { + return UrlFromObject(p) +} + +func (p *BackendLBPolicy) GetTargetRefs() []PolicyTargetReference { + return lo.Map(p.Spec.TargetRefs, func(item gwapiv1alpha2.LocalPolicyTargetReference, _ int) PolicyTargetReference { + return LocalPolicyTargetReference{ + LocalPolicyTargetReference: item, + PolicyNamespace: p.Namespace, + } + }) +} + +func (p *BackendLBPolicy) GetMergeStrategy() MergeStrategy { + return DefaultMergeStrategy +} + +func (p *BackendLBPolicy) Merge(other Policy) Policy { + source, ok := other.(*BackendLBPolicy) + if !ok { + return p + } + return source.GetMergeStrategy()(source, p) +} + func namespacedSectionName(namespace string, sectionName gwapiv1.SectionName) string { return fmt.Sprintf("%s%s%s", namespace, string(nameSectionNameURLSeparator), sectionName) } From d9d03d4dd6372f84f7fa97faeb9df568c6cf08e0 Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 11:27:52 +0100 Subject: [PATCH 12/21] targetable: Namespace Core API kind wrapper Signed-off-by: KevFan --- machinery/core_types.go | 86 ++++++++++++++++++++++++++++++++++ machinery/gateway_api_types.go | 58 ----------------------- 2 files changed, 86 insertions(+), 58 deletions(-) create mode 100644 machinery/core_types.go diff --git a/machinery/core_types.go b/machinery/core_types.go new file mode 100644 index 0000000..c4a3bf5 --- /dev/null +++ b/machinery/core_types.go @@ -0,0 +1,86 @@ +package machinery + +import ( + core "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// These are wrappers for Core API types so instances can be used as targetables in the topology. + +type Namespace struct { + *core.Namespace + + attachedPolicies []Policy +} + +var _ Targetable = &Namespace{} + +func (n *Namespace) GetURL() string { + return UrlFromObject(n) +} + +func (n *Namespace) SetPolicies(policies []Policy) { + n.attachedPolicies = policies +} + +func (n *Namespace) Policies() []Policy { + return n.attachedPolicies +} + +type Service struct { + *core.Service + + attachedPolicies []Policy +} + +var _ Targetable = &Service{} + +func (s *Service) GetURL() string { + return UrlFromObject(s) +} + +func (s *Service) SetPolicies(policies []Policy) { + s.attachedPolicies = policies +} + +func (s *Service) Policies() []Policy { + return s.attachedPolicies +} + +type ServicePort struct { + *core.ServicePort + + Service *Service + attachedPolicies []Policy +} + +var _ Targetable = &ServicePort{} + +func (p *ServicePort) GroupVersionKind() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Kind: "ServicePort", + } +} + +func (p *ServicePort) SetGroupVersionKind(schema.GroupVersionKind) {} + +func (p *ServicePort) GetURL() string { + return namespacedSectionName(UrlFromObject(p.Service), gwapiv1.SectionName(p.Name)) +} + +func (p *ServicePort) GetNamespace() string { + return p.Service.GetNamespace() +} + +func (p *ServicePort) GetName() string { + return namespacedSectionName(p.Service.Name, gwapiv1.SectionName(p.Name)) +} + +func (p *ServicePort) SetPolicies(policies []Policy) { + p.attachedPolicies = policies +} + +func (p *ServicePort) Policies() []Policy { + return p.attachedPolicies +} diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index b5356a2..b645970 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/samber/lo" - core "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -159,63 +158,6 @@ func (r *HTTPRouteRule) Policies() []Policy { return r.attachedPolicies } -type Service struct { - *core.Service - - attachedPolicies []Policy -} - -var _ Targetable = &Service{} - -func (s *Service) GetURL() string { - return UrlFromObject(s) -} - -func (s *Service) SetPolicies(policies []Policy) { - s.attachedPolicies = policies -} - -func (s *Service) Policies() []Policy { - return s.attachedPolicies -} - -type ServicePort struct { - *core.ServicePort - - Service *Service - attachedPolicies []Policy -} - -var _ Targetable = &ServicePort{} - -func (p *ServicePort) GroupVersionKind() schema.GroupVersionKind { - return schema.GroupVersionKind{ - Kind: "ServicePort", - } -} - -func (p *ServicePort) SetGroupVersionKind(schema.GroupVersionKind) {} - -func (p *ServicePort) GetURL() string { - return namespacedSectionName(UrlFromObject(p.Service), gwapiv1.SectionName(p.Name)) -} - -func (p *ServicePort) GetNamespace() string { - return p.Service.GetNamespace() -} - -func (p *ServicePort) GetName() string { - return namespacedSectionName(p.Service.Name, gwapiv1.SectionName(p.Name)) -} - -func (p *ServicePort) SetPolicies(policies []Policy) { - p.attachedPolicies = policies -} - -func (p *ServicePort) Policies() []Policy { - return p.attachedPolicies -} - type GRPCRoute struct { *gwapiv1.GRPCRoute From c94410c8af8454ee87ed28d698d33ddf14ecddbc Mon Sep 17 00:00:00 2001 From: KevFan Date: Tue, 30 Jul 2024 18:56:13 +0100 Subject: [PATCH 13/21] machinary: add GRPCRoute & GRPCRouteRules to topology Signed-off-by: KevFan --- machinery/gateway_api_test_helper.go | 63 +++++- machinery/gateway_api_topology.go | 267 +++++++++++++++++++++---- machinery/gateway_api_topology_test.go | 16 +- 3 files changed, 298 insertions(+), 48 deletions(-) diff --git a/machinery/gateway_api_test_helper.go b/machinery/gateway_api_test_helper.go index adbb44e..5386998 100644 --- a/machinery/gateway_api_test_helper.go +++ b/machinery/gateway_api_test_helper.go @@ -129,10 +129,57 @@ func BuildService(f ...func(*core.Service)) *core.Service { return s } +func BuildGRPCRoute(f ...func(*gwapiv1.GRPCRoute)) *gwapiv1.GRPCRoute { + r := &gwapiv1.GRPCRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: gwapiv1.GroupVersion.String(), + Kind: "GRPCRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-grpc-route", + Namespace: "my-namespace", + }, + Spec: gwapiv1.GRPCRouteSpec{ + CommonRouteSpec: gwapiv1.CommonRouteSpec{ + ParentRefs: []gwapiv1.ParentReference{ + { + Name: "my-gateway", + }, + }, + }, + Rules: []gwapiv1.GRPCRouteRule{ + { + BackendRefs: []gwapiv1.GRPCBackendRef{BuildGRPCBackendRef()}, + }, + }, + }, + } + for _, fn := range f { + fn(r) + } + + return r +} + +func BuildGRPCBackendRef(f ...func(*gwapiv1.BackendObjectReference)) gwapiv1.GRPCBackendRef { + bor := &gwapiv1.BackendObjectReference{ + Name: "my-service", + } + for _, fn := range f { + fn(bor) + } + return gwapiv1.GRPCBackendRef{ + BackendRef: gwapiv1.BackendRef{ + BackendObjectReference: *bor, + }, + } +} + type GatewayAPIResources struct { GatewayClasses []*gwapiv1.GatewayClass Gateways []*gwapiv1.Gateway HTTPRoutes []*gwapiv1.HTTPRoute + GRPCRoutes []*gwapiv1.GRPCRoute Services []*core.Service } @@ -323,13 +370,6 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }, } }), - BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-7" - r.Spec.ParentRefs[0].Name = "gateway-5" - r.Spec.Rules[0].BackendRefs[0] = BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-7" - }) - }), }, Services: []*core.Service{ BuildService(func(s *core.Service) { @@ -369,6 +409,15 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway s.Spec.Ports[0].Name = "port-1" }), }, + GRPCRoutes: []*gwapiv1.GRPCRoute{ + BuildGRPCRoute(func(r *gwapiv1.GRPCRoute) { + r.Name = "route-7" + r.Spec.ParentRefs[0].Name = "gateway-5" + r.Spec.Rules[0].BackendRefs[0] = BuildGRPCBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-7" + }) + }), + }, } for _, f := range funcs { f(&t) diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index 01a6cdb..45031b3 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -14,6 +14,7 @@ type GatewayAPITopologyOptions struct { GatewayClasses []*GatewayClass Gateways []*Gateway HTTPRoutes []*HTTPRoute + GRPCRoutes []*GRPCRoute Services []*Service Policies []Policy Objects []Object @@ -21,6 +22,7 @@ type GatewayAPITopologyOptions struct { ExpandGatewayListeners bool ExpandHTTPRouteRules bool + ExpandGRPCRouteRules bool ExpandServicePorts bool } @@ -53,6 +55,15 @@ func WithHTTPRoutes(httpRoutes ...*gwapiv1.HTTPRoute) GatewayAPITopologyOptionsF } } +// WithGRPCRoutes adds GRPC routes to the options to initialize a new Gateway API topology. +func WithGRPCRoutes(grpcRoutes ...*gwapiv1.GRPCRoute) GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.GRPCRoutes = append(o.GRPCRoutes, lo.Map(grpcRoutes, func(grpcRoute *gwapiv1.GRPCRoute, _ int) *GRPCRoute { + return &GRPCRoute{GRPCRoute: grpcRoute} + })...) + } +} + // WithServices adds services to the options to initialize a new Gateway API topology. func WithServices(services ...*core.Service) GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -78,7 +89,7 @@ func WithGatewayAPITopologyObjects(objects ...Object) GatewayAPITopologyOptionsF } } -// WithLinks adds link functions to the options to initialize a new Gateway API topology. +// WithGatewayAPITopologyLinks adds link functions to the options to initialize a new Gateway API topology. func WithGatewayAPITopologyLinks(links ...LinkFunc) GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { o.Links = append(o.Links, links...) @@ -99,6 +110,13 @@ func ExpandHTTPRouteRules() GatewayAPITopologyOptionsFunc { } } +// ExpandGRPCRouteRules adds targetable GRPC route rules to the options to initialize a new Gateway API topology. +func ExpandGRPCRouteRules() GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.ExpandGRPCRouteRules = true + } +} + // ExpandServicePorts adds targetable service ports to the options to initialize a new Gateway API topology. func ExpandServicePorts() GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -128,6 +146,7 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { WithTargetables(o.GatewayClasses...), WithTargetables(o.Gateways...), WithTargetables(o.HTTPRoutes...), + WithTargetables(o.GRPCRoutes...), WithTargetables(o.Services...), WithLinks(o.Links...), WithLinks(LinkGatewayClassToGatewayFunc(o.GatewayClasses)), // GatewayClass -> Gateway @@ -139,9 +158,11 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { opts = append(opts, WithLinks( LinkGatewayToListenerFunc(), // Gateway -> Listener LinkListenerToHTTPRouteFunc(o.Gateways, listeners), // Listener -> HTTPRoute + LinkListenerToGRPCRouteFunc(o.Gateways, listeners), // Listener -> GRPCRoute )) } else { opts = append(opts, WithLinks(LinkGatewayToHTTPRouteFunc(o.Gateways))) // Gateway -> HTTPRoute + opts = append(opts, WithLinks(LinkGatewayToGRPCRouteFunc(o.Gateways))) // Gateway -> GRPCRoute } if o.ExpandHTTPRouteRules { @@ -170,6 +191,32 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { } } + if o.ExpandGRPCRouteRules { + grpcRouteRules := lo.FlatMap(o.GRPCRoutes, GRPCRouteRulesFromGRPCRouteRule) + opts = append(opts, WithTargetables(grpcRouteRules...)) + opts = append(opts, WithLinks(LinkGRPCRouteToGRPCRouteRuleFunc())) // GRPCRoute -> GRPCRouteRule + + if o.ExpandServicePorts { + servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) + opts = append(opts, WithTargetables(servicePorts...)) + opts = append(opts, WithLinks( + LinkGRPCRouteRuleToServicePortFunc(grpcRouteRules), // GRPCRouteRule -> ServicePort + LinkGRPCRouteRuleToServiceFunc(grpcRouteRules, true), // GRPCRouteRule -> Service + )) + } else { + opts = append(opts, WithLinks(LinkGRPCRouteRuleToServiceFunc(grpcRouteRules, false))) // GRPCRouteRule -> Service + } + } else { + if o.ExpandServicePorts { + opts = append(opts, WithLinks( + LinkGRPCRouteToServicePortFunc(o.GRPCRoutes), // GRPCRoute -> ServicePort + LinkGRPCRouteToServiceFunc(o.GRPCRoutes, true), // GRPCRoute -> Service + )) + } else { + opts = append(opts, WithLinks(LinkGRPCRouteToServiceFunc(o.GRPCRoutes, false))) // GRPCRoute -> Service + } + } + if o.ExpandServicePorts { opts = append(opts, WithLinks(LinkServiceToServicePortFunc())) // Service -> ServicePort } @@ -198,6 +245,17 @@ func HTTPRouteRulesFromHTTPRouteFunc(httpRoute *HTTPRoute, _ int) []*HTTPRouteRu }) } +// GRPCRouteRulesFromGRPCRouteRule returns a list of targetable GRPCRouteRules from a targetable GRPCRoute. +func GRPCRouteRulesFromGRPCRouteRule(grpcRoute *GRPCRoute, _ int) []*GRPCRouteRule { + return lo.Map(grpcRoute.Spec.Rules, func(rule gwapiv1.GRPCRouteRule, i int) *GRPCRouteRule { + return &GRPCRouteRule{ + GRPCRouteRule: &rule, + GRPCRoute: grpcRoute, + Name: gwapiv1.SectionName(fmt.Sprintf("rule-%d", i+1)), + } + }) +} + // ServicePortsFromBackendFunc returns a list of targetable service ports from a targetable Service. func ServicePortsFromBackendFunc(service *Service, _ int) []*ServicePort { return lo.Map(service.Spec.Ports, func(port core.ServicePort, _ int) *ServicePort { @@ -235,21 +293,39 @@ func LinkGatewayToHTTPRouteFunc(gateways []*Gateway) LinkFunc { To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, Func: func(child Object) []Object { httpRoute := child.(*HTTPRoute) - return lo.FilterMap(httpRoute.Spec.ParentRefs, func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { - parentRefGroup := ptr.Deref(parentRef.Group, gwapiv1.Group(gwapiv1.GroupName)) - parentRefKind := ptr.Deref(parentRef.Kind, gwapiv1.Kind("Gateway")) - if parentRefGroup != gwapiv1.GroupName || parentRefKind != "Gateway" { - return nil, false - } - gatewayNamespace := string(ptr.Deref(parentRef.Namespace, gwapiv1.Namespace(httpRoute.Namespace))) - return lo.Find(gateways, func(g *Gateway) bool { - return g.Namespace == gatewayNamespace && g.Name == string(parentRef.Name) - }) - }) + return lo.FilterMap(httpRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, httpRoute.Namespace)) }, } } +// LinkGatewayToGRPCRouteFunc returns a link function that teaches a topology how to link GRPCRoute's from known +// Gateway's, based on the GRPCRoute's `parentRefs` field. +func LinkGatewayToGRPCRouteFunc(gateways []*Gateway) LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"}, + To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + Func: func(child Object) []Object { + grpcRoute := child.(*GRPCRoute) + return lo.FilterMap(grpcRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, grpcRoute.Namespace)) + }, + } +} + +// findGatewayFromParentRefFunc is a common function to find a Gateway from a xRoute's `parentRef` field +func findGatewayFromParentRefFunc(gateways []*Gateway, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { + return func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { + parentRefGroup := ptr.Deref(parentRef.Group, gwapiv1.GroupName) + parentRefKind := ptr.Deref(parentRef.Kind, "Gateway") + if parentRefGroup != gwapiv1.GroupName || parentRefKind != "Gateway" { + return nil, false + } + gatewayNamespace := string(ptr.Deref(parentRef.Namespace, gwapiv1.Namespace(routeNamespace))) + return lo.Find(gateways, func(g *Gateway) bool { + return g.Namespace == gatewayNamespace && g.Name == string(parentRef.Name) + }) + } +} + // LinkGatewayToListenerFunc returns a link function that teaches a topology how to link gateway Listeners from the // Gateways they are strongly related to. func LinkGatewayToListenerFunc() LinkFunc { @@ -273,36 +349,56 @@ func LinkListenerToHTTPRouteFunc(gateways []*Gateway, listeners []*Listener) Lin To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, Func: func(child Object) []Object { httpRoute := child.(*HTTPRoute) - return lo.FlatMap(httpRoute.Spec.ParentRefs, func(parentRef gwapiv1.ParentReference, _ int) []Object { - parentRefGroup := ptr.Deref(parentRef.Group, gwapiv1.Group(gwapiv1.GroupName)) - parentRefKind := ptr.Deref(parentRef.Kind, gwapiv1.Kind("Gateway")) - if parentRefGroup != gwapiv1.GroupName || parentRefKind != "Gateway" { - return nil - } - gatewayNamespace := string(ptr.Deref(parentRef.Namespace, gwapiv1.Namespace(httpRoute.Namespace))) - gateway, ok := lo.Find(gateways, func(g *Gateway) bool { - return g.Namespace == gatewayNamespace && g.Name == string(parentRef.Name) - }) - if !ok { - return nil - } - if parentRef.SectionName != nil { - listener, ok := lo.Find(listeners, func(l *Listener) bool { - return l.Gateway.GetURL() == gateway.GetURL() && l.Name == *parentRef.SectionName - }) - if !ok { - return nil - } - return []Object{listener} - } - return lo.FilterMap(listeners, func(l *Listener, _ int) (Object, bool) { - return l, l.Gateway.GetURL() == gateway.GetURL() - }) - }) + return lo.FlatMap(httpRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, httpRoute.Namespace)) }, } } +// LinkListenerToGRPCRouteFunc returns a link function that teaches a topology how to link GRPCRoutes from known +// Gateways and gateway Listeners, based on the GRPCRoute's `parentRefs` field. +// The function links a specific Listener of a Gateway to the GRPCRoute when the `sectionName` field of the parent +// reference is present, otherwise all Listeners of the parent Gateway are linked to the GRPCRoute. +func LinkListenerToGRPCRouteFunc(gateways []*Gateway, listeners []*Listener) LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"}, + To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + Func: func(child Object) []Object { + grpcRoute := child.(*GRPCRoute) + return lo.FlatMap(grpcRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, grpcRoute.Namespace)) + }, + } +} + +// findListenerFromParentRefFunc is a common function to find a gateway Listener from a xRoute's `parentRef` field +func findListenerFromParentRefFunc(gateways []*Gateway, listeners []*Listener, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) []Object { + return func(parentRef gwapiv1.ParentReference, _ int) []Object { + parentRefGroup := ptr.Deref(parentRef.Group, gwapiv1.GroupName) + parentRefKind := ptr.Deref(parentRef.Kind, "Gateway") + if parentRefGroup != gwapiv1.GroupName || parentRefKind != "Gateway" { + return nil + } + gatewayNamespace := string(ptr.Deref(parentRef.Namespace, gwapiv1.Namespace(routeNamespace))) + gateway, ok := lo.Find(gateways, func(g *Gateway) bool { + return g.Namespace == gatewayNamespace && g.Name == string(parentRef.Name) + }) + if !ok { + return nil + } + if parentRef.SectionName != nil { + listener, ok := lo.Find(listeners, func(l *Listener) bool { + return l.Gateway.GetURL() == gateway.GetURL() && l.Name == *parentRef.SectionName + }) + if !ok { + return nil + } + return []Object{listener} + } + return lo.FilterMap(listeners, func(l *Listener, _ int) (Object, bool) { + return l, l.Gateway.GetURL() == gateway.GetURL() + }) + } +} + // LinkHTTPRouteToHTTPRouteRuleFunc returns a link function that teaches a topology how to link HTTPRouteRules from the // HTTPRoute they are strongly related to. func LinkHTTPRouteToHTTPRouteRuleFunc() LinkFunc { @@ -396,8 +492,101 @@ func LinkHTTPRouteRuleToServicePortFunc(httpRouteRules []*HTTPRouteRule) LinkFun } } +// LinkGRPCRouteToServiceFunc returns a link function that teaches a topology how to link Services from known +// GRPCRoutes, based on the GRPCRoute's `backendRefs` fields. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkGRPCRouteToServiceFunc(routes []*GRPCRoute, strict bool) LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + To: schema.GroupKind{Kind: "Service"}, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routes, func(route *GRPCRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1.GRPCRouteRule) bool { + backendRefs := lo.FilterMap(rule.BackendRefs, func(backendRef gwapiv1.GRPCBackendRef, _ int) (gwapiv1.BackendRef, bool) { + return backendRef.BackendRef, !strict || backendRef.Port == nil + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, route.Namespace)) + }) + }) + }, + } +} + +// LinkGRPCRouteToServicePortFunc returns a link function that teaches a topology how to link services ports from known +// GRPCRoutes, based on the GRPCRoute's `backendRefs` fields. +// The link function disregards backend references that do not specify a port number. +func LinkGRPCRouteToServicePortFunc(routes []*GRPCRoute) LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + To: schema.GroupKind{Kind: "ServicePort"}, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routes, func(route *GRPCRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1.GRPCRouteRule) bool { + backendRefs := lo.FilterMap(rule.BackendRefs, func(backendRef gwapiv1.GRPCBackendRef, _ int) (gwapiv1.BackendRef, bool) { + return backendRef.BackendRef, backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, route.Namespace)) + }) + }) + }, + } +} + +// LinkGRPCRouteToGRPCRouteRuleFunc returns a link function that teaches a topology how to link GRPCRouteRule from the +// GRPCRoute they are strongly related to. +func LinkGRPCRouteToGRPCRouteRuleFunc() LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"}, + Func: func(child Object) []Object { + grpcRouteRule := child.(*GRPCRouteRule) + return []Object{grpcRouteRule.GRPCRoute} + }, + } +} + +// LinkGRPCRouteRuleToServiceFunc returns a link function that teaches a topology how to link Services from known +// GRPCRouteRules, based on the GRPCRouteRule's `backendRefs` field. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkGRPCRouteRuleToServiceFunc(routeRules []*GRPCRouteRule, strict bool) LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"}, + To: schema.GroupKind{Kind: "Service"}, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routeRules, func(routeRule *GRPCRouteRule, _ int) (Object, bool) { + backendRefs := lo.FilterMap(routeRule.BackendRefs, func(backendRef gwapiv1.GRPCBackendRef, _ int) (gwapiv1.BackendRef, bool) { + return backendRef.BackendRef, !strict || backendRef.Port == nil + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, routeRule.GRPCRoute.Namespace)) + }) + }, + } +} + +// LinkGRPCRouteRuleToServicePortFunc returns a link function that teaches a topology how to link services ports from +// known GRPCRouteRules, based on the GRPCRouteRule's `backendRefs` field. +// The link function disregards backend references that do not specify a port number. +func LinkGRPCRouteRuleToServicePortFunc(routeRules []*GRPCRouteRule) LinkFunc { + return LinkFunc{ + From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"}, + To: schema.GroupKind{Kind: "ServicePort"}, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routeRules, func(routeRule *GRPCRouteRule, _ int) (Object, bool) { + backendRefs := lo.FilterMap(routeRule.BackendRefs, func(backendRef gwapiv1.GRPCBackendRef, _ int) (gwapiv1.BackendRef, bool) { + return backendRef.BackendRef, backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, routeRule.GRPCRoute.Namespace)) + }) + }, + } +} + // LinkServiceToServicePortFunc returns a link function that teaches a topology how to link service ports from the -// Serviceg they are strongly related to. +// Service they are strongly related to. func LinkServiceToServicePortFunc() LinkFunc { return LinkFunc{ From: schema.GroupKind{Kind: "Service"}, diff --git a/machinery/gateway_api_topology_test.go b/machinery/gateway_api_topology_test.go index d8240a2..008e841 100644 --- a/machinery/gateway_api_topology_test.go +++ b/machinery/gateway_api_topology_test.go @@ -20,6 +20,7 @@ import ( // This results in a topology with the following scheme: // // GatewayClass -> Gateway -> HTTPRoute -> Service +// ∟> GRPCRoute ⤴ func TestGatewayAPITopology(t *testing.T) { testCases := []struct { name string @@ -42,12 +43,14 @@ func TestGatewayAPITopology(t *testing.T) { GatewayClasses: []*gwapiv1.GatewayClass{BuildGatewayClass()}, Gateways: []*gwapiv1.Gateway{BuildGateway()}, HTTPRoutes: []*gwapiv1.HTTPRoute{BuildHTTPRoute()}, + GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, - "my-gateway": {"my-http-route"}, + "my-gateway": {"my-http-route", "my-grpc-route"}, + "my-grpc-route": {"my-service"}, "my-http-route": {"my-service"}, }, }, @@ -79,6 +82,7 @@ func TestGatewayAPITopology(t *testing.T) { }) gateways := lo.Map(tc.targetables.Gateways, func(gateway *gwapiv1.Gateway, _ int) *Gateway { return &Gateway{Gateway: gateway} }) httpRoutes := lo.Map(tc.targetables.HTTPRoutes, func(httpRoute *gwapiv1.HTTPRoute, _ int) *HTTPRoute { return &HTTPRoute{HTTPRoute: httpRoute} }) + grpcRoutes := lo.Map(tc.targetables.GRPCRoutes, func(grpcRoute *gwapiv1.GRPCRoute, _ int) *GRPCRoute { return &GRPCRoute{GRPCRoute: grpcRoute} }) services := lo.Map(tc.targetables.Services, func(service *core.Service, _ int) *Service { return &Service{Service: service} }) topology := NewTopology( @@ -86,10 +90,13 @@ func TestGatewayAPITopology(t *testing.T) { WithTargetables(gateways...), WithTargetables(httpRoutes...), WithTargetables(services...), + WithTargetables(grpcRoutes...), WithLinks( LinkGatewayClassToGatewayFunc(gatewayClasses), LinkGatewayToHTTPRouteFunc(gateways), LinkHTTPRouteToServiceFunc(httpRoutes, false), + LinkGatewayToGRPCRouteFunc(gateways), + LinkGRPCRouteToServiceFunc(grpcRoutes, false), ), WithPolicies(tc.policies...), ) @@ -132,13 +139,16 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { GatewayClasses: []*gwapiv1.GatewayClass{BuildGatewayClass()}, Gateways: []*gwapiv1.Gateway{BuildGateway()}, HTTPRoutes: []*gwapiv1.HTTPRoute{BuildHTTPRoute()}, + GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, "my-gateway": {"my-gateway#my-listener"}, - "my-gateway#my-listener": {"my-http-route"}, + "my-gateway#my-listener": {"my-http-route", "my-grpc-route"}, + "my-grpc-route": {"my-grpc-route#rule-1"}, + "my-grpc-route#rule-1": {"my-service"}, "my-http-route": {"my-http-route#rule-1"}, "my-http-route#rule-1": {"my-service"}, "my-service": {"my-service#http"}, @@ -239,6 +249,8 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { ExpandGatewayListeners(), WithHTTPRoutes(tc.targetables.HTTPRoutes...), ExpandHTTPRouteRules(), + WithGRPCRoutes(tc.targetables.GRPCRoutes...), + ExpandGRPCRouteRules(), WithServices(tc.targetables.Services...), ExpandServicePorts(), WithGatewayAPITopologyPolicies(tc.policies...), From c72f74ecbaf841c1f08f8d615b87092c602db0ab Mon Sep 17 00:00:00 2001 From: KevFan Date: Wed, 31 Jul 2024 10:03:07 +0100 Subject: [PATCH 14/21] refactor: Gateway API GroupKind vars Signed-off-by: KevFan --- machinery/gateway_api_topology.go | 80 ++++++++++++++++++------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index 45031b3..3bdf9e7 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -10,6 +10,18 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) +var ( + GatewayClassGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GatewayClass"} + GatewayGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"} + ListenerGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"} + HTTPRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"} + HTTPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"} + GRPCRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"} + GRPCRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"} + ServiceGroupKind = schema.GroupKind{Kind: "Service"} + ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} +) + type GatewayAPITopologyOptions struct { GatewayClasses []*GatewayClass Gateways []*Gateway @@ -270,8 +282,8 @@ func ServicePortsFromBackendFunc(service *Service, _ int) []*ServicePort { // GatewayClasses, based on the Gateway's `gatewayClassName` field. func LinkGatewayClassToGatewayFunc(gatewayClasses []*GatewayClass) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GatewayClass"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"}, + From: GatewayClassGroupKind, + To: GatewayGroupKind, Func: func(child Object) []Object { gateway := child.(*Gateway) gatewayClass, ok := lo.Find(gatewayClasses, func(gc *GatewayClass) bool { @@ -289,8 +301,8 @@ func LinkGatewayClassToGatewayFunc(gatewayClasses []*GatewayClass) LinkFunc { // Gateways, based on the HTTPRoute's `parentRefs` field. func LinkGatewayToHTTPRouteFunc(gateways []*Gateway) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, + From: GatewayGroupKind, + To: HTTPRouteGroupKind, Func: func(child Object) []Object { httpRoute := child.(*HTTPRoute) return lo.FilterMap(httpRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, httpRoute.Namespace)) @@ -302,8 +314,8 @@ func LinkGatewayToHTTPRouteFunc(gateways []*Gateway) LinkFunc { // Gateway's, based on the GRPCRoute's `parentRefs` field. func LinkGatewayToGRPCRouteFunc(gateways []*Gateway) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + From: GatewayGroupKind, + To: GRPCRouteGroupKind, Func: func(child Object) []Object { grpcRoute := child.(*GRPCRoute) return lo.FilterMap(grpcRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, grpcRoute.Namespace)) @@ -330,8 +342,8 @@ func findGatewayFromParentRefFunc(gateways []*Gateway, routeNamespace string) fu // Gateways they are strongly related to. func LinkGatewayToListenerFunc() LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"}, + From: GatewayGroupKind, + To: ListenerGroupKind, Func: func(child Object) []Object { listener := child.(*Listener) return []Object{listener.Gateway} @@ -345,8 +357,8 @@ func LinkGatewayToListenerFunc() LinkFunc { // reference is present, otherwise all Listeners of the parent Gateway are linked to the HTTPRoute. func LinkListenerToHTTPRouteFunc(gateways []*Gateway, listeners []*Listener) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, + From: ListenerGroupKind, + To: HTTPRouteGroupKind, Func: func(child Object) []Object { httpRoute := child.(*HTTPRoute) return lo.FlatMap(httpRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, httpRoute.Namespace)) @@ -360,8 +372,8 @@ func LinkListenerToHTTPRouteFunc(gateways []*Gateway, listeners []*Listener) Lin // reference is present, otherwise all Listeners of the parent Gateway are linked to the GRPCRoute. func LinkListenerToGRPCRouteFunc(gateways []*Gateway, listeners []*Listener) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, + From: ListenerGroupKind, + To: GRPCRouteGroupKind, Func: func(child Object) []Object { grpcRoute := child.(*GRPCRoute) return lo.FlatMap(grpcRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, grpcRoute.Namespace)) @@ -403,8 +415,8 @@ func findListenerFromParentRefFunc(gateways []*Gateway, listeners []*Listener, r // HTTPRoute they are strongly related to. func LinkHTTPRouteToHTTPRouteRuleFunc() LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"}, + From: HTTPRouteGroupKind, + To: HTTPRouteRuleGroupKind, Func: func(child Object) []Object { httpRouteRule := child.(*HTTPRouteRule) return []Object{httpRouteRule.HTTPRoute} @@ -417,8 +429,8 @@ func LinkHTTPRouteToHTTPRouteRuleFunc() LinkFunc { // Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. func LinkHTTPRouteToServiceFunc(httpRoutes []*HTTPRoute, strict bool) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, - To: schema.GroupKind{Kind: "Service"}, + From: HTTPRouteGroupKind, + To: ServiceGroupKind, Func: func(child Object) []Object { service := child.(*Service) return lo.FilterMap(httpRoutes, func(httpRoute *HTTPRoute, _ int) (Object, bool) { @@ -438,8 +450,8 @@ func LinkHTTPRouteToServiceFunc(httpRoutes []*HTTPRoute, strict bool) LinkFunc { // The link function disregards backend references that do not specify a port number. func LinkHTTPRouteToServicePortFunc(httpRoutes []*HTTPRoute) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"}, - To: schema.GroupKind{Kind: "ServicePort"}, + From: HTTPRouteGroupKind, + To: ServicePortGroupKind, Func: func(child Object) []Object { servicePort := child.(*ServicePort) return lo.FilterMap(httpRoutes, func(httpRoute *HTTPRoute, _ int) (Object, bool) { @@ -459,8 +471,8 @@ func LinkHTTPRouteToServicePortFunc(httpRoutes []*HTTPRoute) LinkFunc { // Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. func LinkHTTPRouteRuleToServiceFunc(httpRouteRules []*HTTPRouteRule, strict bool) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"}, - To: schema.GroupKind{Kind: "Service"}, + From: HTTPRouteRuleGroupKind, + To: ServiceGroupKind, Func: func(child Object) []Object { service := child.(*Service) return lo.FilterMap(httpRouteRules, func(httpRouteRule *HTTPRouteRule, _ int) (Object, bool) { @@ -478,8 +490,8 @@ func LinkHTTPRouteRuleToServiceFunc(httpRouteRules []*HTTPRouteRule, strict bool // The link function disregards backend references that do not specify a port number. func LinkHTTPRouteRuleToServicePortFunc(httpRouteRules []*HTTPRouteRule) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"}, - To: schema.GroupKind{Kind: "ServicePort"}, + From: HTTPRouteRuleGroupKind, + To: ServicePortGroupKind, Func: func(child Object) []Object { servicePort := child.(*ServicePort) return lo.FilterMap(httpRouteRules, func(httpRouteRule *HTTPRouteRule, _ int) (Object, bool) { @@ -497,8 +509,8 @@ func LinkHTTPRouteRuleToServicePortFunc(httpRouteRules []*HTTPRouteRule) LinkFun // Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. func LinkGRPCRouteToServiceFunc(routes []*GRPCRoute, strict bool) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, - To: schema.GroupKind{Kind: "Service"}, + From: GRPCRouteGroupKind, + To: ServiceGroupKind, Func: func(child Object) []Object { service := child.(*Service) return lo.FilterMap(routes, func(route *GRPCRoute, _ int) (Object, bool) { @@ -518,8 +530,8 @@ func LinkGRPCRouteToServiceFunc(routes []*GRPCRoute, strict bool) LinkFunc { // The link function disregards backend references that do not specify a port number. func LinkGRPCRouteToServicePortFunc(routes []*GRPCRoute) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, - To: schema.GroupKind{Kind: "ServicePort"}, + From: GRPCRouteGroupKind, + To: ServicePortGroupKind, Func: func(child Object) []Object { servicePort := child.(*ServicePort) return lo.FilterMap(routes, func(route *GRPCRoute, _ int) (Object, bool) { @@ -538,8 +550,8 @@ func LinkGRPCRouteToServicePortFunc(routes []*GRPCRoute) LinkFunc { // GRPCRoute they are strongly related to. func LinkGRPCRouteToGRPCRouteRuleFunc() LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"}, - To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"}, + From: GRPCRouteGroupKind, + To: GRPCRouteRuleGroupKind, Func: func(child Object) []Object { grpcRouteRule := child.(*GRPCRouteRule) return []Object{grpcRouteRule.GRPCRoute} @@ -552,8 +564,8 @@ func LinkGRPCRouteToGRPCRouteRuleFunc() LinkFunc { // Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. func LinkGRPCRouteRuleToServiceFunc(routeRules []*GRPCRouteRule, strict bool) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"}, - To: schema.GroupKind{Kind: "Service"}, + From: GRPCRouteRuleGroupKind, + To: ServiceGroupKind, Func: func(child Object) []Object { service := child.(*Service) return lo.FilterMap(routeRules, func(routeRule *GRPCRouteRule, _ int) (Object, bool) { @@ -571,8 +583,8 @@ func LinkGRPCRouteRuleToServiceFunc(routeRules []*GRPCRouteRule, strict bool) Li // The link function disregards backend references that do not specify a port number. func LinkGRPCRouteRuleToServicePortFunc(routeRules []*GRPCRouteRule) LinkFunc { return LinkFunc{ - From: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"}, - To: schema.GroupKind{Kind: "ServicePort"}, + From: GRPCRouteRuleGroupKind, + To: ServicePortGroupKind, Func: func(child Object) []Object { servicePort := child.(*ServicePort) return lo.FilterMap(routeRules, func(routeRule *GRPCRouteRule, _ int) (Object, bool) { @@ -589,8 +601,8 @@ func LinkGRPCRouteRuleToServicePortFunc(routeRules []*GRPCRouteRule) LinkFunc { // Service they are strongly related to. func LinkServiceToServicePortFunc() LinkFunc { return LinkFunc{ - From: schema.GroupKind{Kind: "Service"}, - To: schema.GroupKind{Kind: "ServicePort"}, + From: ServiceGroupKind, + To: ServicePortGroupKind, Func: func(child Object) []Object { servicePort := child.(*ServicePort) return []Object{servicePort.Service} From 3a85136e1de0c719992062223620ef18665b4c58 Mon Sep 17 00:00:00 2001 From: KevFan Date: Wed, 31 Jul 2024 11:24:55 +0100 Subject: [PATCH 15/21] machinary: add TCPRoute & TCPRouteRules to topology Signed-off-by: KevFan --- machinery/gateway_api_test_helper.go | 113 +++++++++------ machinery/gateway_api_topology.go | 182 +++++++++++++++++++++++++ machinery/gateway_api_topology_test.go | 93 +++++++------ 3 files changed, 306 insertions(+), 82 deletions(-) diff --git a/machinery/gateway_api_test_helper.go b/machinery/gateway_api_test_helper.go index 5386998..43e53b4 100644 --- a/machinery/gateway_api_test_helper.go +++ b/machinery/gateway_api_test_helper.go @@ -88,16 +88,8 @@ func BuildHTTPRoute(f ...func(*gwapiv1.HTTPRoute)) *gwapiv1.HTTPRoute { } func BuildHTTPBackendRef(f ...func(*gwapiv1.BackendObjectReference)) gwapiv1.HTTPBackendRef { - bor := &gwapiv1.BackendObjectReference{ - Name: "my-service", - } - for _, fn := range f { - fn(bor) - } return gwapiv1.HTTPBackendRef{ - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: *bor, - }, + BackendRef: BuildBackendRef(f...), } } @@ -162,17 +154,53 @@ func BuildGRPCRoute(f ...func(*gwapiv1.GRPCRoute)) *gwapiv1.GRPCRoute { } func BuildGRPCBackendRef(f ...func(*gwapiv1.BackendObjectReference)) gwapiv1.GRPCBackendRef { + return gwapiv1.GRPCBackendRef{ + BackendRef: BuildBackendRef(f...), + } +} + +func BuildBackendRef(f ...func(*gwapiv1.BackendObjectReference)) gwapiv1.BackendRef { bor := &gwapiv1.BackendObjectReference{ Name: "my-service", } for _, fn := range f { fn(bor) } - return gwapiv1.GRPCBackendRef{ - BackendRef: gwapiv1.BackendRef{ - BackendObjectReference: *bor, + return gwapiv1.BackendRef{ + BackendObjectReference: *bor, + } +} + +func BuildTCPRoute(f ...func(route *gwapiv1alpha2.TCPRoute)) *gwapiv1alpha2.TCPRoute { + r := &gwapiv1alpha2.TCPRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: gwapiv1.GroupVersion.String(), + Kind: "TCPRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-tcp-route", + Namespace: "my-namespace", + }, + Spec: gwapiv1alpha2.TCPRouteSpec{ + CommonRouteSpec: gwapiv1.CommonRouteSpec{ + ParentRefs: []gwapiv1.ParentReference{ + { + Name: "my-gateway", + }, + }, + }, + Rules: []gwapiv1alpha2.TCPRouteRule{ + { + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef()}, + }, + }, }, } + for _, fn := range f { + fn(r) + } + + return r } type GatewayAPIResources struct { @@ -180,6 +208,7 @@ type GatewayAPIResources struct { Gateways []*gwapiv1.Gateway HTTPRoutes []*gwapiv1.HTTPRoute GRPCRoutes []*gwapiv1.GRPCRoute + TCPRoutes []*gwapiv1alpha2.TCPRoute Services []*core.Service } @@ -205,7 +234,7 @@ type GatewayAPIResources struct { // │ └───────┬───────┘ │ │ └────────────┬─────────────┘ │ │ // │ │ │ │ │ │ │ // ┌───────────┴───────────┐ ┌──────┴─────┐ ┌─────┴──────┐ ┌───────────┴───────────┐ ┌───────────┴───────────┐ ┌───────────┴───────────┐ ┌─────┴──────┐ -// │ route-1 │ │ route-2 │ │ route-3 │ │ route-4 │ │ route-5 │ │ route-6 │ │ route-7 │ +// │ h-route-1 │ │ h-route-2 │ │ h-route-3 │ │ h-route-4 │ │ h-route-5 │ │ tcp-route-1 │ │ g-route-1 │ // │ │ │ │ │ │ │ │ │ │ │ │ │ │ // │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ // │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ │ │ rule-1 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ @@ -273,7 +302,7 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }, HTTPRoutes: []*gwapiv1.HTTPRoute{ BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-1" + r.Name = "http-route-1" r.Spec.ParentRefs[0].Name = "gateway-1" r.Spec.Rules = []gwapiv1.HTTPRouteRule{ { // rule-1 @@ -289,7 +318,7 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway } }), BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-2" + r.Name = "http-route-2" r.Spec.ParentRefs = []gwapiv1.ParentReference{ { Name: "gateway-1", @@ -306,7 +335,7 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }) }), BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-3" + r.Name = "http-route-3" r.Spec.ParentRefs[0].Name = "gateway-2" r.Spec.Rules[0].BackendRefs[0] = BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { backendRef.Name = "service-3" @@ -314,7 +343,7 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }) }), BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-4" + r.Name = "http-route-4" r.Spec.ParentRefs[0].Name = "gateway-3" r.Spec.Rules = []gwapiv1.HTTPRouteRule{ { // rule-1 @@ -332,7 +361,7 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway } }), BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-5" + r.Name = "http-route-5" r.Spec.ParentRefs[0].Name = "gateway-3" r.Spec.ParentRefs = append(r.Spec.ParentRefs, gwapiv1.ParentReference{Name: "gateway-4"}) r.Spec.Rules = []gwapiv1.HTTPRouteRule{ @@ -348,28 +377,6 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }, } }), - BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "route-6" - r.Spec.ParentRefs[0].Name = "gateway-4" - r.Spec.Rules = []gwapiv1.HTTPRouteRule{ - { // rule-1 - BackendRefs: []gwapiv1.HTTPBackendRef{ - BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-5" - }), - BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-6" - }), - }, - }, - { // rule-2 - BackendRefs: []gwapiv1.HTTPBackendRef{BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-6" - backendRef.Port = ptr.To(gwapiv1.PortNumber(80)) // port-1 - })}, - }, - } - }), }, Services: []*core.Service{ BuildService(func(s *core.Service) { @@ -411,13 +418,37 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }, GRPCRoutes: []*gwapiv1.GRPCRoute{ BuildGRPCRoute(func(r *gwapiv1.GRPCRoute) { - r.Name = "route-7" + r.Name = "grpc-route-1" r.Spec.ParentRefs[0].Name = "gateway-5" r.Spec.Rules[0].BackendRefs[0] = BuildGRPCBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { backendRef.Name = "service-7" }) }), }, + TCPRoutes: []*gwapiv1alpha2.TCPRoute{ + BuildTCPRoute(func(r *gwapiv1alpha2.TCPRoute) { + r.Name = "tcp-route-1" + r.Spec.ParentRefs[0].Name = "gateway-4" + r.Spec.Rules = []gwapiv1alpha2.TCPRouteRule{ + { // rule-1 + BackendRefs: []gwapiv1.BackendRef{ + BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-5" + }), + BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-6" + }), + }, + }, + { // rule-2 + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-6" + backendRef.Port = ptr.To(gwapiv1.PortNumber(80)) // port-1 + })}, + }, + } + }), + }, } for _, f := range funcs { f(&t) diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index 3bdf9e7..cf9ddc9 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -8,6 +8,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) var ( @@ -18,6 +19,8 @@ var ( HTTPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"} GRPCRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"} GRPCRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"} + TCPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRoute"} + TCPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRouteRule"} ServiceGroupKind = schema.GroupKind{Kind: "Service"} ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} ) @@ -27,6 +30,7 @@ type GatewayAPITopologyOptions struct { Gateways []*Gateway HTTPRoutes []*HTTPRoute GRPCRoutes []*GRPCRoute + TCPRoutes []*TCPRoute Services []*Service Policies []Policy Objects []Object @@ -35,6 +39,7 @@ type GatewayAPITopologyOptions struct { ExpandGatewayListeners bool ExpandHTTPRouteRules bool ExpandGRPCRouteRules bool + ExpandTCPRouteRules bool ExpandServicePorts bool } @@ -76,6 +81,15 @@ func WithGRPCRoutes(grpcRoutes ...*gwapiv1.GRPCRoute) GatewayAPITopologyOptionsF } } +// WithTCPRoutes adds TCP routes to the options to initialize a new Gateway API topology. +func WithTCPRoutes(tcpRoutes ...*gwapiv1alpha2.TCPRoute) GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.TCPRoutes = append(o.TCPRoutes, lo.Map(tcpRoutes, func(tcpRoute *gwapiv1alpha2.TCPRoute, _ int) *TCPRoute { + return &TCPRoute{TCPRoute: tcpRoute} + })...) + } +} + // WithServices adds services to the options to initialize a new Gateway API topology. func WithServices(services ...*core.Service) GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -129,6 +143,13 @@ func ExpandGRPCRouteRules() GatewayAPITopologyOptionsFunc { } } +// ExpandTCPRouteRules adds targetable TCP route rules to the options to initialize a new Gateway API topology. +func ExpandTCPRouteRules() GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.ExpandTCPRouteRules = true + } +} + // ExpandServicePorts adds targetable service ports to the options to initialize a new Gateway API topology. func ExpandServicePorts() GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -159,6 +180,7 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { WithTargetables(o.Gateways...), WithTargetables(o.HTTPRoutes...), WithTargetables(o.GRPCRoutes...), + WithTargetables(o.TCPRoutes...), WithTargetables(o.Services...), WithLinks(o.Links...), WithLinks(LinkGatewayClassToGatewayFunc(o.GatewayClasses)), // GatewayClass -> Gateway @@ -171,10 +193,12 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { LinkGatewayToListenerFunc(), // Gateway -> Listener LinkListenerToHTTPRouteFunc(o.Gateways, listeners), // Listener -> HTTPRoute LinkListenerToGRPCRouteFunc(o.Gateways, listeners), // Listener -> GRPCRoute + LinkListenerToTCPRouteFunc(o.Gateways, listeners), // Listener -> TCPRoute )) } else { opts = append(opts, WithLinks(LinkGatewayToHTTPRouteFunc(o.Gateways))) // Gateway -> HTTPRoute opts = append(opts, WithLinks(LinkGatewayToGRPCRouteFunc(o.Gateways))) // Gateway -> GRPCRoute + opts = append(opts, WithLinks(LinkGatewayToTCPRouteFunc(o.Gateways))) // Gateway -> TCPRoute } if o.ExpandHTTPRouteRules { @@ -229,6 +253,32 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { } } + if o.ExpandTCPRouteRules { + tcpRouteRules := lo.FlatMap(o.TCPRoutes, TCPRouteRulesFromTCPRouteFunc) + opts = append(opts, WithTargetables(tcpRouteRules...)) + opts = append(opts, WithLinks(LinkTCPRouteToTCPRouteRuleFunc())) // TCPRoute - TCPRouteRules + + if o.ExpandServicePorts { + servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) + opts = append(opts, WithTargetables(servicePorts...)) + opts = append(opts, WithLinks( + LinkTCPRouteRuleToServicePortFunc(tcpRouteRules), // TCPRouteRule -> ServicePort + LinkTCPRouteRuleToServiceFunc(tcpRouteRules, true), // TCPRoute -> service + )) + } else { + opts = append(opts, WithLinks(LinkTCPRouteRuleToServiceFunc(tcpRouteRules, false))) // TCPRouteRule -> Service + } + } else { + if o.ExpandServicePorts { + opts = append(opts, WithLinks( + LinkTCPRouteToServicePortFunc(o.TCPRoutes), // TCPRoute -> ServicePort + LinkTCPRouteToServiceFunc(o.TCPRoutes, true), // TCPRoute -> Service + )) + } else { + opts = append(opts, WithLinks(LinkTCPRouteToServiceFunc(o.TCPRoutes, false))) // TCPRoute -> Service + } + } + if o.ExpandServicePorts { opts = append(opts, WithLinks(LinkServiceToServicePortFunc())) // Service -> ServicePort } @@ -268,6 +318,17 @@ func GRPCRouteRulesFromGRPCRouteRule(grpcRoute *GRPCRoute, _ int) []*GRPCRouteRu }) } +// TCPRouteRulesFromTCPRouteFunc returns a list of targetable TCPRouteRules from a targetable TCPRoute. +func TCPRouteRulesFromTCPRouteFunc(tcpRoute *TCPRoute, _ int) []*TCPRouteRule { + return lo.Map(tcpRoute.Spec.Rules, func(rule gwapiv1alpha2.TCPRouteRule, i int) *TCPRouteRule { + return &TCPRouteRule{ + TCPRouteRule: &rule, + TCPRoute: tcpRoute, + Name: gwapiv1.SectionName(fmt.Sprintf("rule-%d", i+1)), + } + }) +} + // ServicePortsFromBackendFunc returns a list of targetable service ports from a targetable Service. func ServicePortsFromBackendFunc(service *Service, _ int) []*ServicePort { return lo.Map(service.Spec.Ports, func(port core.ServicePort, _ int) *ServicePort { @@ -323,6 +384,19 @@ func LinkGatewayToGRPCRouteFunc(gateways []*Gateway) LinkFunc { } } +// LinkGatewayToTCPRouteFunc returns a link function that teaches a topology how to link TCPRoute's from known +// Gateway's, based on the TCPRoute's `parentRefs` field. +func LinkGatewayToTCPRouteFunc(gateways []*Gateway) LinkFunc { + return LinkFunc{ + From: GatewayGroupKind, + To: TCPRouteGroupKind, + Func: func(child Object) []Object { + tcpRoute := child.(*TCPRoute) + return lo.FilterMap(tcpRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, tcpRoute.Namespace)) + }, + } +} + // findGatewayFromParentRefFunc is a common function to find a Gateway from a xRoute's `parentRef` field func findGatewayFromParentRefFunc(gateways []*Gateway, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { return func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { @@ -381,6 +455,21 @@ func LinkListenerToGRPCRouteFunc(gateways []*Gateway, listeners []*Listener) Lin } } +// LinkListenerToTCPRouteFunc returns a link function that teaches a topology how to link GRPCRoutes from known +// Gateways and gateway Listeners, based on the TCPRoute's `parentRefs` field. +// The function links a specific Listener of a Gateway to the TCPRoute when the `sectionName` field of the parent +// reference is present, otherwise all Listeners of the parent Gateway are linked to the TCPRoute. +func LinkListenerToTCPRouteFunc(gateways []*Gateway, listeners []*Listener) LinkFunc { + return LinkFunc{ + From: ListenerGroupKind, + To: TCPRouteGroupKind, + Func: func(child Object) []Object { + tcpRoute := child.(*TCPRoute) + return lo.FlatMap(tcpRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, tcpRoute.Namespace)) + }, + } +} + // findListenerFromParentRefFunc is a common function to find a gateway Listener from a xRoute's `parentRef` field func findListenerFromParentRefFunc(gateways []*Gateway, listeners []*Listener, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) []Object { return func(parentRef gwapiv1.ParentReference, _ int) []Object { @@ -597,6 +686,99 @@ func LinkGRPCRouteRuleToServicePortFunc(routeRules []*GRPCRouteRule) LinkFunc { } } +// LinkTCPRouteToServiceFunc returns a link function that teaches a topology how to link Services from known +// GRPCRoutes, based on the TCPRoute's `backendRefs` fields. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkTCPRouteToServiceFunc(routes []*TCPRoute, strict bool) LinkFunc { + return LinkFunc{ + From: TCPRouteGroupKind, + To: ServiceGroupKind, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routes, func(route *TCPRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1alpha2.TCPRouteRule) bool { + backendRefs := lo.Filter(rule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return !strict || backendRef.Port == nil + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, route.Namespace)) + }) + }) + }, + } +} + +// LinkTCPRouteToServicePortFunc returns a link function that teaches a topology how to link services ports from known +// TCPRoutes, based on the TCPRoute's `backendRefs` fields. +// The link function disregards backend references that do not specify a port number. +func LinkTCPRouteToServicePortFunc(routes []*TCPRoute) LinkFunc { + return LinkFunc{ + From: TCPRouteGroupKind, + To: ServicePortGroupKind, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routes, func(route *TCPRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1alpha2.TCPRouteRule) bool { + backendRefs := lo.Filter(rule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, route.Namespace)) + }) + }) + }, + } +} + +// LinkTCPRouteToTCPRouteRuleFunc returns a link function that teaches a topology how to link TCPRouteRule from the +// TCPRoute they are strongly related to. +func LinkTCPRouteToTCPRouteRuleFunc() LinkFunc { + return LinkFunc{ + From: TCPRouteGroupKind, + To: TCPRouteRuleGroupKind, + Func: func(child Object) []Object { + tcpRouteRule := child.(*TCPRouteRule) + return []Object{tcpRouteRule.TCPRoute} + }, + } +} + +// LinkTCPRouteRuleToServiceFunc returns a link function that teaches a topology how to link Services from known +// TCPRouteRules, based on the TCPRouteRule's `backendRefs` field. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkTCPRouteRuleToServiceFunc(routeRules []*TCPRouteRule, strict bool) LinkFunc { + return LinkFunc{ + From: TCPRouteRuleGroupKind, + To: ServiceGroupKind, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routeRules, func(routeRule *TCPRouteRule, _ int) (Object, bool) { + backendRefs := lo.Filter(routeRule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return !strict || backendRef.Port == nil + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, routeRule.TCPRoute.Namespace)) + }) + }, + } +} + +// LinkTCPRouteRuleToServicePortFunc returns a link function that teaches a topology how to link services ports from +// known TCPRouteRules, based on the TCPRouteRule's `backendRefs` field. +// The link function disregards backend references that do not specify a port number. +func LinkTCPRouteRuleToServicePortFunc(routeRules []*TCPRouteRule) LinkFunc { + return LinkFunc{ + From: TCPRouteGroupKind, + To: ServicePortGroupKind, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routeRules, func(routeRule *TCPRouteRule, _ int) (Object, bool) { + backendRefs := lo.Filter(routeRule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, routeRule.TCPRoute.Namespace)) + }) + }, + } +} + // LinkServiceToServicePortFunc returns a link function that teaches a topology how to link service ports from the // Service they are strongly related to. func LinkServiceToServicePortFunc() LinkFunc { diff --git a/machinery/gateway_api_topology_test.go b/machinery/gateway_api_topology_test.go index 008e841..d6e1f21 100644 --- a/machinery/gateway_api_topology_test.go +++ b/machinery/gateway_api_topology_test.go @@ -44,14 +44,16 @@ func TestGatewayAPITopology(t *testing.T) { Gateways: []*gwapiv1.Gateway{BuildGateway()}, HTTPRoutes: []*gwapiv1.HTTPRoute{BuildHTTPRoute()}, GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, + TCPRoutes: []*gwapiv1alpha2.TCPRoute{BuildTCPRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, - "my-gateway": {"my-http-route", "my-grpc-route"}, + "my-gateway": {"my-http-route", "my-grpc-route", "my-tcp-route"}, "my-grpc-route": {"my-service"}, "my-http-route": {"my-service"}, + "my-tcp-route": {"my-service"}, }, }, { @@ -60,18 +62,18 @@ func TestGatewayAPITopology(t *testing.T) { expectedLinks: map[string][]string{ "gatewayclass-1": {"gateway-1", "gateway-2", "gateway-3"}, "gatewayclass-2": {"gateway-4", "gateway-5"}, - "gateway-1": {"route-1", "route-2"}, - "gateway-2": {"route-2", "route-3"}, - "gateway-3": {"route-4", "route-5"}, - "gateway-4": {"route-5", "route-6"}, - "gateway-5": {"route-7"}, - "route-1": {"service-1", "service-2"}, - "route-2": {"service-3"}, - "route-3": {"service-3"}, - "route-4": {"service-3", "service-4"}, - "route-5": {"service-5"}, - "route-6": {"service-5", "service-6"}, - "route-7": {"service-7"}, + "gateway-1": {"http-route-1", "http-route-2"}, + "gateway-2": {"http-route-2", "http-route-3"}, + "gateway-3": {"http-route-4", "http-route-5"}, + "gateway-4": {"http-route-5", "tcp-route-1"}, + "gateway-5": {"grpc-route-1"}, + "grpc-route-1": {"service-7"}, + "http-route-1": {"service-1", "service-2"}, + "http-route-2": {"service-3"}, + "http-route-3": {"service-3"}, + "http-route-4": {"service-3", "service-4"}, + "http-route-5": {"service-5"}, + "tcp-route-1": {"service-5", "service-6"}, }, }, } @@ -83,6 +85,7 @@ func TestGatewayAPITopology(t *testing.T) { gateways := lo.Map(tc.targetables.Gateways, func(gateway *gwapiv1.Gateway, _ int) *Gateway { return &Gateway{Gateway: gateway} }) httpRoutes := lo.Map(tc.targetables.HTTPRoutes, func(httpRoute *gwapiv1.HTTPRoute, _ int) *HTTPRoute { return &HTTPRoute{HTTPRoute: httpRoute} }) grpcRoutes := lo.Map(tc.targetables.GRPCRoutes, func(grpcRoute *gwapiv1.GRPCRoute, _ int) *GRPCRoute { return &GRPCRoute{GRPCRoute: grpcRoute} }) + tcpRoutes := lo.Map(tc.targetables.TCPRoutes, func(tcpRoute *gwapiv1alpha2.TCPRoute, _ int) *TCPRoute { return &TCPRoute{TCPRoute: tcpRoute} }) services := lo.Map(tc.targetables.Services, func(service *core.Service, _ int) *Service { return &Service{Service: service} }) topology := NewTopology( @@ -91,12 +94,15 @@ func TestGatewayAPITopology(t *testing.T) { WithTargetables(httpRoutes...), WithTargetables(services...), WithTargetables(grpcRoutes...), + WithTargetables(tcpRoutes...), WithLinks( LinkGatewayClassToGatewayFunc(gatewayClasses), LinkGatewayToHTTPRouteFunc(gateways), - LinkHTTPRouteToServiceFunc(httpRoutes, false), LinkGatewayToGRPCRouteFunc(gateways), + LinkGatewayToTCPRouteFunc(gateways), + LinkHTTPRouteToServiceFunc(httpRoutes, false), LinkGRPCRouteToServiceFunc(grpcRoutes, false), + LinkTCPRouteToServiceFunc(tcpRoutes, false), ), WithPolicies(tc.policies...), ) @@ -140,17 +146,20 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { Gateways: []*gwapiv1.Gateway{BuildGateway()}, HTTPRoutes: []*gwapiv1.HTTPRoute{BuildHTTPRoute()}, GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, + TCPRoutes: []*gwapiv1alpha2.TCPRoute{BuildTCPRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, "my-gateway": {"my-gateway#my-listener"}, - "my-gateway#my-listener": {"my-http-route", "my-grpc-route"}, + "my-gateway#my-listener": {"my-http-route", "my-grpc-route", "my-tcp-route"}, "my-grpc-route": {"my-grpc-route#rule-1"}, "my-grpc-route#rule-1": {"my-service"}, "my-http-route": {"my-http-route#rule-1"}, "my-http-route#rule-1": {"my-service"}, + "my-tcp-route": {"my-tcp-route#rule-1"}, + "my-tcp-route#rule-1": {"my-service"}, "my-service": {"my-service#http"}, }, }, @@ -205,32 +214,32 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { "gateway-3": {"gateway-3#listener-1", "gateway-3#listener-2"}, "gateway-4": {"gateway-4#listener-1", "gateway-4#listener-2"}, "gateway-5": {"gateway-5#listener-1"}, - "gateway-1#listener-1": {"route-1"}, - "gateway-1#listener-2": {"route-1", "route-2"}, - "gateway-2#listener-1": {"route-2", "route-3"}, - "gateway-3#listener-1": {"route-4", "route-5"}, - "gateway-3#listener-2": {"route-4", "route-5"}, - "gateway-4#listener-1": {"route-5", "route-6"}, - "gateway-4#listener-2": {"route-5", "route-6"}, - "gateway-5#listener-1": {"route-7"}, - "route-1": {"route-1#rule-1", "route-1#rule-2"}, - "route-2": {"route-2#rule-1"}, - "route-3": {"route-3#rule-1"}, - "route-4": {"route-4#rule-1", "route-4#rule-2"}, - "route-5": {"route-5#rule-1", "route-5#rule-2"}, - "route-6": {"route-6#rule-1", "route-6#rule-2"}, - "route-7": {"route-7#rule-1"}, - "route-1#rule-1": {"service-1"}, - "route-1#rule-2": {"service-2"}, - "route-2#rule-1": {"service-3#port-1"}, - "route-3#rule-1": {"service-3#port-1"}, - "route-4#rule-1": {"service-3#port-2"}, - "route-4#rule-2": {"service-4#port-1"}, - "route-5#rule-1": {"service-5"}, - "route-5#rule-2": {"service-5"}, - "route-6#rule-1": {"service-5", "service-6"}, - "route-6#rule-2": {"service-6#port-1"}, - "route-7#rule-1": {"service-7"}, + "gateway-1#listener-1": {"http-route-1"}, + "gateway-1#listener-2": {"http-route-1", "http-route-2"}, + "gateway-2#listener-1": {"http-route-2", "http-route-3"}, + "gateway-3#listener-1": {"http-route-4", "http-route-5"}, + "gateway-3#listener-2": {"http-route-4", "http-route-5"}, + "gateway-4#listener-1": {"http-route-5", "tcp-route-1"}, + "gateway-4#listener-2": {"http-route-5", "tcp-route-1"}, + "gateway-5#listener-1": {"grpc-route-1"}, + "grpc-route-1": {"grpc-route-1#rule-1"}, + "grpc-route-1#rule-1": {"service-7"}, + "http-route-1": {"http-route-1#rule-1", "http-route-1#rule-2"}, + "http-route-2": {"http-route-2#rule-1"}, + "http-route-3": {"http-route-3#rule-1"}, + "http-route-4": {"http-route-4#rule-1", "http-route-4#rule-2"}, + "http-route-5": {"http-route-5#rule-1", "http-route-5#rule-2"}, + "http-route-1#rule-1": {"service-1"}, + "http-route-1#rule-2": {"service-2"}, + "http-route-2#rule-1": {"service-3#port-1"}, + "http-route-3#rule-1": {"service-3#port-1"}, + "http-route-4#rule-1": {"service-3#port-2"}, + "http-route-4#rule-2": {"service-4#port-1"}, + "http-route-5#rule-1": {"service-5"}, + "http-route-5#rule-2": {"service-5"}, + "tcp-route-1": {"tcp-route-1#rule-1", "tcp-route-1#rule-2"}, + "tcp-route-1#rule-1": {"service-5", "service-6"}, + "tcp-route-1#rule-2": {"service-6#port-1"}, "service-1": {"service-1#port-1", "service-1#port-2"}, "service-2": {"service-2#port-1"}, "service-3": {"service-3#port-1", "service-3#port-2"}, @@ -251,6 +260,8 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { ExpandHTTPRouteRules(), WithGRPCRoutes(tc.targetables.GRPCRoutes...), ExpandGRPCRouteRules(), + WithTCPRoutes(tc.targetables.TCPRoutes...), + ExpandTCPRouteRules(), WithServices(tc.targetables.Services...), ExpandServicePorts(), WithGatewayAPITopologyPolicies(tc.policies...), From 34a873fb77985c642653fbc80f71aeb37d23e7b1 Mon Sep 17 00:00:00 2001 From: KevFan Date: Wed, 31 Jul 2024 15:27:28 +0100 Subject: [PATCH 16/21] machinary: add TLSRoute & TLSRouteRules to topology Signed-off-by: KevFan --- machinery/gateway_api_test_helper.go | 69 +++++++--- machinery/gateway_api_topology.go | 183 ++++++++++++++++++++++++- machinery/gateway_api_topology_test.go | 35 +++-- 3 files changed, 257 insertions(+), 30 deletions(-) diff --git a/machinery/gateway_api_test_helper.go b/machinery/gateway_api_test_helper.go index 43e53b4..80e777d 100644 --- a/machinery/gateway_api_test_helper.go +++ b/machinery/gateway_api_test_helper.go @@ -203,12 +203,45 @@ func BuildTCPRoute(f ...func(route *gwapiv1alpha2.TCPRoute)) *gwapiv1alpha2.TCPR return r } +func BuildTLSRoute(f ...func(route *gwapiv1alpha2.TLSRoute)) *gwapiv1alpha2.TLSRoute { + r := &gwapiv1alpha2.TLSRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: gwapiv1.GroupVersion.String(), + Kind: "TLSRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-tls-route", + Namespace: "my-namespace", + }, + Spec: gwapiv1alpha2.TLSRouteSpec{ + CommonRouteSpec: gwapiv1.CommonRouteSpec{ + ParentRefs: []gwapiv1.ParentReference{ + { + Name: "my-gateway", + }, + }, + }, + Rules: []gwapiv1alpha2.TLSRouteRule{ + { + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef()}, + }, + }, + }, + } + for _, fn := range f { + fn(r) + } + + return r +} + type GatewayAPIResources struct { GatewayClasses []*gwapiv1.GatewayClass Gateways []*gwapiv1.Gateway HTTPRoutes []*gwapiv1.HTTPRoute GRPCRoutes []*gwapiv1.GRPCRoute TCPRoutes []*gwapiv1alpha2.TCPRoute + TLSRoutes []*gwapiv1alpha2.TLSRoute Services []*core.Service } @@ -360,23 +393,6 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway }, } }), - BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "http-route-5" - r.Spec.ParentRefs[0].Name = "gateway-3" - r.Spec.ParentRefs = append(r.Spec.ParentRefs, gwapiv1.ParentReference{Name: "gateway-4"}) - r.Spec.Rules = []gwapiv1.HTTPRouteRule{ - { // rule-1 - BackendRefs: []gwapiv1.HTTPBackendRef{BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-5" - })}, - }, - { // rule-2 - BackendRefs: []gwapiv1.HTTPBackendRef{BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-5" - })}, - }, - } - }), }, Services: []*core.Service{ BuildService(func(s *core.Service) { @@ -449,6 +465,25 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway } }), }, + TLSRoutes: []*gwapiv1alpha2.TLSRoute{ + BuildTLSRoute(func(r *gwapiv1alpha2.TLSRoute) { + r.Name = "tls-route-1" + r.Spec.ParentRefs[0].Name = "gateway-3" + r.Spec.ParentRefs = append(r.Spec.ParentRefs, gwapiv1.ParentReference{Name: "gateway-4"}) + r.Spec.Rules = []gwapiv1alpha2.TLSRouteRule{ + { // rule-1 + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-5" + })}, + }, + { // rule-2 + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-5" + })}, + }, + } + }), + }, } for _, f := range funcs { f(&t) diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index cf9ddc9..22a23ba 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -21,6 +21,8 @@ var ( GRPCRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"} TCPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRoute"} TCPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRouteRule"} + TLSRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRoute"} + TLSRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRouteRule"} ServiceGroupKind = schema.GroupKind{Kind: "Service"} ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} ) @@ -31,6 +33,7 @@ type GatewayAPITopologyOptions struct { HTTPRoutes []*HTTPRoute GRPCRoutes []*GRPCRoute TCPRoutes []*TCPRoute + TLSRoutes []*TLSRoute Services []*Service Policies []Policy Objects []Object @@ -40,6 +43,7 @@ type GatewayAPITopologyOptions struct { ExpandHTTPRouteRules bool ExpandGRPCRouteRules bool ExpandTCPRouteRules bool + ExpandTLSRouteRules bool ExpandServicePorts bool } @@ -90,6 +94,15 @@ func WithTCPRoutes(tcpRoutes ...*gwapiv1alpha2.TCPRoute) GatewayAPITopologyOptio } } +// WithTLSRoutes adds TLS routes to the options to initialize a new Gateway API topology. +func WithTLSRoutes(tlsRoutes ...*gwapiv1alpha2.TLSRoute) GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.TLSRoutes = append(o.TLSRoutes, lo.Map(tlsRoutes, func(tlsRoute *gwapiv1alpha2.TLSRoute, _ int) *TLSRoute { + return &TLSRoute{TLSRoute: tlsRoute} + })...) + } +} + // WithServices adds services to the options to initialize a new Gateway API topology. func WithServices(services ...*core.Service) GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -150,6 +163,13 @@ func ExpandTCPRouteRules() GatewayAPITopologyOptionsFunc { } } +// ExpandTLSRouteRules adds targetable TLS route rules to the options to initialize a new Gateway API topology. +func ExpandTLSRouteRules() GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.ExpandTLSRouteRules = true + } +} + // ExpandServicePorts adds targetable service ports to the options to initialize a new Gateway API topology. func ExpandServicePorts() GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -181,6 +201,7 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { WithTargetables(o.HTTPRoutes...), WithTargetables(o.GRPCRoutes...), WithTargetables(o.TCPRoutes...), + WithTargetables(o.TLSRoutes...), WithTargetables(o.Services...), WithLinks(o.Links...), WithLinks(LinkGatewayClassToGatewayFunc(o.GatewayClasses)), // GatewayClass -> Gateway @@ -194,11 +215,13 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { LinkListenerToHTTPRouteFunc(o.Gateways, listeners), // Listener -> HTTPRoute LinkListenerToGRPCRouteFunc(o.Gateways, listeners), // Listener -> GRPCRoute LinkListenerToTCPRouteFunc(o.Gateways, listeners), // Listener -> TCPRoute + LinkListenerToTLSRouteFunc(o.Gateways, listeners), // Listener -> TLSRoute )) } else { opts = append(opts, WithLinks(LinkGatewayToHTTPRouteFunc(o.Gateways))) // Gateway -> HTTPRoute opts = append(opts, WithLinks(LinkGatewayToGRPCRouteFunc(o.Gateways))) // Gateway -> GRPCRoute opts = append(opts, WithLinks(LinkGatewayToTCPRouteFunc(o.Gateways))) // Gateway -> TCPRoute + opts = append(opts, WithLinks(LinkGatewayToTLSRouteFunc(o.Gateways))) // Gateway -> TLSRoute } if o.ExpandHTTPRouteRules { @@ -279,6 +302,32 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { } } + if o.ExpandTLSRouteRules { + tlsRouteRules := lo.FlatMap(o.TLSRoutes, TLSRouteRulesFromTLSRouteFunc) + opts = append(opts, WithTargetables(tlsRouteRules...)) + opts = append(opts, WithLinks(LinkTLSRouteToTLSRouteRuleFunc())) + + if o.ExpandServicePorts { + servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) + opts = append(opts, WithTargetables(servicePorts...)) + opts = append(opts, WithLinks( + LinkTLSRouteRuleToServicePortFunc(tlsRouteRules), // TLSRoute -> ServicePort + LinkTLSRouteRuleToServiceFunc(tlsRouteRules, true), // TLSRoute -> Service + )) + } else { + opts = append(opts, WithLinks(LinkTLSRouteToServiceFunc(o.TLSRoutes, false))) // TLSRoute -> Service + } + } else { + if o.ExpandServicePorts { + opts = append(opts, WithLinks( + LinkTLSRouteToServicePortFunc(o.TLSRoutes), // TLSRoute -> ServicePort + LinkTLSRouteToServiceFunc(o.TLSRoutes, true), // TLSRoute -> Service + )) + } else { + opts = append(opts, WithLinks(LinkTLSRouteToServiceFunc(o.TLSRoutes, false))) // TLSRoute -> Service + } + } + if o.ExpandServicePorts { opts = append(opts, WithLinks(LinkServiceToServicePortFunc())) // Service -> ServicePort } @@ -329,6 +378,17 @@ func TCPRouteRulesFromTCPRouteFunc(tcpRoute *TCPRoute, _ int) []*TCPRouteRule { }) } +// TLSRouteRulesFromTLSRouteFunc returns a list of targetable TCPRouteRules from a targetable TLSRoute. +func TLSRouteRulesFromTLSRouteFunc(tlsRoute *TLSRoute, _ int) []*TLSRouteRule { + return lo.Map(tlsRoute.Spec.Rules, func(rule gwapiv1alpha2.TLSRouteRule, i int) *TLSRouteRule { + return &TLSRouteRule{ + TLSRouteRule: &rule, + TLSRoute: tlsRoute, + Name: gwapiv1.SectionName(fmt.Sprintf("rule-%d", i+1)), + } + }) +} + // ServicePortsFromBackendFunc returns a list of targetable service ports from a targetable Service. func ServicePortsFromBackendFunc(service *Service, _ int) []*ServicePort { return lo.Map(service.Spec.Ports, func(port core.ServicePort, _ int) *ServicePort { @@ -397,6 +457,19 @@ func LinkGatewayToTCPRouteFunc(gateways []*Gateway) LinkFunc { } } +// LinkGatewayToTLSRouteFunc returns a link function that teaches a topology how to link TLSRoute's from known +// Gateway's, based on the TLSRoute's `parentRefs` field. +func LinkGatewayToTLSRouteFunc(gateways []*Gateway) LinkFunc { + return LinkFunc{ + From: GatewayGroupKind, + To: TLSRouteGroupKind, + Func: func(child Object) []Object { + tlsRoute := child.(*TLSRoute) + return lo.FilterMap(tlsRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, tlsRoute.Namespace)) + }, + } +} + // findGatewayFromParentRefFunc is a common function to find a Gateway from a xRoute's `parentRef` field func findGatewayFromParentRefFunc(gateways []*Gateway, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { return func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { @@ -470,6 +543,21 @@ func LinkListenerToTCPRouteFunc(gateways []*Gateway, listeners []*Listener) Link } } +// LinkListenerToTLSRouteFunc returns a link function that teaches a topology how to link GRPCRoutes from known +// Gateways and gateway Listeners, based on the TLSRoute's `parentRefs` field. +// The function links a specific Listener of a Gateway to the TLSRoute when the `sectionName` field of the parent +// reference is present, otherwise all Listeners of the parent Gateway are linked to the TLSRoute. +func LinkListenerToTLSRouteFunc(gateways []*Gateway, listeners []*Listener) LinkFunc { + return LinkFunc{ + From: ListenerGroupKind, + To: TLSRouteGroupKind, + Func: func(child Object) []Object { + tlsRoute := child.(*TLSRoute) + return lo.FlatMap(tlsRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, tlsRoute.Namespace)) + }, + } +} + // findListenerFromParentRefFunc is a common function to find a gateway Listener from a xRoute's `parentRef` field func findListenerFromParentRefFunc(gateways []*Gateway, listeners []*Listener, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) []Object { return func(parentRef gwapiv1.ParentReference, _ int) []Object { @@ -765,7 +853,7 @@ func LinkTCPRouteRuleToServiceFunc(routeRules []*TCPRouteRule, strict bool) Link // The link function disregards backend references that do not specify a port number. func LinkTCPRouteRuleToServicePortFunc(routeRules []*TCPRouteRule) LinkFunc { return LinkFunc{ - From: TCPRouteGroupKind, + From: TCPRouteRuleGroupKind, To: ServicePortGroupKind, Func: func(child Object) []Object { servicePort := child.(*ServicePort) @@ -779,6 +867,99 @@ func LinkTCPRouteRuleToServicePortFunc(routeRules []*TCPRouteRule) LinkFunc { } } +// LinkTLSRouteToServiceFunc returns a link function that teaches a topology how to link Services from known +// TLSRoutes, based on the TLSRoute's `backendRefs` fields. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkTLSRouteToServiceFunc(routes []*TLSRoute, strict bool) LinkFunc { + return LinkFunc{ + From: TLSRouteGroupKind, + To: ServiceGroupKind, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routes, func(route *TLSRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1alpha2.TLSRouteRule) bool { + backendRefs := lo.Filter(rule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return !strict || backendRef.Port == nil + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, route.Namespace)) + }) + }) + }, + } +} + +// LinkTLSRouteToServicePortFunc returns a link function that teaches a topology how to link services ports from known +// TLSRoutes, based on the TLSRoute's `backendRefs` fields. +// The link function disregards backend references that do not specify a port number. +func LinkTLSRouteToServicePortFunc(routes []*TLSRoute) LinkFunc { + return LinkFunc{ + From: TLSRouteGroupKind, + To: ServicePortGroupKind, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routes, func(route *TLSRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1alpha2.TLSRouteRule) bool { + backendRefs := lo.Filter(rule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, route.Namespace)) + }) + }) + }, + } +} + +// LinkTLSRouteToTLSRouteRuleFunc returns a link function that teaches a topology how to link TLSRouteRule from the +// TLSRoute they are strongly related to. +func LinkTLSRouteToTLSRouteRuleFunc() LinkFunc { + return LinkFunc{ + From: TLSRouteGroupKind, + To: TLSRouteRuleGroupKind, + Func: func(child Object) []Object { + tlsRouteRule := child.(*TLSRouteRule) + return []Object{tlsRouteRule.TLSRoute} + }, + } +} + +// LinkTLSRouteRuleToServiceFunc returns a link function that teaches a topology how to link Services from known +// TLSRouteRules, based on the TLSRouteRule's `backendRefs` field. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkTLSRouteRuleToServiceFunc(routeRules []*TLSRouteRule, strict bool) LinkFunc { + return LinkFunc{ + From: TLSRouteRuleGroupKind, + To: ServiceGroupKind, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routeRules, func(routeRule *TLSRouteRule, _ int) (Object, bool) { + backendRefs := lo.Filter(routeRule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return !strict || backendRef.Port == nil + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, routeRule.TLSRoute.Namespace)) + }) + }, + } +} + +// LinkTLSRouteRuleToServicePortFunc returns a link function that teaches a topology how to link services ports from +// known TLSRouteRules, based on the TLSRouteRule's `backendRefs` field. +// The link function disregards backend references that do not specify a port number. +func LinkTLSRouteRuleToServicePortFunc(routeRules []*TLSRouteRule) LinkFunc { + return LinkFunc{ + From: TLSRouteRuleGroupKind, + To: ServicePortGroupKind, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routeRules, func(routeRule *TLSRouteRule, _ int) (Object, bool) { + backendRefs := lo.Filter(routeRule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, routeRule.TLSRoute.Namespace)) + }) + }, + } +} + // LinkServiceToServicePortFunc returns a link function that teaches a topology how to link service ports from the // Service they are strongly related to. func LinkServiceToServicePortFunc() LinkFunc { diff --git a/machinery/gateway_api_topology_test.go b/machinery/gateway_api_topology_test.go index d6e1f21..8ec23ec 100644 --- a/machinery/gateway_api_topology_test.go +++ b/machinery/gateway_api_topology_test.go @@ -45,15 +45,17 @@ func TestGatewayAPITopology(t *testing.T) { HTTPRoutes: []*gwapiv1.HTTPRoute{BuildHTTPRoute()}, GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, TCPRoutes: []*gwapiv1alpha2.TCPRoute{BuildTCPRoute()}, + TLSRoutes: []*gwapiv1alpha2.TLSRoute{BuildTLSRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, - "my-gateway": {"my-http-route", "my-grpc-route", "my-tcp-route"}, + "my-gateway": {"my-http-route", "my-grpc-route", "my-tcp-route", "my-tls-route"}, "my-grpc-route": {"my-service"}, "my-http-route": {"my-service"}, "my-tcp-route": {"my-service"}, + "my-tls-route": {"my-service"}, }, }, { @@ -64,15 +66,15 @@ func TestGatewayAPITopology(t *testing.T) { "gatewayclass-2": {"gateway-4", "gateway-5"}, "gateway-1": {"http-route-1", "http-route-2"}, "gateway-2": {"http-route-2", "http-route-3"}, - "gateway-3": {"http-route-4", "http-route-5"}, - "gateway-4": {"http-route-5", "tcp-route-1"}, + "gateway-3": {"http-route-4", "tls-route-1"}, + "gateway-4": {"tls-route-1", "tcp-route-1"}, "gateway-5": {"grpc-route-1"}, "grpc-route-1": {"service-7"}, "http-route-1": {"service-1", "service-2"}, "http-route-2": {"service-3"}, "http-route-3": {"service-3"}, "http-route-4": {"service-3", "service-4"}, - "http-route-5": {"service-5"}, + "tls-route-1": {"service-5"}, "tcp-route-1": {"service-5", "service-6"}, }, }, @@ -86,6 +88,7 @@ func TestGatewayAPITopology(t *testing.T) { httpRoutes := lo.Map(tc.targetables.HTTPRoutes, func(httpRoute *gwapiv1.HTTPRoute, _ int) *HTTPRoute { return &HTTPRoute{HTTPRoute: httpRoute} }) grpcRoutes := lo.Map(tc.targetables.GRPCRoutes, func(grpcRoute *gwapiv1.GRPCRoute, _ int) *GRPCRoute { return &GRPCRoute{GRPCRoute: grpcRoute} }) tcpRoutes := lo.Map(tc.targetables.TCPRoutes, func(tcpRoute *gwapiv1alpha2.TCPRoute, _ int) *TCPRoute { return &TCPRoute{TCPRoute: tcpRoute} }) + tlsRoutes := lo.Map(tc.targetables.TLSRoutes, func(tlsRoute *gwapiv1alpha2.TLSRoute, _ int) *TLSRoute { return &TLSRoute{TLSRoute: tlsRoute} }) services := lo.Map(tc.targetables.Services, func(service *core.Service, _ int) *Service { return &Service{Service: service} }) topology := NewTopology( @@ -95,14 +98,17 @@ func TestGatewayAPITopology(t *testing.T) { WithTargetables(services...), WithTargetables(grpcRoutes...), WithTargetables(tcpRoutes...), + WithTargetables(tlsRoutes...), WithLinks( LinkGatewayClassToGatewayFunc(gatewayClasses), LinkGatewayToHTTPRouteFunc(gateways), LinkGatewayToGRPCRouteFunc(gateways), LinkGatewayToTCPRouteFunc(gateways), + LinkGatewayToTLSRouteFunc(gateways), LinkHTTPRouteToServiceFunc(httpRoutes, false), LinkGRPCRouteToServiceFunc(grpcRoutes, false), LinkTCPRouteToServiceFunc(tcpRoutes, false), + LinkTLSRouteToServiceFunc(tlsRoutes, false), ), WithPolicies(tc.policies...), ) @@ -147,19 +153,22 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { HTTPRoutes: []*gwapiv1.HTTPRoute{BuildHTTPRoute()}, GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, TCPRoutes: []*gwapiv1alpha2.TCPRoute{BuildTCPRoute()}, + TLSRoutes: []*gwapiv1alpha2.TLSRoute{BuildTLSRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, "my-gateway": {"my-gateway#my-listener"}, - "my-gateway#my-listener": {"my-http-route", "my-grpc-route", "my-tcp-route"}, + "my-gateway#my-listener": {"my-http-route", "my-grpc-route", "my-tcp-route", "my-tls-route"}, "my-grpc-route": {"my-grpc-route#rule-1"}, "my-grpc-route#rule-1": {"my-service"}, "my-http-route": {"my-http-route#rule-1"}, "my-http-route#rule-1": {"my-service"}, "my-tcp-route": {"my-tcp-route#rule-1"}, "my-tcp-route#rule-1": {"my-service"}, + "my-tls-route": {"my-tls-route#rule-1"}, + "my-tls-route#rule-1": {"my-service"}, "my-service": {"my-service#http"}, }, }, @@ -217,10 +226,10 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { "gateway-1#listener-1": {"http-route-1"}, "gateway-1#listener-2": {"http-route-1", "http-route-2"}, "gateway-2#listener-1": {"http-route-2", "http-route-3"}, - "gateway-3#listener-1": {"http-route-4", "http-route-5"}, - "gateway-3#listener-2": {"http-route-4", "http-route-5"}, - "gateway-4#listener-1": {"http-route-5", "tcp-route-1"}, - "gateway-4#listener-2": {"http-route-5", "tcp-route-1"}, + "gateway-3#listener-1": {"http-route-4", "tls-route-1"}, + "gateway-3#listener-2": {"http-route-4", "tls-route-1"}, + "gateway-4#listener-1": {"tls-route-1", "tcp-route-1"}, + "gateway-4#listener-2": {"tls-route-1", "tcp-route-1"}, "gateway-5#listener-1": {"grpc-route-1"}, "grpc-route-1": {"grpc-route-1#rule-1"}, "grpc-route-1#rule-1": {"service-7"}, @@ -228,15 +237,15 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { "http-route-2": {"http-route-2#rule-1"}, "http-route-3": {"http-route-3#rule-1"}, "http-route-4": {"http-route-4#rule-1", "http-route-4#rule-2"}, - "http-route-5": {"http-route-5#rule-1", "http-route-5#rule-2"}, "http-route-1#rule-1": {"service-1"}, "http-route-1#rule-2": {"service-2"}, "http-route-2#rule-1": {"service-3#port-1"}, "http-route-3#rule-1": {"service-3#port-1"}, "http-route-4#rule-1": {"service-3#port-2"}, "http-route-4#rule-2": {"service-4#port-1"}, - "http-route-5#rule-1": {"service-5"}, - "http-route-5#rule-2": {"service-5"}, + "tls-route-1": {"tls-route-1#rule-1", "tls-route-1#rule-2"}, + "tls-route-1#rule-1": {"service-5"}, + "tls-route-1#rule-2": {"service-5"}, "tcp-route-1": {"tcp-route-1#rule-1", "tcp-route-1#rule-2"}, "tcp-route-1#rule-1": {"service-5", "service-6"}, "tcp-route-1#rule-2": {"service-6#port-1"}, @@ -262,6 +271,8 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { ExpandGRPCRouteRules(), WithTCPRoutes(tc.targetables.TCPRoutes...), ExpandTCPRouteRules(), + WithTLSRoutes(tc.targetables.TLSRoutes...), + ExpandTLSRouteRules(), WithServices(tc.targetables.Services...), ExpandServicePorts(), WithGatewayAPITopologyPolicies(tc.policies...), From dcd153b20ffb8527f6e16b2aad49ca9beccf5a8c Mon Sep 17 00:00:00 2001 From: KevFan Date: Thu, 1 Aug 2024 09:44:39 +0100 Subject: [PATCH 17/21] machinary: add UDPRoute & UDPRouteRules to topology Signed-off-by: KevFan --- machinery/gateway_api_test_helper.go | 147 +++++++++++------- machinery/gateway_api_topology.go | 199 ++++++++++++++++++++++++- machinery/gateway_api_topology_test.go | 32 ++-- 3 files changed, 305 insertions(+), 73 deletions(-) diff --git a/machinery/gateway_api_test_helper.go b/machinery/gateway_api_test_helper.go index 80e777d..9a1f85a 100644 --- a/machinery/gateway_api_test_helper.go +++ b/machinery/gateway_api_test_helper.go @@ -235,6 +235,38 @@ func BuildTLSRoute(f ...func(route *gwapiv1alpha2.TLSRoute)) *gwapiv1alpha2.TLSR return r } +func BuildUDPRoute(f ...func(route *gwapiv1alpha2.UDPRoute)) *gwapiv1alpha2.UDPRoute { + r := &gwapiv1alpha2.UDPRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: gwapiv1.GroupVersion.String(), + Kind: "UDPRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-udp-route", + Namespace: "my-namespace", + }, + Spec: gwapiv1alpha2.UDPRouteSpec{ + CommonRouteSpec: gwapiv1.CommonRouteSpec{ + ParentRefs: []gwapiv1.ParentReference{ + { + Name: "my-gateway", + }, + }, + }, + Rules: []gwapiv1alpha2.UDPRouteRule{ + { + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef()}, + }, + }, + }, + } + for _, fn := range f { + fn(r) + } + + return r +} + type GatewayAPIResources struct { GatewayClasses []*gwapiv1.GatewayClass Gateways []*gwapiv1.Gateway @@ -242,49 +274,50 @@ type GatewayAPIResources struct { GRPCRoutes []*gwapiv1.GRPCRoute TCPRoutes []*gwapiv1alpha2.TCPRoute TLSRoutes []*gwapiv1alpha2.TLSRoute + UDPRoutes []*gwapiv1alpha2.UDPRoute Services []*core.Service } // BuildComplexGatewayAPITopology returns a set of Gateway API resources organized : // -// ┌────────────────┐ ┌────────────────┐ -// │ gatewayclass-1 │ │ gatewayclass-2 │ -// └────────────────┘ └────────────────┘ -// ▲ ▲ -// │ │ -// ┌─────────────────────────┼──────────────────────────┐ ┌────────────┴─────────────┐ -// │ │ │ │ │ -// ┌───────────────┴───────────────┐ ┌───────┴────────┐ ┌───────────────┴───────────────┐ ┌──────────────┴────────────────┐ ┌───────┴────────┐ -// │ gateway-1 │ │ gateway-2 │ │ gateway-3 │ │ gateway-4 │ │ gateway-5 │ -// │ │ │ │ │ │ │ │ │ │ -// │ ┌────────────┐ ┌────────────┐ │ │ ┌────────────┐ │ │ ┌────────────┐ ┌────────────┐ │ │ ┌────────────┐ ┌────────────┐ │ │ ┌────────────┐ │ -// │ │ listener-1 │ │ listener-2 │ │ │ │ listener-1 │ │ │ │ listener-1 │ │ listener-2 │ │ │ │ listener-1 │ │ listener-2 │ │ │ │ listener-1 │ │ -// │ └────────────┘ └────────────┘ │ │ └────────────┘ │ │ └────────────┘ └────────────┘ │ │ └────────────┘ └────────────┘ │ │ └────────────┘ │ -// │ ▲ │ │ ▲ │ │ │ │ │ │ │ -// └────────────────────────┬──────┘ └──────┬─────────┘ └───────────────────────────────┘ └───────────────────────────────┘ └────────────────┘ -// ▲ │ │ ▲ ▲ ▲ ▲ ▲ ▲ -// │ │ │ │ │ │ │ │ │ -// │ └───────┬───────┘ │ │ └────────────┬─────────────┘ │ │ -// │ │ │ │ │ │ │ -// ┌───────────┴───────────┐ ┌──────┴─────┐ ┌─────┴──────┐ ┌───────────┴───────────┐ ┌───────────┴───────────┐ ┌───────────┴───────────┐ ┌─────┴──────┐ -// │ h-route-1 │ │ h-route-2 │ │ h-route-3 │ │ h-route-4 │ │ h-route-5 │ │ tcp-route-1 │ │ g-route-1 │ -// │ │ │ │ │ │ │ │ │ │ │ │ │ │ -// │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ -// │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ │ │ rule-1 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ -// │ └────┬───┘ └────┬───┘ │ │ └────┬───┘ │ │ └───┬────┘ │ │ └─┬──────┘ └───┬────┘ │ │ └───┬────┘ └────┬───┘ │ │ └─┬────┬─┘ └────┬───┘ │ │ └────┬───┘ │ -// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ -// └──────┼──────────┼─────┘ └──────┼─────┘ └─────┼──────┘ └───┼────────────┼──────┘ └─────┼───────────┼─────┘ └───┼────┼────────┼─────┘ └──────┼─────┘ -// │ │ │ │ │ │ │ │ │ │ │ │ -// │ │ └─────────────┤ │ │ └───────────┴───────────┘ │ │ │ -// ▼ ▼ │ │ │ ▼ ▼ │ ▼ -// ┌───────────────────────┐ ┌────────────┐ ┌──────┴────────────┴───┐ ┌─────┴──────┐ ┌────────────┐ ┌─────────┴──┐ ┌────────────┐ -// │ │ │ │ │ ▼ ▼ │ │ ▼ │ │ │ │ ▼ │ │ │ -// │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ -// │ │ port-1 │ │ port-2 │ │ │ │ port-1 │ │ │ │ port-1 │ │ port-2 │ │ │ │ port-1 │ │ │ │ port-1 │ │ │ │ port-1 │ │ │ │ port-1 │ │ -// │ └────────┘ └────────┘ │ │ └────────┘ │ │ └────────┘ └────────┘ │ │ └────────┘ │ │ └────────┘ │ │ └────────┘ │ │ └────────┘ │ -// │ │ │ │ │ │ │ │ │ │ │ │ │ │ -// │ service-1 │ │ service-2 │ │ service-3 │ │ service-4 │ │ service-5 │ │ service-6 │ │ service-7 │ -// └───────────────────────┘ └────────────┘ └───────────────────────┘ └────────────┘ └────────────┘ └────────────┘ └────────────┘ +// ┌────────────────┐ ┌────────────────┐ +// │ gatewayclass-1 │ │ gatewayclass-2 │ +// └────────────────┘ └────────────────┘ +// ▲ ▲ +// │ │ +// ┌─────────────────────────┼──────────────────────────┐ ┌────────────┴─────────────┐ +// │ │ │ │ │ +// ┌───────────────┴───────────────┐ ┌───────┴────────┐ ┌───────────────┴───────────────┐ ┌──────────────┴────────────────┐ ┌───────┴────────┐ +// │ gateway-1 │ │ gateway-2 │ │ gateway-3 │ │ gateway-4 │ │ gateway-5 │ +// │ │ │ │ │ │ │ │ │ │ +// │ ┌────────────┐ ┌────────────┐ │ │ ┌────────────┐ │ │ ┌────────────┐ ┌────────────┐ │ │ ┌────────────┐ ┌────────────┐ │ │ ┌────────────┐ │ +// │ │ listener-1 │ │ listener-2 │ │ │ │ listener-1 │ │ │ │ listener-1 │ │ listener-2 │ │ │ │ listener-1 │ │ listener-2 │ │ │ │ listener-1 │ │ +// │ └────────────┘ └────────────┘ │ │ └────────────┘ │ │ └────────────┘ └────────────┘ │ │ └────────────┘ └────────────┘ │ │ └────────────┘ │ +// │ ▲ │ │ ▲ │ │ │ │ │ │ │ +// └────────────────────────┬──────┘ └──────┬─────────┘ └───────────────────────────────┘ └───────────────────────────────┘ └────────────────┘ +// ▲ │ │ ▲ ▲ ▲ ▲ ▲ ▲ +// │ │ │ │ │ │ │ │ │ +// │ └───────┬───────┘ │ │ └──────────────┬─────────────┘ │ │ +// │ │ │ │ │ │ │ +// ┌───────────┴───────────┐ ┌──────┴───────┐ ┌─────┴────────┐ ┌─────────┴─────────────┐ ┌───────────┴───────────┐ ┌───────────┴───────────┐ ┌─────┴────────┐ +// │ http-route-1 │ │ http-route-2 │ │ http-route-3 │ │ udp-route-1 │ │ tls-route-1 │ │ tcp-route-1 │ │ grpc-route-1 │ +// │ │ │ │ │ │ │ │ │ │ │ │ │ │ +// │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ +// │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ │ │ rule-1 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ rule-2 │ │ │ │ rule-1 │ │ +// │ └────┬───┘ └─────┬──┘ │ │ └────┬───┘ │ │ └───┬────┘ │ │ └─┬──────┘ └───┬────┘ │ │ └───┬────┘ └────┬───┘ │ │ └─┬────┬─┘ └────┬───┘ │ │ └────┬───┘ │ +// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +// └──────┼───────────┼────┘ └──────┼───────┘ └──────┼───────┘ └───┼────────────┼──────┘ └─────┼───────────┼─────┘ └───┼────┼────────┼─────┘ └──────┼───────┘ +// │ │ │ │ │ │ │ │ │ │ │ │ +// │ │ └────────────────┤ │ │ └───────────┴───────────┘ │ │ │ +// ▼ ▼ │ │ │ ▼ ▼ │ ▼ +// ┌───────────────────────┐ ┌────────────┐ ┌───────┴─────────────┴───┐ ┌─────┴──────┐ ┌────────────┐ ┌─────────┴──┐ ┌────────────┐ +// │ │ │ │ │ ▼ ▼ │ │ ▼ │ │ │ │ ▼ │ │ │ +// │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │ +// │ │ port-1 │ │ port-2 │ │ │ │ port-1 │ │ │ │ port-1 │ │ port-2 │ │ │ │ port-1 │ │ │ │ port-1 │ │ │ │ port-1 │ │ │ │ port-1 │ │ +// │ └────────┘ └────────┘ │ │ └────────┘ │ │ └────────┘ └────────┘ │ │ └────────┘ │ │ └────────┘ │ │ └────────┘ │ │ └────────┘ │ +// │ │ │ │ │ │ │ │ │ │ │ │ │ │ +// │ service-1 │ │ service-2 │ │ service-3 │ │ service-4 │ │ service-5 │ │ service-6 │ │ service-7 │ +// └───────────────────────┘ └────────────┘ └─────────────────────────┘ └────────────┘ └────────────┘ └────────────┘ └────────────┘ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) GatewayAPIResources { t := GatewayAPIResources{ GatewayClasses: []*gwapiv1.GatewayClass{ @@ -375,24 +408,6 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway backendRef.Port = ptr.To(gwapiv1.PortNumber(80)) // port-1 }) }), - BuildHTTPRoute(func(r *gwapiv1.HTTPRoute) { - r.Name = "http-route-4" - r.Spec.ParentRefs[0].Name = "gateway-3" - r.Spec.Rules = []gwapiv1.HTTPRouteRule{ - { // rule-1 - BackendRefs: []gwapiv1.HTTPBackendRef{BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-3" - backendRef.Port = ptr.To(gwapiv1.PortNumber(443)) // port-2 - })}, - }, - { // rule-2 - BackendRefs: []gwapiv1.HTTPBackendRef{BuildHTTPBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { - backendRef.Name = "service-4" - backendRef.Port = ptr.To(gwapiv1.PortNumber(80)) // port-1 - })}, - }, - } - }), }, Services: []*core.Service{ BuildService(func(s *core.Service) { @@ -484,6 +499,26 @@ func BuildComplexGatewayAPITopology(funcs ...func(*GatewayAPIResources)) Gateway } }), }, + UDPRoutes: []*gwapiv1alpha2.UDPRoute{ + BuildUDPRoute(func(r *gwapiv1alpha2.UDPRoute) { + r.Name = "udp-route-1" + r.Spec.ParentRefs[0].Name = "gateway-3" + r.Spec.Rules = []gwapiv1alpha2.UDPRouteRule{ + { // rule-1 + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-3" + backendRef.Port = ptr.To(gwapiv1.PortNumber(443)) // port-2 + })}, + }, + { // rule-2 + BackendRefs: []gwapiv1.BackendRef{BuildBackendRef(func(backendRef *gwapiv1.BackendObjectReference) { + backendRef.Name = "service-4" + backendRef.Port = ptr.To(gwapiv1.PortNumber(80)) // port-1 + })}, + }, + } + }), + }, } for _, f := range funcs { f(&t) diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index 22a23ba..c924e47 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -23,6 +23,8 @@ var ( TCPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRouteRule"} TLSRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRoute"} TLSRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRouteRule"} + UDPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRoute"} + UDPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRouteRule"} ServiceGroupKind = schema.GroupKind{Kind: "Service"} ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} ) @@ -34,6 +36,7 @@ type GatewayAPITopologyOptions struct { GRPCRoutes []*GRPCRoute TCPRoutes []*TCPRoute TLSRoutes []*TLSRoute + UDPRoutes []*UDPRoute Services []*Service Policies []Policy Objects []Object @@ -44,6 +47,7 @@ type GatewayAPITopologyOptions struct { ExpandGRPCRouteRules bool ExpandTCPRouteRules bool ExpandTLSRouteRules bool + ExpandUDPRouteRules bool ExpandServicePorts bool } @@ -103,6 +107,15 @@ func WithTLSRoutes(tlsRoutes ...*gwapiv1alpha2.TLSRoute) GatewayAPITopologyOptio } } +// WithUDPRoutes adds UDP routes to the options to initialize a new Gateway API topology. +func WithUDPRoutes(udpRoutes ...*gwapiv1alpha2.UDPRoute) GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.UDPRoutes = append(o.UDPRoutes, lo.Map(udpRoutes, func(udpRoute *gwapiv1alpha2.UDPRoute, _ int) *UDPRoute { + return &UDPRoute{UDPRoute: udpRoute} + })...) + } +} + // WithServices adds services to the options to initialize a new Gateway API topology. func WithServices(services ...*core.Service) GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -170,6 +183,13 @@ func ExpandTLSRouteRules() GatewayAPITopologyOptionsFunc { } } +// ExpandUDPRouteRules adds targetable UDP route rules to the options to initialize a new Gateway API topology. +func ExpandUDPRouteRules() GatewayAPITopologyOptionsFunc { + return func(o *GatewayAPITopologyOptions) { + o.ExpandUDPRouteRules = true + } +} + // ExpandServicePorts adds targetable service ports to the options to initialize a new Gateway API topology. func ExpandServicePorts() GatewayAPITopologyOptionsFunc { return func(o *GatewayAPITopologyOptions) { @@ -202,6 +222,7 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { WithTargetables(o.GRPCRoutes...), WithTargetables(o.TCPRoutes...), WithTargetables(o.TLSRoutes...), + WithTargetables(o.UDPRoutes...), WithTargetables(o.Services...), WithLinks(o.Links...), WithLinks(LinkGatewayClassToGatewayFunc(o.GatewayClasses)), // GatewayClass -> Gateway @@ -216,12 +237,16 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { LinkListenerToGRPCRouteFunc(o.Gateways, listeners), // Listener -> GRPCRoute LinkListenerToTCPRouteFunc(o.Gateways, listeners), // Listener -> TCPRoute LinkListenerToTLSRouteFunc(o.Gateways, listeners), // Listener -> TLSRoute + LinkListenerToUDPRouteFunc(o.Gateways, listeners), // Listener -> UDPRoute )) } else { - opts = append(opts, WithLinks(LinkGatewayToHTTPRouteFunc(o.Gateways))) // Gateway -> HTTPRoute - opts = append(opts, WithLinks(LinkGatewayToGRPCRouteFunc(o.Gateways))) // Gateway -> GRPCRoute - opts = append(opts, WithLinks(LinkGatewayToTCPRouteFunc(o.Gateways))) // Gateway -> TCPRoute - opts = append(opts, WithLinks(LinkGatewayToTLSRouteFunc(o.Gateways))) // Gateway -> TLSRoute + opts = append(opts, WithLinks( + LinkGatewayToHTTPRouteFunc(o.Gateways), // Gateway -> HTTPRoute + LinkGatewayToGRPCRouteFunc(o.Gateways), // Gateway -> GRPCRoute + LinkGatewayToTCPRouteFunc(o.Gateways), // Gateway -> TCPRoute + LinkGatewayToTLSRouteFunc(o.Gateways), // Gateway -> TLSRoute + LinkGatewayToUDPRouteFunc(o.Gateways), // Gateway -> UDPRoute + )) } if o.ExpandHTTPRouteRules { @@ -311,8 +336,8 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks( - LinkTLSRouteRuleToServicePortFunc(tlsRouteRules), // TLSRoute -> ServicePort - LinkTLSRouteRuleToServiceFunc(tlsRouteRules, true), // TLSRoute -> Service + LinkTLSRouteRuleToServicePortFunc(tlsRouteRules), // TLSRouteRule -> ServicePort + LinkTLSRouteRuleToServiceFunc(tlsRouteRules, true), // TLSRouteRule -> Service )) } else { opts = append(opts, WithLinks(LinkTLSRouteToServiceFunc(o.TLSRoutes, false))) // TLSRoute -> Service @@ -328,6 +353,32 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { } } + if o.ExpandUDPRouteRules { + udpRouteRules := lo.FlatMap(o.UDPRoutes, UDPRouteRulesFromUDPRouteFunc) + opts = append(opts, WithTargetables(udpRouteRules...)) + opts = append(opts, WithLinks(LinkUDPRouteToUDPRouteRuleFunc())) + + if o.ExpandServicePorts { + servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) + opts = append(opts, WithTargetables(servicePorts...)) + opts = append(opts, WithLinks( + LinkUDPRouteRuleToServicePortFunc(udpRouteRules), // UDPRouteRule -> ServicePort + LinkUDPRouteRuleToServiceFunc(udpRouteRules, true), // UDPRouteRule -> Service + )) + } else { + opts = append(opts, WithLinks(LinkUDPRouteToServiceFunc(o.UDPRoutes, false))) // UDPRoute -> Service + } + } else { + if o.ExpandServicePorts { + opts = append(opts, WithLinks( + LinkUDPRouteToServicePortFunc(o.UDPRoutes), // UDPRoute -> ServicePort + LinkUDPRouteToServiceFunc(o.UDPRoutes, true), // UDPRoute -> Service + )) + } else { + opts = append(opts, WithLinks(LinkUDPRouteToServiceFunc(o.UDPRoutes, false))) // UDPRoute -> Service + } + } + if o.ExpandServicePorts { opts = append(opts, WithLinks(LinkServiceToServicePortFunc())) // Service -> ServicePort } @@ -389,6 +440,17 @@ func TLSRouteRulesFromTLSRouteFunc(tlsRoute *TLSRoute, _ int) []*TLSRouteRule { }) } +// UDPRouteRulesFromUDPRouteFunc returns a list of targetable UDPRouteRules from a targetable UDPRoute. +func UDPRouteRulesFromUDPRouteFunc(udpRoute *UDPRoute, _ int) []*UDPRouteRule { + return lo.Map(udpRoute.Spec.Rules, func(rule gwapiv1alpha2.UDPRouteRule, i int) *UDPRouteRule { + return &UDPRouteRule{ + UDPRouteRule: &rule, + UDPRoute: udpRoute, + Name: gwapiv1.SectionName(fmt.Sprintf("rule-%d", i+1)), + } + }) +} + // ServicePortsFromBackendFunc returns a list of targetable service ports from a targetable Service. func ServicePortsFromBackendFunc(service *Service, _ int) []*ServicePort { return lo.Map(service.Spec.Ports, func(port core.ServicePort, _ int) *ServicePort { @@ -470,6 +532,19 @@ func LinkGatewayToTLSRouteFunc(gateways []*Gateway) LinkFunc { } } +// LinkGatewayToUDPRouteFunc returns a link function that teaches a topology how to link UDPRoute's from known +// Gateway's, based on the UDPRoute's `parentRefs` field. +func LinkGatewayToUDPRouteFunc(gateways []*Gateway) LinkFunc { + return LinkFunc{ + From: GatewayGroupKind, + To: UDPRouteGroupKind, + Func: func(child Object) []Object { + udpRoute := child.(*UDPRoute) + return lo.FilterMap(udpRoute.Spec.ParentRefs, findGatewayFromParentRefFunc(gateways, udpRoute.Namespace)) + }, + } +} + // findGatewayFromParentRefFunc is a common function to find a Gateway from a xRoute's `parentRef` field func findGatewayFromParentRefFunc(gateways []*Gateway, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { return func(parentRef gwapiv1.ParentReference, _ int) (Object, bool) { @@ -528,7 +603,7 @@ func LinkListenerToGRPCRouteFunc(gateways []*Gateway, listeners []*Listener) Lin } } -// LinkListenerToTCPRouteFunc returns a link function that teaches a topology how to link GRPCRoutes from known +// LinkListenerToTCPRouteFunc returns a link function that teaches a topology how to link TCPRoutes from known // Gateways and gateway Listeners, based on the TCPRoute's `parentRefs` field. // The function links a specific Listener of a Gateway to the TCPRoute when the `sectionName` field of the parent // reference is present, otherwise all Listeners of the parent Gateway are linked to the TCPRoute. @@ -543,7 +618,7 @@ func LinkListenerToTCPRouteFunc(gateways []*Gateway, listeners []*Listener) Link } } -// LinkListenerToTLSRouteFunc returns a link function that teaches a topology how to link GRPCRoutes from known +// LinkListenerToTLSRouteFunc returns a link function that teaches a topology how to link TLSRoutes from known // Gateways and gateway Listeners, based on the TLSRoute's `parentRefs` field. // The function links a specific Listener of a Gateway to the TLSRoute when the `sectionName` field of the parent // reference is present, otherwise all Listeners of the parent Gateway are linked to the TLSRoute. @@ -558,6 +633,21 @@ func LinkListenerToTLSRouteFunc(gateways []*Gateway, listeners []*Listener) Link } } +// LinkListenerToUDPRouteFunc returns a link function that teaches a topology how to link UDPRoutes from known +// Gateways and gateway Listeners, based on the UDPRoute's `parentRefs` field. +// The function links a specific Listener of a Gateway to the UDPRoute when the `sectionName` field of the parent +// reference is present, otherwise all Listeners of the parent Gateway are linked to the UDPRoute. +func LinkListenerToUDPRouteFunc(gateways []*Gateway, listeners []*Listener) LinkFunc { + return LinkFunc{ + From: ListenerGroupKind, + To: UDPRouteGroupKind, + Func: func(child Object) []Object { + udpRoute := child.(*UDPRoute) + return lo.FlatMap(udpRoute.Spec.ParentRefs, findListenerFromParentRefFunc(gateways, listeners, udpRoute.Namespace)) + }, + } +} + // findListenerFromParentRefFunc is a common function to find a gateway Listener from a xRoute's `parentRef` field func findListenerFromParentRefFunc(gateways []*Gateway, listeners []*Listener, routeNamespace string) func(parentRef gwapiv1.ParentReference, _ int) []Object { return func(parentRef gwapiv1.ParentReference, _ int) []Object { @@ -960,6 +1050,99 @@ func LinkTLSRouteRuleToServicePortFunc(routeRules []*TLSRouteRule) LinkFunc { } } +// LinkUDPRouteToServiceFunc returns a link function that teaches a topology how to link Services from known +// UDPRoutes, based on the UDPRoute's `backendRefs` fields. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkUDPRouteToServiceFunc(routes []*UDPRoute, strict bool) LinkFunc { + return LinkFunc{ + From: UDPRouteGroupKind, + To: ServiceGroupKind, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routes, func(route *UDPRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1alpha2.UDPRouteRule) bool { + backendRefs := lo.Filter(rule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return !strict || backendRef.Port == nil + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, route.Namespace)) + }) + }) + }, + } +} + +// LinkUDPRouteToServicePortFunc returns a link function that teaches a topology how to link services ports from known +// UDPRoutes, based on the UDPRoute's `backendRefs` fields. +// The link function disregards backend references that do not specify a port number. +func LinkUDPRouteToServicePortFunc(routes []*UDPRoute) LinkFunc { + return LinkFunc{ + From: UDPRouteGroupKind, + To: ServicePortGroupKind, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routes, func(route *UDPRoute, _ int) (Object, bool) { + return route, lo.ContainsBy(route.Spec.Rules, func(rule gwapiv1alpha2.UDPRouteRule) bool { + backendRefs := lo.Filter(rule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, route.Namespace)) + }) + }) + }, + } +} + +// LinkUDPRouteToUDPRouteRuleFunc returns a link function that teaches a topology how to link UDPRouteRule from the +// UDPRoute they are strongly related to. +func LinkUDPRouteToUDPRouteRuleFunc() LinkFunc { + return LinkFunc{ + From: UDPRouteGroupKind, + To: UDPRouteRuleGroupKind, + Func: func(child Object) []Object { + updRouteRule := child.(*UDPRouteRule) + return []Object{updRouteRule.UDPRoute} + }, + } +} + +// LinkUDPRouteRuleToServiceFunc returns a link function that teaches a topology how to link Services from known +// UDPRouteRules, based on the UDPRouteRule's `backendRefs` field. +// Set the `strict` parameter to `true` to link only to services that have no port specified in the backendRefs. +func LinkUDPRouteRuleToServiceFunc(routeRules []*UDPRouteRule, strict bool) LinkFunc { + return LinkFunc{ + From: UDPRouteRuleGroupKind, + To: ServiceGroupKind, + Func: func(child Object) []Object { + service := child.(*Service) + return lo.FilterMap(routeRules, func(routeRule *UDPRouteRule, _ int) (Object, bool) { + backendRefs := lo.Filter(routeRule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return !strict || backendRef.Port == nil + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(service, routeRule.UDPRoute.Namespace)) + }) + }, + } +} + +// LinkUDPRouteRuleToServicePortFunc returns a link function that teaches a topology how to link services ports from +// known UDPRouteRules, based on the UDPRouteRule's `backendRefs` field. +// The link function disregards backend references that do not specify a port number. +func LinkUDPRouteRuleToServicePortFunc(routeRules []*UDPRouteRule) LinkFunc { + return LinkFunc{ + From: UDPRouteRuleGroupKind, + To: ServicePortGroupKind, + Func: func(child Object) []Object { + servicePort := child.(*ServicePort) + return lo.FilterMap(routeRules, func(routeRule *UDPRouteRule, _ int) (Object, bool) { + backendRefs := lo.Filter(routeRule.BackendRefs, func(backendRef gwapiv1.BackendRef, _ int) bool { + return backendRef.Port != nil && int32(*backendRef.Port) == servicePort.Port + }) + return routeRule, lo.ContainsBy(backendRefs, backendRefContainsServiceFunc(servicePort.Service, routeRule.UDPRoute.Namespace)) + }) + }, + } +} + // LinkServiceToServicePortFunc returns a link function that teaches a topology how to link service ports from the // Service they are strongly related to. func LinkServiceToServicePortFunc() LinkFunc { diff --git a/machinery/gateway_api_topology_test.go b/machinery/gateway_api_topology_test.go index 8ec23ec..0f8fd0e 100644 --- a/machinery/gateway_api_topology_test.go +++ b/machinery/gateway_api_topology_test.go @@ -21,6 +21,9 @@ import ( // // GatewayClass -> Gateway -> HTTPRoute -> Service // ∟> GRPCRoute ⤴ +// ∟> TCPRoute ⤴ +// ∟> TLSRoute ⤴ +// ∟> UDPRoute ⤴ func TestGatewayAPITopology(t *testing.T) { testCases := []struct { name string @@ -46,16 +49,18 @@ func TestGatewayAPITopology(t *testing.T) { GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, TCPRoutes: []*gwapiv1alpha2.TCPRoute{BuildTCPRoute()}, TLSRoutes: []*gwapiv1alpha2.TLSRoute{BuildTLSRoute()}, + UDPRoutes: []*gwapiv1alpha2.UDPRoute{BuildUDPRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, - "my-gateway": {"my-http-route", "my-grpc-route", "my-tcp-route", "my-tls-route"}, + "my-gateway": {"my-http-route", "my-grpc-route", "my-tcp-route", "my-tls-route", "my-udp-route"}, "my-grpc-route": {"my-service"}, "my-http-route": {"my-service"}, "my-tcp-route": {"my-service"}, "my-tls-route": {"my-service"}, + "my-udp-route": {"my-service"}, }, }, { @@ -66,14 +71,14 @@ func TestGatewayAPITopology(t *testing.T) { "gatewayclass-2": {"gateway-4", "gateway-5"}, "gateway-1": {"http-route-1", "http-route-2"}, "gateway-2": {"http-route-2", "http-route-3"}, - "gateway-3": {"http-route-4", "tls-route-1"}, + "gateway-3": {"udp-route-1", "tls-route-1"}, "gateway-4": {"tls-route-1", "tcp-route-1"}, "gateway-5": {"grpc-route-1"}, "grpc-route-1": {"service-7"}, "http-route-1": {"service-1", "service-2"}, "http-route-2": {"service-3"}, "http-route-3": {"service-3"}, - "http-route-4": {"service-3", "service-4"}, + "udp-route-1": {"service-3", "service-4"}, "tls-route-1": {"service-5"}, "tcp-route-1": {"service-5", "service-6"}, }, @@ -89,6 +94,7 @@ func TestGatewayAPITopology(t *testing.T) { grpcRoutes := lo.Map(tc.targetables.GRPCRoutes, func(grpcRoute *gwapiv1.GRPCRoute, _ int) *GRPCRoute { return &GRPCRoute{GRPCRoute: grpcRoute} }) tcpRoutes := lo.Map(tc.targetables.TCPRoutes, func(tcpRoute *gwapiv1alpha2.TCPRoute, _ int) *TCPRoute { return &TCPRoute{TCPRoute: tcpRoute} }) tlsRoutes := lo.Map(tc.targetables.TLSRoutes, func(tlsRoute *gwapiv1alpha2.TLSRoute, _ int) *TLSRoute { return &TLSRoute{TLSRoute: tlsRoute} }) + udpRoutes := lo.Map(tc.targetables.UDPRoutes, func(updRoute *gwapiv1alpha2.UDPRoute, _ int) *UDPRoute { return &UDPRoute{UDPRoute: updRoute} }) services := lo.Map(tc.targetables.Services, func(service *core.Service, _ int) *Service { return &Service{Service: service} }) topology := NewTopology( @@ -99,16 +105,19 @@ func TestGatewayAPITopology(t *testing.T) { WithTargetables(grpcRoutes...), WithTargetables(tcpRoutes...), WithTargetables(tlsRoutes...), + WithTargetables(udpRoutes...), WithLinks( LinkGatewayClassToGatewayFunc(gatewayClasses), LinkGatewayToHTTPRouteFunc(gateways), LinkGatewayToGRPCRouteFunc(gateways), LinkGatewayToTCPRouteFunc(gateways), LinkGatewayToTLSRouteFunc(gateways), + LinkGatewayToUDPRouteFunc(gateways), LinkHTTPRouteToServiceFunc(httpRoutes, false), LinkGRPCRouteToServiceFunc(grpcRoutes, false), LinkTCPRouteToServiceFunc(tcpRoutes, false), LinkTLSRouteToServiceFunc(tlsRoutes, false), + LinkUDPRouteToServiceFunc(udpRoutes, false), ), WithPolicies(tc.policies...), ) @@ -154,13 +163,14 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { GRPCRoutes: []*gwapiv1.GRPCRoute{BuildGRPCRoute()}, TCPRoutes: []*gwapiv1alpha2.TCPRoute{BuildTCPRoute()}, TLSRoutes: []*gwapiv1alpha2.TLSRoute{BuildTLSRoute()}, + UDPRoutes: []*gwapiv1alpha2.UDPRoute{BuildUDPRoute()}, Services: []*core.Service{BuildService()}, }, policies: []Policy{buildPolicy()}, expectedLinks: map[string][]string{ "my-gateway-class": {"my-gateway"}, "my-gateway": {"my-gateway#my-listener"}, - "my-gateway#my-listener": {"my-http-route", "my-grpc-route", "my-tcp-route", "my-tls-route"}, + "my-gateway#my-listener": {"my-http-route", "my-grpc-route", "my-tcp-route", "my-tls-route", "my-udp-route"}, "my-grpc-route": {"my-grpc-route#rule-1"}, "my-grpc-route#rule-1": {"my-service"}, "my-http-route": {"my-http-route#rule-1"}, @@ -169,6 +179,8 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { "my-tcp-route#rule-1": {"my-service"}, "my-tls-route": {"my-tls-route#rule-1"}, "my-tls-route#rule-1": {"my-service"}, + "my-udp-route": {"my-udp-route#rule-1"}, + "my-udp-route#rule-1": {"my-service"}, "my-service": {"my-service#http"}, }, }, @@ -226,8 +238,8 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { "gateway-1#listener-1": {"http-route-1"}, "gateway-1#listener-2": {"http-route-1", "http-route-2"}, "gateway-2#listener-1": {"http-route-2", "http-route-3"}, - "gateway-3#listener-1": {"http-route-4", "tls-route-1"}, - "gateway-3#listener-2": {"http-route-4", "tls-route-1"}, + "gateway-3#listener-1": {"udp-route-1", "tls-route-1"}, + "gateway-3#listener-2": {"udp-route-1", "tls-route-1"}, "gateway-4#listener-1": {"tls-route-1", "tcp-route-1"}, "gateway-4#listener-2": {"tls-route-1", "tcp-route-1"}, "gateway-5#listener-1": {"grpc-route-1"}, @@ -236,13 +248,13 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { "http-route-1": {"http-route-1#rule-1", "http-route-1#rule-2"}, "http-route-2": {"http-route-2#rule-1"}, "http-route-3": {"http-route-3#rule-1"}, - "http-route-4": {"http-route-4#rule-1", "http-route-4#rule-2"}, + "udp-route-1": {"udp-route-1#rule-1", "udp-route-1#rule-2"}, "http-route-1#rule-1": {"service-1"}, "http-route-1#rule-2": {"service-2"}, "http-route-2#rule-1": {"service-3#port-1"}, "http-route-3#rule-1": {"service-3#port-1"}, - "http-route-4#rule-1": {"service-3#port-2"}, - "http-route-4#rule-2": {"service-4#port-1"}, + "udp-route-1#rule-1": {"service-3#port-2"}, + "udp-route-1#rule-2": {"service-4#port-1"}, "tls-route-1": {"tls-route-1#rule-1", "tls-route-1#rule-2"}, "tls-route-1#rule-1": {"service-5"}, "tls-route-1#rule-2": {"service-5"}, @@ -274,6 +286,8 @@ func TestGatewayAPITopologyWithSectionNames(t *testing.T) { WithTLSRoutes(tc.targetables.TLSRoutes...), ExpandTLSRouteRules(), WithServices(tc.targetables.Services...), + WithUDPRoutes(tc.targetables.UDPRoutes...), + ExpandUDPRouteRules(), ExpandServicePorts(), WithGatewayAPITopologyPolicies(tc.policies...), ) From 64ccd19541b4900dd02979f1ad08fe26c9ca2622 Mon Sep 17 00:00:00 2001 From: KevFan Date: Thu, 15 Aug 2024 16:12:58 +0100 Subject: [PATCH 18/21] fixup: address comments Signed-off-by: KevFan --- machinery/core_types.go | 5 +++++ machinery/gateway_api_topology.go | 19 ------------------- machinery/gateway_api_topology_test.go | 8 ++++---- machinery/gateway_api_types.go | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/machinery/core_types.go b/machinery/core_types.go index c4a3bf5..f9a4179 100644 --- a/machinery/core_types.go +++ b/machinery/core_types.go @@ -6,6 +6,11 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) +var ( + ServiceGroupKind = schema.GroupKind{Kind: "Service"} + ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} +) + // These are wrappers for Core API types so instances can be used as targetables in the topology. type Namespace struct { diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index c924e47..fd755c9 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -5,30 +5,11 @@ import ( "github.com/samber/lo" core "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) -var ( - GatewayClassGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GatewayClass"} - GatewayGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"} - ListenerGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"} - HTTPRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"} - HTTPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"} - GRPCRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"} - GRPCRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"} - TCPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRoute"} - TCPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRouteRule"} - TLSRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRoute"} - TLSRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRouteRule"} - UDPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRoute"} - UDPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRouteRule"} - ServiceGroupKind = schema.GroupKind{Kind: "Service"} - ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} -) - type GatewayAPITopologyOptions struct { GatewayClasses []*GatewayClass Gateways []*Gateway diff --git a/machinery/gateway_api_topology_test.go b/machinery/gateway_api_topology_test.go index 0f8fd0e..0b0b0ff 100644 --- a/machinery/gateway_api_topology_test.go +++ b/machinery/gateway_api_topology_test.go @@ -20,10 +20,10 @@ import ( // This results in a topology with the following scheme: // // GatewayClass -> Gateway -> HTTPRoute -> Service -// ∟> GRPCRoute ⤴ -// ∟> TCPRoute ⤴ -// ∟> TLSRoute ⤴ -// ∟> UDPRoute ⤴ +// ∟> GRPCRoute ⤴ +// ∟> TCPRoute ⤴ +// ∟> TLSRoute ⤴ +// ∟> UDPRoute ⤴ func TestGatewayAPITopology(t *testing.T) { testCases := []struct { name string diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index b645970..95c902f 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -12,6 +12,22 @@ import ( gwapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) +var ( + GatewayClassGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GatewayClass"} + GatewayGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"} + ListenerGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"} + HTTPRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"} + HTTPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"} + GRPCRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"} + GRPCRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"} + TCPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRoute"} + TCPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRouteRule"} + TLSRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRoute"} + TLSRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRouteRule"} + UDPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRoute"} + UDPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRouteRule"} +) + const nameSectionNameURLSeparator = '#' // These are wrappers for Gateway API types so instances can be used as targetables in the topology. From d7d3d30631d96f3786532452d9e7873df4f5b10a Mon Sep 17 00:00:00 2001 From: KevFan Date: Fri, 16 Aug 2024 12:32:11 +0100 Subject: [PATCH 19/21] fixup: expand service ports as targetables only once Signed-off-by: KevFan --- machinery/gateway_api_topology.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/machinery/gateway_api_topology.go b/machinery/gateway_api_topology.go index fd755c9..78a1262 100644 --- a/machinery/gateway_api_topology.go +++ b/machinery/gateway_api_topology.go @@ -236,8 +236,6 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { opts = append(opts, WithLinks(LinkHTTPRouteToHTTPRouteRuleFunc())) // HTTPRoute -> HTTPRouteRule if o.ExpandServicePorts { - servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) - opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks( LinkHTTPRouteRuleToServicePortFunc(httpRouteRules), // HTTPRouteRule -> ServicePort LinkHTTPRouteRuleToServiceFunc(httpRouteRules, true), // HTTPRouteRule -> Service @@ -262,8 +260,6 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { opts = append(opts, WithLinks(LinkGRPCRouteToGRPCRouteRuleFunc())) // GRPCRoute -> GRPCRouteRule if o.ExpandServicePorts { - servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) - opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks( LinkGRPCRouteRuleToServicePortFunc(grpcRouteRules), // GRPCRouteRule -> ServicePort LinkGRPCRouteRuleToServiceFunc(grpcRouteRules, true), // GRPCRouteRule -> Service @@ -288,8 +284,6 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { opts = append(opts, WithLinks(LinkTCPRouteToTCPRouteRuleFunc())) // TCPRoute - TCPRouteRules if o.ExpandServicePorts { - servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) - opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks( LinkTCPRouteRuleToServicePortFunc(tcpRouteRules), // TCPRouteRule -> ServicePort LinkTCPRouteRuleToServiceFunc(tcpRouteRules, true), // TCPRoute -> service @@ -314,8 +308,6 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { opts = append(opts, WithLinks(LinkTLSRouteToTLSRouteRuleFunc())) if o.ExpandServicePorts { - servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) - opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks( LinkTLSRouteRuleToServicePortFunc(tlsRouteRules), // TLSRouteRule -> ServicePort LinkTLSRouteRuleToServiceFunc(tlsRouteRules, true), // TLSRouteRule -> Service @@ -340,8 +332,6 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { opts = append(opts, WithLinks(LinkUDPRouteToUDPRouteRuleFunc())) if o.ExpandServicePorts { - servicePorts := lo.FlatMap(o.Services, ServicePortsFromBackendFunc) - opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks( LinkUDPRouteRuleToServicePortFunc(udpRouteRules), // UDPRouteRule -> ServicePort LinkUDPRouteRuleToServiceFunc(udpRouteRules, true), // UDPRouteRule -> Service @@ -361,6 +351,8 @@ func NewGatewayAPITopology(options ...GatewayAPITopologyOptionsFunc) *Topology { } if o.ExpandServicePorts { + servicePorts := lo.FlatMap(o.Services, ServicePortsFromServiceFunc) + opts = append(opts, WithTargetables(servicePorts...)) opts = append(opts, WithLinks(LinkServiceToServicePortFunc())) // Service -> ServicePort } @@ -432,8 +424,8 @@ func UDPRouteRulesFromUDPRouteFunc(udpRoute *UDPRoute, _ int) []*UDPRouteRule { }) } -// ServicePortsFromBackendFunc returns a list of targetable service ports from a targetable Service. -func ServicePortsFromBackendFunc(service *Service, _ int) []*ServicePort { +// ServicePortsFromServiceFunc returns a list of targetable service ports from a targetable Service. +func ServicePortsFromServiceFunc(service *Service, _ int) []*ServicePort { return lo.Map(service.Spec.Ports, func(port core.ServicePort, _ int) *ServicePort { return &ServicePort{ ServicePort: &port, From 619af82674e58eac49d4710f16877037d09aaaf5 Mon Sep 17 00:00:00 2001 From: KevFan Date: Mon, 19 Aug 2024 10:16:10 +0100 Subject: [PATCH 20/21] fixup: use group kinds from machinery package where possible Signed-off-by: KevFan --- controller/resources.go | 11 -------- controller/test_helper.go | 2 +- controller/topology_builder.go | 8 +++--- examples/kuadrant/main.go | 24 ++++++++--------- .../kuadrant/reconcilers/envoy_gateway.go | 6 ++--- examples/kuadrant/reconcilers/istio.go | 6 ++--- machinery/core_types.go | 4 +-- machinery/gateway_api_test_helper.go | 6 ++--- machinery/gateway_api_types.go | 26 +++++++++---------- 9 files changed, 41 insertions(+), 52 deletions(-) diff --git a/controller/resources.go b/controller/resources.go index b6eb3a1..e3de019 100644 --- a/controller/resources.go +++ b/controller/resources.go @@ -5,17 +5,6 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) -// GroupKinds -var ( - // core - ServiceKind = core.SchemeGroupVersion.WithKind("Service").GroupKind() - - // gateway api - GatewayClassKind = gwapiv1.SchemeGroupVersion.WithKind("GatewayClass").GroupKind() - GatewayKind = gwapiv1.SchemeGroupVersion.WithKind("Gateway").GroupKind() - HTTPRouteKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRoute").GroupKind() -) - // API Resources var ( // core diff --git a/controller/test_helper.go b/controller/test_helper.go index 67290d3..89c1715 100644 --- a/controller/test_helper.go +++ b/controller/test_helper.go @@ -45,7 +45,7 @@ func init() { myObjects := objs.FilterByGroupKind(schema.GroupKind{Group: "test/v1", Kind: "MyObject"}) return machinery.LinkFunc{ From: schema.GroupKind{Group: "test/v1", Kind: "MyObject"}, - To: GatewayKind, + To: machinery.GatewayGroupKind, Func: func(_ machinery.Object) []machinery.Object { return []machinery.Object{&RuntimeObject{myObjects[0]}} }, } } diff --git a/controller/topology_builder.go b/controller/topology_builder.go index e0c28a5..adef2c9 100644 --- a/controller/topology_builder.go +++ b/controller/topology_builder.go @@ -24,10 +24,10 @@ type gatewayAPITopologyBuilder struct { } func (t *gatewayAPITopologyBuilder) Build(objs Store) *machinery.Topology { - gatewayClasses := lo.Map(objs.FilterByGroupKind(GatewayClassKind), ObjectAs[*gwapiv1.GatewayClass]) - gateways := lo.Map(objs.FilterByGroupKind(GatewayKind), ObjectAs[*gwapiv1.Gateway]) - httpRoutes := lo.Map(objs.FilterByGroupKind(HTTPRouteKind), ObjectAs[*gwapiv1.HTTPRoute]) - services := lo.Map(objs.FilterByGroupKind(ServiceKind), ObjectAs[*core.Service]) + gatewayClasses := lo.Map(objs.FilterByGroupKind(machinery.GatewayClassGroupKind), ObjectAs[*gwapiv1.GatewayClass]) + gateways := lo.Map(objs.FilterByGroupKind(machinery.GatewayGroupKind), ObjectAs[*gwapiv1.Gateway]) + httpRoutes := lo.Map(objs.FilterByGroupKind(machinery.HTTPRouteGroupKind), ObjectAs[*gwapiv1.HTTPRoute]) + services := lo.Map(objs.FilterByGroupKind(machinery.ServiceGroupKind), ObjectAs[*core.Service]) linkFuncs := lo.Map(t.objectLinks, func(f LinkFunc, _ int) machinery.LinkFunc { return f(objs) diff --git a/examples/kuadrant/main.go b/examples/kuadrant/main.go index 71ab345..5aa7afb 100644 --- a/examples/kuadrant/main.go +++ b/examples/kuadrant/main.go @@ -35,18 +35,18 @@ import ( const ( // reconciliation modes defaultReconciliationMode = stateReconciliationMode - deltaReconciliationMode = "delta" - stateReconciliationMode = "state" + deltaReconciliationMode = "delta" + stateReconciliationMode = "state" ) var ( scheme = runtime.NewScheme() supportedReconciliationModes = []string{stateReconciliationMode, deltaReconciliationMode} - reconciliationMode = defaultReconciliationMode + reconciliationMode = defaultReconciliationMode supportedGatewayProviders = []string{reconcilers.EnvoyGatewayProviderName, reconcilers.IstioGatewayProviderName} - gatewayProviders []string + gatewayProviders []string ) func init() { @@ -134,13 +134,13 @@ func main() { controller.WithReconcile(buildReconciler(gatewayProviders, client)), } - // gateway provider specific controller options + // gateway provider specific controller options controllerOpts = append(controllerOpts, controllerOptionsFor(gatewayProviders)...) // managed controller if reconciliationMode == stateReconciliationMode { manager, err := ctrlruntime.NewManager(config, ctrlruntime.Options{ - Logger: logger, + Logger: logger, Scheme: scheme, Metrics: ctrlruntimemetrics.Options{BindAddress: ":8080"}, WebhookServer: ctrlruntimewebhook.NewServer(ctrlruntimewebhook.Options{Port: 9443}), @@ -204,10 +204,10 @@ func buildReconciler(gatewayProviders []string, client *dynamic.DynamicClient) c effectivePolicyReconciler := &reconcilers.EffectivePoliciesReconciler{Client: client} commonAuthPolicyResourceEventMatchers := []controller.ResourceEventMatcher{ - {Kind: ptr.To(controller.GatewayClassKind)}, - {Kind: ptr.To(controller.GatewayKind), EventType: ptr.To(controller.CreateEvent)}, - {Kind: ptr.To(controller.GatewayKind), EventType: ptr.To(controller.UpdateEvent)}, - {Kind: ptr.To(controller.HTTPRouteKind)}, + {Kind: ptr.To(machinery.GatewayClassGroupKind)}, + {Kind: ptr.To(machinery.GatewayGroupKind), EventType: ptr.To(controller.CreateEvent)}, + {Kind: ptr.To(machinery.GatewayGroupKind), EventType: ptr.To(controller.UpdateEvent)}, + {Kind: ptr.To(machinery.HTTPRouteGroupKind)}, {Kind: ptr.To(kuadrantv1beta3.AuthPolicyKind)}, } @@ -222,7 +222,7 @@ func buildReconciler(gatewayProviders []string, client *dynamic.DynamicClient) c effectivePolicyReconciler.ReconcileFuncs = append(effectivePolicyReconciler.ReconcileFuncs, (&controller.Subscription{ ReconcileFunc: envoyGatewayProvider.DeleteSecurityPolicy, Events: []controller.ResourceEventMatcher{ - {Kind: ptr.To(controller.GatewayKind), EventType: ptr.To(controller.DeleteEvent)}, + {Kind: ptr.To(machinery.GatewayGroupKind), EventType: ptr.To(controller.DeleteEvent)}, }, }).Reconcile) case reconcilers.IstioGatewayProviderName: @@ -234,7 +234,7 @@ func buildReconciler(gatewayProviders []string, client *dynamic.DynamicClient) c effectivePolicyReconciler.ReconcileFuncs = append(effectivePolicyReconciler.ReconcileFuncs, (&controller.Subscription{ ReconcileFunc: istioGatewayProvider.DeleteAuthorizationPolicy, Events: []controller.ResourceEventMatcher{ - {Kind: ptr.To(controller.GatewayKind), EventType: ptr.To(controller.DeleteEvent)}, + {Kind: ptr.To(machinery.GatewayGroupKind), EventType: ptr.To(controller.DeleteEvent)}, }, }).Reconcile) } diff --git a/examples/kuadrant/reconcilers/envoy_gateway.go b/examples/kuadrant/reconcilers/envoy_gateway.go index b63e379..157c250 100644 --- a/examples/kuadrant/reconcilers/envoy_gateway.go +++ b/examples/kuadrant/reconcilers/envoy_gateway.go @@ -155,10 +155,10 @@ func (p *EnvoyGatewayProvider) deleteSecurityPolicy(ctx context.Context, topolog } func LinkGatewayToEnvoyGatewaySecurityPolicyFunc(objs controller.Store) machinery.LinkFunc { - gateways := lo.Map(objs.FilterByGroupKind(controller.GatewayKind), controller.ObjectAs[*gwapiv1.Gateway]) + gateways := lo.Map(objs.FilterByGroupKind(machinery.GatewayGroupKind), controller.ObjectAs[*gwapiv1.Gateway]) return machinery.LinkFunc{ - From: controller.GatewayKind, + From: machinery.GatewayGroupKind, To: EnvoyGatewaySecurityPolicyKind, Func: func(child machinery.Object) []machinery.Object { o := child.(*controller.RuntimeObject) @@ -168,7 +168,7 @@ func LinkGatewayToEnvoyGatewaySecurityPolicyFunc(objs controller.Store) machiner refs = append(refs, *ref) } refs = lo.Filter(refs, func(ref gwapiv1alpha2.LocalPolicyTargetReferenceWithSectionName, _ int) bool { - return ref.Group == gwapiv1.GroupName && ref.Kind == gwapiv1.Kind(controller.GatewayKind.Kind) + return ref.Group == gwapiv1.GroupName && ref.Kind == gwapiv1.Kind(machinery.GatewayGroupKind.Kind) }) if len(refs) == 0 { return nil diff --git a/examples/kuadrant/reconcilers/istio.go b/examples/kuadrant/reconcilers/istio.go index e5ef992..af37d0a 100644 --- a/examples/kuadrant/reconcilers/istio.go +++ b/examples/kuadrant/reconcilers/istio.go @@ -294,10 +294,10 @@ func hostSubsetOf(superset gwapiv1.Hostname) func(gwapiv1.Hostname, int) bool { } func LinkGatewayToIstioAuthorizationPolicyFunc(objs controller.Store) machinery.LinkFunc { - gateways := lo.Map(objs.FilterByGroupKind(controller.GatewayKind), controller.ObjectAs[*gwapiv1.Gateway]) + gateways := lo.Map(objs.FilterByGroupKind(machinery.GatewayGroupKind), controller.ObjectAs[*gwapiv1.Gateway]) return machinery.LinkFunc{ - From: controller.GatewayKind, + From: machinery.GatewayGroupKind, To: IstioAuthorizationPolicyKind, Func: func(child machinery.Object) []machinery.Object { o := child.(*controller.RuntimeObject) @@ -307,7 +307,7 @@ func LinkGatewayToIstioAuthorizationPolicyFunc(objs controller.Store) machinery. refs = append(refs, ref) } refs = lo.Filter(refs, func(ref *istiov1beta1.PolicyTargetReference, _ int) bool { - return ref.Group == gwapiv1.GroupName && ref.Kind == controller.GatewayKind.Kind + return ref.Group == gwapiv1.GroupName && ref.Kind == machinery.GatewayGroupKind.Kind }) if len(refs) == 0 { return nil diff --git a/machinery/core_types.go b/machinery/core_types.go index f9a4179..cb2ea67 100644 --- a/machinery/core_types.go +++ b/machinery/core_types.go @@ -7,8 +7,8 @@ import ( ) var ( - ServiceGroupKind = schema.GroupKind{Kind: "Service"} - ServicePortGroupKind = schema.GroupKind{Kind: "ServicePort"} + ServiceGroupKind = core.SchemeGroupVersion.WithKind("Service").GroupKind() + ServicePortGroupKind = core.SchemeGroupVersion.WithKind("ServicePort").GroupKind() ) // These are wrappers for Core API types so instances can be used as targetables in the topology. diff --git a/machinery/gateway_api_test_helper.go b/machinery/gateway_api_test_helper.go index 9a1f85a..e98974a 100644 --- a/machinery/gateway_api_test_helper.go +++ b/machinery/gateway_api_test_helper.go @@ -174,7 +174,7 @@ func BuildBackendRef(f ...func(*gwapiv1.BackendObjectReference)) gwapiv1.Backend func BuildTCPRoute(f ...func(route *gwapiv1alpha2.TCPRoute)) *gwapiv1alpha2.TCPRoute { r := &gwapiv1alpha2.TCPRoute{ TypeMeta: metav1.TypeMeta{ - APIVersion: gwapiv1.GroupVersion.String(), + APIVersion: gwapiv1alpha2.GroupVersion.String(), Kind: "TCPRoute", }, ObjectMeta: metav1.ObjectMeta{ @@ -206,7 +206,7 @@ func BuildTCPRoute(f ...func(route *gwapiv1alpha2.TCPRoute)) *gwapiv1alpha2.TCPR func BuildTLSRoute(f ...func(route *gwapiv1alpha2.TLSRoute)) *gwapiv1alpha2.TLSRoute { r := &gwapiv1alpha2.TLSRoute{ TypeMeta: metav1.TypeMeta{ - APIVersion: gwapiv1.GroupVersion.String(), + APIVersion: gwapiv1alpha2.GroupVersion.String(), Kind: "TLSRoute", }, ObjectMeta: metav1.ObjectMeta{ @@ -238,7 +238,7 @@ func BuildTLSRoute(f ...func(route *gwapiv1alpha2.TLSRoute)) *gwapiv1alpha2.TLSR func BuildUDPRoute(f ...func(route *gwapiv1alpha2.UDPRoute)) *gwapiv1alpha2.UDPRoute { r := &gwapiv1alpha2.UDPRoute{ TypeMeta: metav1.TypeMeta{ - APIVersion: gwapiv1.GroupVersion.String(), + APIVersion: gwapiv1alpha2.GroupVersion.String(), Kind: "UDPRoute", }, ObjectMeta: metav1.ObjectMeta{ diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index 95c902f..ef9bdaa 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -13,19 +13,19 @@ import ( ) var ( - GatewayClassGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GatewayClass"} - GatewayGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Gateway"} - ListenerGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "Listener"} - HTTPRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRoute"} - HTTPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "HTTPRouteRule"} - GRPCRouteGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRoute"} - GRPCRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GRPCRouteRule"} - TCPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRoute"} - TCPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TCPRouteRule"} - TLSRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRoute"} - TLSRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "TLSRouteRule"} - UDPRouteGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRoute"} - UDPRouteRuleGroupKind = schema.GroupKind{Group: gwapiv1alpha2.GroupVersion.Group, Kind: "UDPRouteRule"} + GatewayClassGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GatewayClass").GroupKind() + GatewayGroupKind = gwapiv1.SchemeGroupVersion.WithKind("Gateway").GroupKind() + ListenerGroupKind = gwapiv1.SchemeGroupVersion.WithKind("Listener").GroupKind() + HTTPRouteGroupKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRoute").GroupKind() + HTTPRouteRuleGroupKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRouteRule").GroupKind() + GRPCRouteGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GRPCRoute").GroupKind() + GRPCRouteRuleGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GRPCRouteRule").GroupKind() + TCPRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TCPRoute").GroupKind() + TCPRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TCPRouteRule").GroupKind() + TLSRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TLSRoute").GroupKind() + TLSRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TLSRouteRule").GroupKind() + UDPRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("UDPRoute").GroupKind() + UDPRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("UDPRouteRule").GroupKind() ) const nameSectionNameURLSeparator = '#' From 0613f74fdeb17d4afe8feeb9e588fad158b01058 Mon Sep 17 00:00:00 2001 From: KevFan Date: Wed, 21 Aug 2024 19:13:27 +0100 Subject: [PATCH 21/21] fixup: add missing group kinds Signed-off-by: KevFan --- machinery/core_types.go | 1 + machinery/gateway_api_types.go | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/machinery/core_types.go b/machinery/core_types.go index cb2ea67..75917fa 100644 --- a/machinery/core_types.go +++ b/machinery/core_types.go @@ -7,6 +7,7 @@ import ( ) var ( + NamespaceGroupKind = core.SchemeGroupVersion.WithKind("Namespace").GroupKind() ServiceGroupKind = core.SchemeGroupVersion.WithKind("Service").GroupKind() ServicePortGroupKind = core.SchemeGroupVersion.WithKind("ServicePort").GroupKind() ) diff --git a/machinery/gateway_api_types.go b/machinery/gateway_api_types.go index ef9bdaa..ddb0d33 100644 --- a/machinery/gateway_api_types.go +++ b/machinery/gateway_api_types.go @@ -13,19 +13,22 @@ import ( ) var ( - GatewayClassGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GatewayClass").GroupKind() - GatewayGroupKind = gwapiv1.SchemeGroupVersion.WithKind("Gateway").GroupKind() - ListenerGroupKind = gwapiv1.SchemeGroupVersion.WithKind("Listener").GroupKind() - HTTPRouteGroupKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRoute").GroupKind() - HTTPRouteRuleGroupKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRouteRule").GroupKind() - GRPCRouteGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GRPCRoute").GroupKind() - GRPCRouteRuleGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GRPCRouteRule").GroupKind() - TCPRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TCPRoute").GroupKind() - TCPRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TCPRouteRule").GroupKind() - TLSRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TLSRoute").GroupKind() - TLSRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TLSRouteRule").GroupKind() - UDPRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("UDPRoute").GroupKind() - UDPRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("UDPRouteRule").GroupKind() + GatewayClassGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GatewayClass").GroupKind() + GatewayGroupKind = gwapiv1.SchemeGroupVersion.WithKind("Gateway").GroupKind() + ListenerGroupKind = gwapiv1.SchemeGroupVersion.WithKind("Listener").GroupKind() + HTTPRouteGroupKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRoute").GroupKind() + HTTPRouteRuleGroupKind = gwapiv1.SchemeGroupVersion.WithKind("HTTPRouteRule").GroupKind() + GRPCRouteGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GRPCRoute").GroupKind() + GRPCRouteRuleGroupKind = gwapiv1.SchemeGroupVersion.WithKind("GRPCRouteRule").GroupKind() + ReferenceGrantGroupKind = gwapiv1beta1.SchemeGroupVersion.WithKind("ReferenceGrant").GroupKind() + BackendTLSPolicyGroupKind = gwapiv1alpha3.SchemeGroupVersion.WithKind("BackendTLSPolicy").GroupKind() + BackendLBPolicyGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("BackendLBPolicy").GroupKind() + TCPRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TCPRoute").GroupKind() + TCPRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TCPRouteRule").GroupKind() + TLSRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TLSRoute").GroupKind() + TLSRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("TLSRouteRule").GroupKind() + UDPRouteGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("UDPRoute").GroupKind() + UDPRouteRuleGroupKind = gwapiv1alpha2.SchemeGroupVersion.WithKind("UDPRouteRule").GroupKind() ) const nameSectionNameURLSeparator = '#'