Skip to content

Commit f33b808

Browse files
committed
add http, grpc. add resolving service
1 parent 58a1e06 commit f33b808

File tree

11 files changed

+633
-135
lines changed

11 files changed

+633
-135
lines changed

pkg/gateway/routeutils/backend.go

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,77 @@
11
package routeutils
22

3-
import v1 "k8s.io/api/core/v1"
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/pkg/errors"
7+
corev1 "k8s.io/api/core/v1"
8+
"k8s.io/apimachinery/pkg/types"
9+
"sigs.k8s.io/controller-runtime/pkg/client"
10+
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
11+
)
412

5-
type BackendDescription interface {
6-
GetService() *v1.Service
7-
GetWeight() int32
8-
GetPort() int
13+
type Backend struct {
14+
Service *corev1.Service
15+
ServicePort *corev1.ServicePort
16+
Weight int
17+
// Add TG config here //
918
}
1019

11-
var _ BackendDescription = &backendDescriptionImpl{}
20+
func commonBackendLoader(ctx context.Context, k8sClient client.Client, backendRef gwv1.BackendRef, routeIdentifier types.NamespacedName, routeKind string) (*Backend, error) {
21+
if backendRef.Port == nil {
22+
return nil, errors.Errorf("Missing port in backend reference")
23+
}
24+
var namespace string
25+
if backendRef.Namespace == nil {
26+
namespace = routeIdentifier.Namespace
27+
} else {
28+
namespace = string(*backendRef.Namespace)
29+
}
1230

13-
type backendDescriptionImpl struct {
14-
}
31+
svcName := types.NamespacedName{
32+
Namespace: namespace,
33+
Name: string(backendRef.Name),
34+
}
35+
svc := &corev1.Service{}
36+
err := k8sClient.Get(ctx, svcName, svc)
37+
if err != nil {
38+
return nil, errors.Wrap(err, fmt.Sprintf("Unable to fetch svc object %+v", svcName))
39+
}
1540

16-
func (b backendDescriptionImpl) GetService() *v1.Service {
17-
//TODO implement me
18-
panic("implement me")
19-
}
41+
// TODO -- Is this correct?
42+
var servicePort *corev1.ServicePort
2043

21-
func (b backendDescriptionImpl) GetWeight() int32 {
22-
//TODO implement me
23-
panic("implement me")
24-
}
44+
for _, svcPort := range svc.Spec.Ports {
45+
if svcPort.Port == int32(*backendRef.Port) {
46+
servicePort = &svcPort
47+
break
48+
}
49+
}
50+
51+
if servicePort == nil {
52+
return nil, errors.Errorf("Unable to find service port for port %d", *backendRef.Port)
53+
}
54+
55+
// look up target group config here
2556

26-
func (b backendDescriptionImpl) GetPort() int {
27-
//TODO implement me
28-
panic("implement me")
57+
// Weight specifies the proportion of requests forwarded to the referenced
58+
// backend. This is computed as weight/(sum of all weights in this
59+
// BackendRefs list). For non-zero values, there may be some epsilon from
60+
// the exact proportion defined here depending on the precision an
61+
// implementation supports. Weight is not a percentage and the sum of
62+
// weights does not need to equal 100.
63+
//
64+
// If only one backend is specified and it has a weight greater than 0, 100%
65+
// of the traffic is forwarded to that backend. If weight is set to 0, no
66+
// traffic should be forwarded for this entry. If unspecified, weight
67+
// defaults to 1.
68+
weight := 1
69+
if backendRef.Weight != nil {
70+
weight = int(*backendRef.Weight)
71+
}
72+
return &Backend{
73+
Service: svc,
74+
ServicePort: servicePort,
75+
Weight: weight,
76+
}, nil
2977
}

pkg/gateway/routeutils/constants.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ const (
1414
GRPCRouteKind = "GRPCRoute"
1515
)
1616

17-
var allRoutes = map[string]func(context context.Context, client client.Client) ([]RouteDescriptor, error){
17+
var allRoutes = map[string]func(context context.Context, client client.Client) ([]preLoadRouteDescriptor, error){
1818
TCPRouteKind: ListTCPRoutes,
1919
UDPRouteKind: ListUDPRoutes,
2020
TLSRouteKind: ListTLSRoutes,
21-
HTTPRouteKind: nil,
22-
GRPCRouteKind: nil,
21+
HTTPRouteKind: ListHTTPRoutes,
22+
GRPCRouteKind: ListGRPCRoutes,
2323
}
2424

2525
var defaultProtocolToRouteKindMap = map[gwv1.ProtocolType]string{
Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
package routeutils
22

3-
type RouteDescriptor interface {
4-
GetRouteNamespace() string
5-
GetRouteName() string
3+
import (
4+
"context"
5+
"k8s.io/apimachinery/pkg/types"
6+
"sigs.k8s.io/controller-runtime/pkg/client"
7+
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
8+
)
9+
10+
type routeMetadataDescriptor interface {
11+
GetRouteNamespacedName() types.NamespacedName
612
GetRouteKind() string
7-
GetAttachedRules() []BackendDescription
13+
GetParentRefs() []gwv1.ParentReference
814
GetRawRoute() interface{}
915
}
16+
17+
type preLoadRouteDescriptor interface {
18+
routeMetadataDescriptor
19+
loadAttachedRules(context context.Context, k8sClient client.Client) (RouteDescriptor, error)
20+
}
21+
22+
type RouteDescriptor interface {
23+
routeMetadataDescriptor
24+
GetAttachedRules() []RouteRule
25+
}

pkg/gateway/routeutils/grpc.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package routeutils
2+
3+
import (
4+
"context"
5+
"k8s.io/apimachinery/pkg/types"
6+
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
7+
"sigs.k8s.io/controller-runtime/pkg/client"
8+
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
9+
)
10+
11+
var _ RouteRule = &convertedGRPCRouteRule{}
12+
13+
type convertedGRPCRouteRule struct {
14+
rule *gwv1.GRPCRouteRule
15+
backends []Backend
16+
}
17+
18+
func convertGRPCRouteRule(rule *gwv1.GRPCRouteRule, backends []Backend) RouteRule {
19+
return &convertedGRPCRouteRule{
20+
rule: rule,
21+
backends: backends,
22+
}
23+
}
24+
25+
func (t *convertedGRPCRouteRule) GetSectionName() *gwv1.SectionName {
26+
return t.rule.Name
27+
}
28+
29+
func (t *convertedGRPCRouteRule) GetBackends() []Backend {
30+
return t.backends
31+
}
32+
33+
func (t *convertedGRPCRouteRule) GetHostnames() []string {
34+
return t.GetHostnames()
35+
}
36+
37+
type grpcRouteDescription struct {
38+
route *gwv1.GRPCRoute
39+
rules []RouteRule
40+
}
41+
42+
func (grpcRoute *grpcRouteDescription) loadAttachedRules(ctx context.Context, k8sClient client.Client) (RouteDescriptor, error) {
43+
convertedRules := make([]RouteRule, 0)
44+
for _, rule := range grpcRoute.route.Spec.Rules {
45+
convertedBackends := make([]Backend, 0)
46+
47+
for _, backend := range rule.BackendRefs {
48+
// TODO - Figure out what stuff we need to transpose from GRPCBackendRef.
49+
// GRPCRouteFilter
50+
convertedBackend, err := commonBackendLoader(ctx, k8sClient, backend.BackendRef, grpcRoute.GetRouteNamespacedName(), grpcRoute.GetRouteKind())
51+
if err != nil {
52+
return nil, err
53+
}
54+
convertedBackends = append(convertedBackends, *convertedBackend)
55+
}
56+
57+
convertedRules = append(convertedRules, convertGRPCRouteRule(&rule, convertedBackends))
58+
}
59+
60+
grpcRoute.rules = convertedRules
61+
return grpcRoute, nil
62+
}
63+
64+
func (grpcRoute *grpcRouteDescription) GetAttachedRules() []RouteRule {
65+
return grpcRoute.rules
66+
}
67+
68+
func (grpcRoute *grpcRouteDescription) GetParentRefs() []gwv1.ParentReference {
69+
return grpcRoute.route.Spec.ParentRefs
70+
}
71+
72+
func (grpcRoute *grpcRouteDescription) GetRouteKind() string {
73+
return GRPCRouteKind
74+
}
75+
76+
func (grpcRoute *grpcRouteDescription) GetRouteNamespacedName() types.NamespacedName {
77+
return k8s.NamespacedName(grpcRoute.route)
78+
}
79+
80+
func convertGRPCRoute(r gwv1.GRPCRoute) *grpcRouteDescription {
81+
return &grpcRouteDescription{route: &r}
82+
}
83+
84+
func (grpcRoute *grpcRouteDescription) GetRawRoute() interface{} {
85+
return grpcRoute.route
86+
}
87+
88+
var _ RouteDescriptor = &grpcRouteDescription{}
89+
90+
// Can we use an indexer here to query more efficiently?
91+
92+
func ListGRPCRoutes(context context.Context, k8sClient client.Client) ([]preLoadRouteDescriptor, error) {
93+
routeList := &gwv1.GRPCRouteList{}
94+
err := k8sClient.List(context, routeList)
95+
if err != nil {
96+
return nil, err
97+
}
98+
99+
result := make([]preLoadRouteDescriptor, 0)
100+
101+
for _, item := range routeList.Items {
102+
result = append(result, convertGRPCRoute(item))
103+
}
104+
105+
return result, err
106+
}

pkg/gateway/routeutils/http.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package routeutils
2+
3+
import (
4+
"context"
5+
"k8s.io/apimachinery/pkg/types"
6+
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
7+
"sigs.k8s.io/controller-runtime/pkg/client"
8+
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
9+
)
10+
11+
var _ RouteRule = &convertedHTTPRouteRule{}
12+
13+
type convertedHTTPRouteRule struct {
14+
rule *gwv1.HTTPRouteRule
15+
backends []Backend
16+
}
17+
18+
func convertHTTPRouteRule(rule *gwv1.HTTPRouteRule, backends []Backend) RouteRule {
19+
return &convertedHTTPRouteRule{
20+
rule: rule,
21+
backends: backends,
22+
}
23+
}
24+
25+
func (t *convertedHTTPRouteRule) GetSectionName() *gwv1.SectionName {
26+
return t.rule.Name
27+
}
28+
29+
func (t *convertedHTTPRouteRule) GetBackends() []Backend {
30+
return t.backends
31+
}
32+
33+
func (t *convertedHTTPRouteRule) GetHostnames() []string {
34+
// TODO - What to do about HTTPS?
35+
return []string{}
36+
}
37+
38+
type httpRouteDescription struct {
39+
route *gwv1.HTTPRoute
40+
rules []RouteRule
41+
}
42+
43+
func (httpRoute *httpRouteDescription) GetAttachedRules() []RouteRule {
44+
return httpRoute.rules
45+
}
46+
47+
func (httpRoute *httpRouteDescription) loadAttachedRules(ctx context.Context, k8sClient client.Client) (RouteDescriptor, error) {
48+
convertedRules := make([]RouteRule, 0)
49+
for _, rule := range httpRoute.route.Spec.Rules {
50+
convertedBackends := make([]Backend, 0)
51+
52+
for _, backend := range rule.BackendRefs {
53+
// TODO - What are we missing here when just using backend refs?
54+
// Backend filters - HTTPRouteFilters
55+
convertedBackend, err := commonBackendLoader(ctx, k8sClient, backend.BackendRef, httpRoute.GetRouteNamespacedName(), httpRoute.GetRouteKind())
56+
if err != nil {
57+
return nil, err
58+
}
59+
convertedBackends = append(convertedBackends, *convertedBackend)
60+
}
61+
62+
convertedRules = append(convertedRules, convertHTTPRouteRule(&rule, convertedBackends))
63+
}
64+
65+
httpRoute.rules = convertedRules
66+
return httpRoute, nil
67+
}
68+
69+
func (httpRoute *httpRouteDescription) GetParentRefs() []gwv1.ParentReference {
70+
return httpRoute.route.Spec.ParentRefs
71+
}
72+
73+
func (httpRoute *httpRouteDescription) GetRouteKind() string {
74+
return HTTPRouteKind
75+
}
76+
77+
func (httpRoute *httpRouteDescription) GetRouteNamespacedName() types.NamespacedName {
78+
return k8s.NamespacedName(httpRoute.route)
79+
}
80+
81+
func convertHTTPRoute(r gwv1.HTTPRoute) *httpRouteDescription {
82+
return &httpRouteDescription{route: &r}
83+
}
84+
85+
func (httpRoute *httpRouteDescription) GetRawRoute() interface{} {
86+
return httpRoute.route
87+
}
88+
89+
var _ RouteDescriptor = &httpRouteDescription{}
90+
91+
// Can we use an indexer here to query more efficiently?
92+
93+
func ListHTTPRoutes(context context.Context, k8sClient client.Client) ([]preLoadRouteDescriptor, error) {
94+
routeList := &gwv1.HTTPRouteList{}
95+
err := k8sClient.List(context, routeList)
96+
if err != nil {
97+
return nil, err
98+
}
99+
100+
result := make([]preLoadRouteDescriptor, 0)
101+
102+
for _, item := range routeList.Items {
103+
result = append(result, convertHTTPRoute(item))
104+
}
105+
106+
return result, err
107+
}

0 commit comments

Comments
 (0)