Skip to content

Commit 5a062c1

Browse files
committed
feature: zone aware eskip.LBEndpoints
Signed-off-by: Sandor Szücs <[email protected]>
1 parent 5a13740 commit 5a062c1

17 files changed

+120
-66
lines changed

dataclients/kubernetes/ingressv1.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func convertPathRuleV1(
151151
r := &eskip.Route{
152152
Id: routeID(ns, name, host, prule.Path, svcName),
153153
BackendType: eskip.LBBackend,
154-
LBEndpoints: eps,
154+
LBEndpoints: eskip.NewLBEndpoints(eps),
155155
LBAlgorithm: getLoadBalancerAlgorithm(metadata, defaultLoadBalancerAlgorithm),
156156
HostRegexps: hostRegexp,
157157
}
@@ -397,7 +397,7 @@ func (ing *ingress) convertDefaultBackendV1(
397397
return &eskip.Route{
398398
Id: routeID(ns, name, "", "", ""),
399399
BackendType: eskip.LBBackend,
400-
LBEndpoints: eps,
400+
LBEndpoints: eskip.NewLBEndpoints(eps),
401401
LBAlgorithm: getLoadBalancerAlgorithm(i.Metadata, ing.defaultLoadBalancerAlgorithm),
402402
}, true, nil
403403
}

dataclients/kubernetes/routegroup.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func applyServiceBackend(ctx *routeGroupContext, backend *definitions.SkipperBac
208208
}
209209

210210
r.BackendType = eskip.LBBackend
211-
r.LBEndpoints = eps
211+
r.LBEndpoints = eskip.NewLBEndpoints(eps)
212212
r.LBAlgorithm = ctx.defaultLoadBalancerAlgorithm
213213
if backend.Algorithm != loadbalancer.None {
214214
r.LBAlgorithm = backend.Algorithm.String()
@@ -261,7 +261,7 @@ func applyBackend(ctx *routeGroupContext, backend *definitions.SkipperBackend, r
261261
}
262262
}
263263

264-
r.LBEndpoints = backend.Endpoints
264+
r.LBEndpoints = eskip.NewLBEndpoints(backend.Endpoints)
265265
r.LBAlgorithm = ctx.defaultLoadBalancerAlgorithm
266266
if backend.Algorithm != loadbalancer.None {
267267
r.LBAlgorithm = backend.Algorithm.String()

eskip/copy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func Copy(r *Route) *Route {
6565
c.BackendType = r.BackendType
6666
c.Backend = r.Backend
6767
c.LBAlgorithm = r.LBAlgorithm
68-
c.LBEndpoints = make([]string, len(r.LBEndpoints))
68+
c.LBEndpoints = make([]*LBEndpoint, len(r.LBEndpoints))
6969
copy(c.LBEndpoints, r.LBEndpoints)
7070
return c
7171
}

eskip/copy_test.go

+17-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestCopy(t *testing.T) {
4242
checkFilter(t, c.Filters[i], r.Filters[i])
4343
}
4444

45-
r.LBEndpoints[0] = "test-slice-identity"
45+
r.LBEndpoints[0] = &LBEndpoint{Address: "test-slice-identity"}
4646
if c.LBEndpoints[0] == r.LBEndpoints[0] {
4747
t.Error("failed to copy LB endpoints")
4848
}
@@ -132,7 +132,10 @@ func TestCopy(t *testing.T) {
132132
},
133133
BackendType: LBBackend,
134134
LBAlgorithm: "roundRobin",
135-
LBEndpoints: []string{"10.0.0.1:80", "10.0.0.2:80"},
135+
LBEndpoints: []*LBEndpoint{
136+
{Address: "10.0.0.1:80"},
137+
{Address: "10.0.0.2:80"},
138+
},
136139
}
137140

138141
c := Copy(r)
@@ -154,7 +157,10 @@ func TestCopy(t *testing.T) {
154157
},
155158
BackendType: LBBackend,
156159
LBAlgorithm: "roundRobin",
157-
LBEndpoints: []string{"10.0.1.1:80", "10.0.1.2:80"},
160+
LBEndpoints: []*LBEndpoint{
161+
{Address: "10.0.1.1:80"},
162+
{Address: "10.0.1.2:80"},
163+
},
158164
}, {
159165
Id: "route2",
160166
Predicates: []*Predicate{
@@ -169,7 +175,10 @@ func TestCopy(t *testing.T) {
169175
},
170176
BackendType: LBBackend,
171177
LBAlgorithm: "roundRobin",
172-
LBEndpoints: []string{"10.0.2.1:80", "10.0.2.2:80"},
178+
LBEndpoints: []*LBEndpoint{
179+
{Address: "10.0.2.1:80"},
180+
{Address: "10.0.2.2:80"},
181+
},
173182
}, {
174183
Id: "route3",
175184
Predicates: []*Predicate{
@@ -184,7 +193,10 @@ func TestCopy(t *testing.T) {
184193
},
185194
BackendType: LBBackend,
186195
LBAlgorithm: "roundRobin",
187-
LBEndpoints: []string{"10.0.3.1:80", "10.0.3.2:80"},
196+
LBEndpoints: []*LBEndpoint{
197+
{Address: "10.0.3.1:80"},
198+
{Address: "10.0.3.2:80"},
199+
},
188200
}}
189201

190202
c := CopyRoutes(r)

eskip/eq.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ func eqArgs(left, right []interface{}) bool {
4040
return true
4141
}
4242

43-
func eqStrings(left, right []string) bool {
43+
func eqLBEndpoints(left, right []*LBEndpoint) bool {
4444
if len(left) != len(right) {
4545
return false
4646
}
4747

4848
for i := range left {
49-
if left[i] != right[i] {
49+
if left[i].Address != right[i].Address && left[i].Zone != right[i].Zone {
5050
return false
5151
}
5252
}
@@ -103,7 +103,7 @@ func eq2(left, right *Route) bool {
103103
return false
104104
}
105105

106-
if !eqStrings(lc.LBEndpoints, rc.LBEndpoints) {
106+
if !eqLBEndpoints(lc.LBEndpoints, rc.LBEndpoints) {
107107
return false
108108
}
109109

@@ -255,9 +255,11 @@ func Canonical(r *Route) *Route {
255255
case LBBackend:
256256
// using the LB fields only when apply:
257257
c.LBAlgorithm = r.LBAlgorithm
258-
c.LBEndpoints = make([]string, len(r.LBEndpoints))
258+
c.LBEndpoints = make([]*LBEndpoint, len(r.LBEndpoints))
259259
copy(c.LBEndpoints, r.LBEndpoints)
260-
sort.Strings(c.LBEndpoints)
260+
sort.Slice(c.LBEndpoints, func(i, j int) bool {
261+
return c.LBEndpoints[i].Address < c.LBEndpoints[j].Address
262+
})
261263
}
262264

263265
// Name and Namespace stripped

eskip/eq_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ func TestEq(t *testing.T) {
9999
}, {
100100
title: "non-eq lb endpoint count",
101101
routes: []*Route{
102-
{BackendType: LBBackend, LBEndpoints: []string{"", ""}},
103-
{BackendType: LBBackend, LBEndpoints: []string{""}},
102+
{BackendType: LBBackend, LBEndpoints: []*LBEndpoint{nil, nil}},
103+
{BackendType: LBBackend, LBEndpoints: []*LBEndpoint{nil}},
104104
},
105105
}, {
106106
title: "non-eq lb endpoints",
107107
routes: []*Route{
108-
{BackendType: LBBackend, LBEndpoints: []string{"https://one.example.org"}},
109-
{BackendType: LBBackend, LBEndpoints: []string{"https://two.example.org"}},
108+
{BackendType: LBBackend, LBEndpoints: []*LBEndpoint{{Address: "https://one.example.org"}}},
109+
{BackendType: LBBackend, LBEndpoints: []*LBEndpoint{{Address: "https://two.example.org"}}},
110110
},
111111
}, {
112112
title: "all eq",
@@ -116,14 +116,14 @@ func TestEq(t *testing.T) {
116116
Filters: []*Filter{{Name: "foo", Args: []interface{}{3, 4}}},
117117
BackendType: LBBackend,
118118
LBAlgorithm: "random",
119-
LBEndpoints: []string{"https://one.example.org", "https://two.example.org"},
119+
LBEndpoints: []*LBEndpoint{{Address: "https://one.example.org"}, {Address: "https://two.example.org"}},
120120
}, {
121121
Id: "foo",
122122
Predicates: []*Predicate{{Name: "Foo", Args: []interface{}{1, 2}}},
123123
Filters: []*Filter{{Name: "foo", Args: []interface{}{3, 4}}},
124124
BackendType: LBBackend,
125125
LBAlgorithm: "random",
126-
LBEndpoints: []string{"https://one.example.org", "https://two.example.org"},
126+
LBEndpoints: []*LBEndpoint{{Address: "https://one.example.org"}, {Address: "https://two.example.org"}},
127127
}},
128128
expect: true,
129129
}, {
@@ -282,7 +282,7 @@ func TestCanonical(t *testing.T) {
282282
expect: &Route{BackendType: NetworkBackend, Backend: "https://www.example.org"},
283283
}, {
284284
title: "clear LB when different type",
285-
route: &Route{LBEndpoints: []string{"https://one.example.org", "https://two.example.org"}},
285+
route: &Route{LBEndpoints: []*LBEndpoint{{Address: "https://one.example.org"}, {Address: "https://two.example.org"}}},
286286
expect: &Route{},
287287
}} {
288288
t.Run(test.title, func(t *testing.T) {

eskip/eskip.go

+40-3
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ type Route struct {
321321

322322
// LBEndpoints stores one or more backend endpoint in case of
323323
// load balancing backends.
324-
LBEndpoints []string
324+
LBEndpoints []*LBEndpoint
325325

326326
// Name is deprecated and not used.
327327
Name string
@@ -330,6 +330,43 @@ type Route struct {
330330
Namespace string
331331
}
332332

333+
func NewLBEndpoints(eps []string) []*LBEndpoint {
334+
if len(eps) == 0 {
335+
return nil
336+
}
337+
result := make([]*LBEndpoint, len(eps))
338+
339+
for i := 0; i < len(eps); i++ {
340+
result[i] = &LBEndpoint{
341+
Address: eps[i],
342+
}
343+
}
344+
345+
return result
346+
}
347+
348+
func LBEndpointString(eps []*LBEndpoint) []string {
349+
if len(eps) == 0 {
350+
return nil
351+
}
352+
result := make([]string, len(eps))
353+
354+
for i := 0; i < len(eps); i++ {
355+
result[i] = eps[i].String()
356+
}
357+
358+
return result
359+
}
360+
361+
type LBEndpoint struct {
362+
Address string
363+
Zone string
364+
}
365+
366+
func (ep LBEndpoint) String() string {
367+
return ep.Address
368+
}
369+
333370
type RoutePredicate func(*Route) bool
334371

335372
// RouteInfo contains a route id, plus the loaded and parsed route or
@@ -402,7 +439,7 @@ func (r *Route) Copy() *Route {
402439
}
403440

404441
if len(r.LBEndpoints) > 0 {
405-
c.LBEndpoints = make([]string, len(r.LBEndpoints))
442+
c.LBEndpoints = make([]*LBEndpoint, len(r.LBEndpoints))
406443
copy(c.LBEndpoints, r.LBEndpoints)
407444
}
408445

@@ -561,7 +598,7 @@ func newRouteDefinition(r *parsedRoute) (*Route, error) {
561598
rd.Shunt = r.shunt
562599
rd.Backend = r.backend
563600
rd.LBAlgorithm = r.lbAlgorithm
564-
rd.LBEndpoints = r.lbEndpoints
601+
rd.LBEndpoints = NewLBEndpoints(r.lbEndpoints)
565602

566603
switch {
567604
case r.shunt:

eskip/json.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func newJSONRoute(r *Route) *jsonRoute {
3737
Type: cr.BackendType.String(),
3838
Address: cr.Backend,
3939
Algorithm: cr.LBAlgorithm,
40-
Endpoints: cr.LBEndpoints,
40+
Endpoints: LBEndpointString(cr.LBEndpoints),
4141
}
4242
}
4343

@@ -94,7 +94,7 @@ func (r *Route) UnmarshalJSON(b []byte) error {
9494
}
9595
case LBBackend:
9696
r.LBAlgorithm = jr.Backend.Algorithm
97-
r.LBEndpoints = jr.Backend.Endpoints
97+
r.LBEndpoints = NewLBEndpoints(jr.Backend.Endpoints)
9898
if len(r.LBEndpoints) == 0 {
9999
r.LBEndpoints = nil
100100
}

eskip/json_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func TestMarshalUnmarshalJSON(t *testing.T) {
8888
},
8989
{
9090
"lb backend",
91-
[]*Route{{Id: "beef", BackendType: LBBackend, LBAlgorithm: "yolo", LBEndpoints: []string{"localhost"}}},
91+
[]*Route{{Id: "beef", BackendType: LBBackend, LBAlgorithm: "yolo", LBEndpoints: []*LBEndpoint{{Address: "localhost"}}}},
9292
`[{"id":"beef","backend":{"type":"lb","algorithm":"yolo","endpoints":["localhost"]}}]`,
9393
},
9494
{

eskip/parser_test.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ func TestLBBackend(t *testing.T) {
255255
code: `* -> <"https://example.org">`,
256256
expectedResult: []*Route{{
257257
BackendType: LBBackend,
258-
LBEndpoints: []string{"https://example.org"},
258+
LBEndpoints: []*LBEndpoint{{Address: "https://example.org"}},
259259
}},
260260
}, {
261261
title: "multiple endpoints, default algorithm",
@@ -264,10 +264,10 @@ func TestLBBackend(t *testing.T) {
264264
"https://example3.org">`,
265265
expectedResult: []*Route{{
266266
BackendType: LBBackend,
267-
LBEndpoints: []string{
268-
"https://example1.org",
269-
"https://example2.org",
270-
"https://example3.org",
267+
LBEndpoints: []*LBEndpoint{
268+
{Address: "https://example1.org"},
269+
{Address: "https://example2.org"},
270+
{Address: "https://example3.org"},
271271
},
272272
}},
273273
}, {
@@ -276,7 +276,7 @@ func TestLBBackend(t *testing.T) {
276276
expectedResult: []*Route{{
277277
BackendType: LBBackend,
278278
LBAlgorithm: "algFoo",
279-
LBEndpoints: []string{"https://example.org"},
279+
LBEndpoints: []*LBEndpoint{{Address: "https://example.org"}},
280280
}},
281281
}, {
282282
title: "multiple endpoints, default algorithm",
@@ -287,10 +287,10 @@ func TestLBBackend(t *testing.T) {
287287
expectedResult: []*Route{{
288288
BackendType: LBBackend,
289289
LBAlgorithm: "algFoo",
290-
LBEndpoints: []string{
291-
"https://example1.org",
292-
"https://example2.org",
293-
"https://example3.org",
290+
LBEndpoints: []*LBEndpoint{
291+
{Address: "https://example1.org"},
292+
{Address: "https://example2.org"},
293+
{Address: "https://example3.org"},
294294
},
295295
}},
296296
}, {
@@ -303,10 +303,10 @@ func TestLBBackend(t *testing.T) {
303303
Filters: []*Filter{{Name: "foo"}},
304304
BackendType: LBBackend,
305305
LBAlgorithm: "algFoo",
306-
LBEndpoints: []string{
307-
"https://example1.org",
308-
"https://example2.org",
309-
"https://example3.org",
306+
LBEndpoints: []*LBEndpoint{
307+
{Address: "https://example1.org"},
308+
{Address: "https://example2.org"},
309+
{Address: "https://example3.org"},
310310
},
311311
}},
312312
}} {

eskip/string.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func lbBackendString(r *Route) string {
167167
b.WriteString(", ")
168168
}
169169
b.WriteByte('"')
170-
b.WriteString(ep)
170+
b.WriteString(ep.String())
171171
b.WriteByte('"')
172172
}
173173
b.WriteByte('>')

eskip/string_test.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,16 @@ func TestRouteString(t *testing.T) {
112112
BackendType: DynamicBackend},
113113
`* -> filter0("Line 1\r\nLine 2") -> <dynamic>`,
114114
}, {
115-
&Route{Method: "GET", BackendType: LBBackend, LBEndpoints: []string{"http://127.0.0.1:9997"}},
115+
&Route{Method: "GET", BackendType: LBBackend, LBEndpoints: []*LBEndpoint{{Address: "http://127.0.0.1:9997"}}},
116116
`Method("GET") -> <"http://127.0.0.1:9997">`,
117117
}, {
118-
&Route{Method: "GET", LBAlgorithm: "random", BackendType: LBBackend, LBEndpoints: []string{"http://127.0.0.1:9997"}},
118+
&Route{Method: "GET", LBAlgorithm: "random", BackendType: LBBackend, LBEndpoints: []*LBEndpoint{{Address: "http://127.0.0.1:9997"}}},
119119
`Method("GET") -> <random, "http://127.0.0.1:9997">`,
120120
}, {
121-
&Route{Method: "GET", LBAlgorithm: "random", BackendType: LBBackend, LBEndpoints: []string{"http://127.0.0.1:9997", "http://127.0.0.1:9998"}},
121+
&Route{Method: "GET", LBAlgorithm: "random", BackendType: LBBackend, LBEndpoints: []*LBEndpoint{
122+
{Address: "http://127.0.0.1:9997"},
123+
{Address: "http://127.0.0.1:9998"},
124+
}},
122125
`Method("GET") -> <random, "http://127.0.0.1:9997", "http://127.0.0.1:9998">`,
123126
}, {
124127
// test slash escaping

loadbalancer/algorithm.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ func (a Algorithm) String() string {
312312
func parseEndpoints(r *routing.Route) error {
313313
r.LBEndpoints = make([]routing.LBEndpoint, len(r.Route.LBEndpoints))
314314
for i, e := range r.Route.LBEndpoints {
315-
scheme, host, err := snet.SchemeHost(e)
315+
scheme, host, err := snet.SchemeHost(e.String())
316316
if err != nil {
317317
return err
318318
}
@@ -337,7 +337,7 @@ func setAlgorithm(r *routing.Route) error {
337337
initialize = algorithms[t]
338338
}
339339

340-
r.LBAlgorithm = initialize(r.Route.LBEndpoints)
340+
r.LBAlgorithm = initialize(eskip.LBEndpointString(r.Route.LBEndpoints))
341341
return nil
342342
}
343343

0 commit comments

Comments
 (0)