Skip to content

Commit ba3cc97

Browse files
committed
Attach VSR to VS by labels
Signed-off-by: Haywood Shannon <[email protected]>
1 parent 214d9f1 commit ba3cc97

File tree

11 files changed

+286
-35
lines changed

11 files changed

+286
-35
lines changed

config/crd/bases/k8s.nginx.org_virtualserverroutes.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,55 @@ spec:
438438
type: array
439439
route:
440440
type: string
441+
routeSelector:
442+
description: |-
443+
A label selector is a label query over a set of resources. The result of matchLabels and
444+
matchExpressions are ANDed. An empty label selector matches all objects. A null
445+
label selector matches no objects.
446+
properties:
447+
matchExpressions:
448+
description: matchExpressions is a list of label selector
449+
requirements. The requirements are ANDed.
450+
items:
451+
description: |-
452+
A label selector requirement is a selector that contains values, a key, and an operator that
453+
relates the key and values.
454+
properties:
455+
key:
456+
description: key is the label key that the selector
457+
applies to.
458+
type: string
459+
operator:
460+
description: |-
461+
operator represents a key's relationship to a set of values.
462+
Valid operators are In, NotIn, Exists and DoesNotExist.
463+
type: string
464+
values:
465+
description: |-
466+
values is an array of string values. If the operator is In or NotIn,
467+
the values array must be non-empty. If the operator is Exists or DoesNotExist,
468+
the values array must be empty. This array is replaced during a strategic
469+
merge patch.
470+
items:
471+
type: string
472+
type: array
473+
x-kubernetes-list-type: atomic
474+
required:
475+
- key
476+
- operator
477+
type: object
478+
type: array
479+
x-kubernetes-list-type: atomic
480+
matchLabels:
481+
additionalProperties:
482+
type: string
483+
description: |-
484+
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
485+
map is equivalent to an element of matchExpressions, whose key field is "key", the
486+
operator is "In", and the values array contains only "value". The requirements are ANDed.
487+
type: object
488+
type: object
489+
x-kubernetes-map-type: atomic
441490
splits:
442491
items:
443492
description: Split defines a split.

config/crd/bases/k8s.nginx.org_virtualservers.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,55 @@ spec:
500500
type: array
501501
route:
502502
type: string
503+
routeSelector:
504+
description: |-
505+
A label selector is a label query over a set of resources. The result of matchLabels and
506+
matchExpressions are ANDed. An empty label selector matches all objects. A null
507+
label selector matches no objects.
508+
properties:
509+
matchExpressions:
510+
description: matchExpressions is a list of label selector
511+
requirements. The requirements are ANDed.
512+
items:
513+
description: |-
514+
A label selector requirement is a selector that contains values, a key, and an operator that
515+
relates the key and values.
516+
properties:
517+
key:
518+
description: key is the label key that the selector
519+
applies to.
520+
type: string
521+
operator:
522+
description: |-
523+
operator represents a key's relationship to a set of values.
524+
Valid operators are In, NotIn, Exists and DoesNotExist.
525+
type: string
526+
values:
527+
description: |-
528+
values is an array of string values. If the operator is In or NotIn,
529+
the values array must be non-empty. If the operator is Exists or DoesNotExist,
530+
the values array must be empty. This array is replaced during a strategic
531+
merge patch.
532+
items:
533+
type: string
534+
type: array
535+
x-kubernetes-list-type: atomic
536+
required:
537+
- key
538+
- operator
539+
type: object
540+
type: array
541+
x-kubernetes-list-type: atomic
542+
matchLabels:
543+
additionalProperties:
544+
type: string
545+
description: |-
546+
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
547+
map is equivalent to an element of matchExpressions, whose key field is "key", the
548+
operator is "In", and the values array contains only "value". The requirements are ANDed.
549+
type: object
550+
type: object
551+
x-kubernetes-map-type: atomic
503552
splits:
504553
items:
505554
description: Split defines a split.

deploy/crds.yaml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,55 @@ spec:
13381338
type: array
13391339
route:
13401340
type: string
1341+
routeSelector:
1342+
description: |-
1343+
A label selector is a label query over a set of resources. The result of matchLabels and
1344+
matchExpressions are ANDed. An empty label selector matches all objects. A null
1345+
label selector matches no objects.
1346+
properties:
1347+
matchExpressions:
1348+
description: matchExpressions is a list of label selector
1349+
requirements. The requirements are ANDed.
1350+
items:
1351+
description: |-
1352+
A label selector requirement is a selector that contains values, a key, and an operator that
1353+
relates the key and values.
1354+
properties:
1355+
key:
1356+
description: key is the label key that the selector
1357+
applies to.
1358+
type: string
1359+
operator:
1360+
description: |-
1361+
operator represents a key's relationship to a set of values.
1362+
Valid operators are In, NotIn, Exists and DoesNotExist.
1363+
type: string
1364+
values:
1365+
description: |-
1366+
values is an array of string values. If the operator is In or NotIn,
1367+
the values array must be non-empty. If the operator is Exists or DoesNotExist,
1368+
the values array must be empty. This array is replaced during a strategic
1369+
merge patch.
1370+
items:
1371+
type: string
1372+
type: array
1373+
x-kubernetes-list-type: atomic
1374+
required:
1375+
- key
1376+
- operator
1377+
type: object
1378+
type: array
1379+
x-kubernetes-list-type: atomic
1380+
matchLabels:
1381+
additionalProperties:
1382+
type: string
1383+
description: |-
1384+
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
1385+
map is equivalent to an element of matchExpressions, whose key field is "key", the
1386+
operator is "In", and the values array contains only "value". The requirements are ANDed.
1387+
type: object
1388+
type: object
1389+
x-kubernetes-map-type: atomic
13411390
splits:
13421391
items:
13431392
description: Split defines a split.
@@ -2129,6 +2178,55 @@ spec:
21292178
type: array
21302179
route:
21312180
type: string
2181+
routeSelector:
2182+
description: |-
2183+
A label selector is a label query over a set of resources. The result of matchLabels and
2184+
matchExpressions are ANDed. An empty label selector matches all objects. A null
2185+
label selector matches no objects.
2186+
properties:
2187+
matchExpressions:
2188+
description: matchExpressions is a list of label selector
2189+
requirements. The requirements are ANDed.
2190+
items:
2191+
description: |-
2192+
A label selector requirement is a selector that contains values, a key, and an operator that
2193+
relates the key and values.
2194+
properties:
2195+
key:
2196+
description: key is the label key that the selector
2197+
applies to.
2198+
type: string
2199+
operator:
2200+
description: |-
2201+
operator represents a key's relationship to a set of values.
2202+
Valid operators are In, NotIn, Exists and DoesNotExist.
2203+
type: string
2204+
values:
2205+
description: |-
2206+
values is an array of string values. If the operator is In or NotIn,
2207+
the values array must be non-empty. If the operator is Exists or DoesNotExist,
2208+
the values array must be empty. This array is replaced during a strategic
2209+
merge patch.
2210+
items:
2211+
type: string
2212+
type: array
2213+
x-kubernetes-list-type: atomic
2214+
required:
2215+
- key
2216+
- operator
2217+
type: object
2218+
type: array
2219+
x-kubernetes-list-type: atomic
2220+
matchLabels:
2221+
additionalProperties:
2222+
type: string
2223+
description: |-
2224+
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
2225+
map is equivalent to an element of matchExpressions, whose key field is "key", the
2226+
operator is "In", and the values array contains only "value". The requirements are ANDed.
2227+
type: object
2228+
type: object
2229+
x-kubernetes-map-type: atomic
21322230
splits:
21332231
items:
21342232
description: Split defines a split.

examples/custom-resources/cross-namespace-configuration/cafe-virtual-server.yaml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ spec:
88
tls:
99
secret: cafe-secret
1010
routes:
11-
- path: /tea
12-
route: tea/tea
13-
- path: /coffee
14-
route: coffee/coffee
11+
# - path: /tea
12+
# route: tea/tea
13+
# - path: /coffee
14+
# route: coffee/coffee
15+
# - path: /coffee
16+
# routeSelector:
17+
# matchLabels:
18+
# route: coffee
19+
- path: /
20+
routeSelector:
21+
matchLabels:
22+
app: cafe

examples/custom-resources/cross-namespace-configuration/coffee-virtual-server-route.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ kind: VirtualServerRoute
33
metadata:
44
name: coffee
55
namespace: coffee
6+
labels:
7+
route: coffee
8+
app: cafe
69
spec:
710
host: cafe.example.com
811
upstreams:

examples/custom-resources/cross-namespace-configuration/tea-virtual-server-route.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ kind: VirtualServerRoute
33
metadata:
44
name: tea
55
namespace: tea
6+
labels:
7+
# route: tea
8+
app: cafe
69
spec:
710
host: cafe.example.com
811
upstreams:

internal/configs/virtualserver.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,12 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
568568
vsrPoliciesFromVs[name] = r.Policies
569569
}
570570

571+
continue
572+
} else if r.RouteSelector != nil {
573+
selector := r.RouteSelector
574+
glog.Infof("RouteSelector: %v", selector)
575+
576+
// get vsr name
571577
continue
572578
}
573579

@@ -681,6 +687,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
681687
}
682688
errorPageLocations = append(errorPageLocations, generateErrorPageLocations(errorPages.index, errorPages.pages)...)
683689
vsrNamespaceName := fmt.Sprintf("%v/%v", vsr.Namespace, vsr.Name)
690+
glog.Infof("vsrNamespaceName: %v", vsrNamespaceName)
684691
// use the VirtualServer error pages if the route does not define any
685692
if r.ErrorPages == nil {
686693
if vsErrorPages, ok := vsrErrorPagesFromVs[vsrNamespaceName]; ok {

internal/k8s/configuration.go

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package k8s
22

33
import (
44
"fmt"
5+
"github.com/golang/glog"
6+
"k8s.io/apimachinery/pkg/labels"
57
"reflect"
68
"sort"
79
"strings"
@@ -570,6 +572,7 @@ func (c *Configuration) AddOrUpdateVirtualServerRoute(vsr *conf_v1.VirtualServer
570572
if !c.hasCorrectIngressClass(vsr) {
571573
delete(c.virtualServerRoutes, key)
572574
} else {
575+
glog.Infof("labels: %v", vsr.ObjectMeta.Labels)
573576
validationError = c.virtualServerValidator.ValidateVirtualServerRoute(vsr)
574577
if validationError != nil {
575578
delete(c.virtualServerRoutes, key)
@@ -1636,32 +1639,57 @@ func (c *Configuration) buildVirtualServerRoutes(vs *conf_v1.VirtualServer) ([]*
16361639
var warnings []string
16371640

16381641
for _, r := range vs.Spec.Routes {
1639-
if r.Route == "" {
1640-
continue
1641-
}
1642+
if r.Route != "" {
1643+
vsrKey := r.Route
16421644

1643-
vsrKey := r.Route
1645+
// if route is defined without a namespace, use the namespace of VirtualServer.
1646+
if !strings.Contains(r.Route, "/") {
1647+
vsrKey = fmt.Sprintf("%s/%s", vs.Namespace, r.Route)
1648+
}
16441649

1645-
// if route is defined without a namespace, use the namespace of VirtualServer.
1646-
if !strings.Contains(r.Route, "/") {
1647-
vsrKey = fmt.Sprintf("%s/%s", vs.Namespace, r.Route)
1648-
}
1650+
vsr, exists := c.virtualServerRoutes[vsrKey]
16491651

1650-
vsr, exists := c.virtualServerRoutes[vsrKey]
1651-
if !exists {
1652-
warning := fmt.Sprintf("VirtualServerRoute %s doesn't exist or invalid", vsrKey)
1653-
warnings = append(warnings, warning)
1654-
continue
1655-
}
1652+
// if route is defined
1653+
if !exists {
1654+
warning := fmt.Sprintf("VirtualServerRoute %s doesn't exist or invalid", vsrKey)
1655+
warnings = append(warnings, warning)
1656+
continue
1657+
}
1658+
1659+
err := c.virtualServerValidator.ValidateVirtualServerRouteForVirtualServer(vsr, vs.Spec.Host, r.Path)
1660+
if err != nil {
1661+
warning := fmt.Sprintf("VirtualServerRoute %s is invalid: %v", vsrKey, err)
1662+
warnings = append(warnings, warning)
1663+
continue
1664+
}
1665+
1666+
vsrs = append(vsrs, vsr)
1667+
} else if r.RouteSelector != nil {
1668+
selector := &metav1.LabelSelector{
1669+
MatchLabels: r.RouteSelector.MatchLabels,
1670+
}
1671+
sel, err := metav1.LabelSelectorAsSelector(selector)
1672+
1673+
if err != nil {
1674+
warning := fmt.Sprintf("VirtualServerRoute LabelSelector %s is invalid: %v", selector, err)
1675+
warnings = append(warnings, warning)
1676+
continue
1677+
}
1678+
for vsrKey, vsr := range c.virtualServerRoutes {
1679+
if sel.Matches(labels.Set(vsr.ObjectMeta.Labels)) {
1680+
err := c.virtualServerValidator.ValidateVirtualServerRouteForVirtualServer(vsr, vs.Spec.Host, r.Path)
1681+
if err != nil {
1682+
warning := fmt.Sprintf("VirtualServerRoute %s is invalid: %v", vsrKey, err)
1683+
warnings = append(warnings, warning)
1684+
continue
1685+
}
1686+
glog.Infof("VirtualServerRoute %s found for label selector %v", vsrKey, selector)
1687+
vsrs = append(vsrs, vsr)
1688+
}
1689+
}
16561690

1657-
err := c.virtualServerValidator.ValidateVirtualServerRouteForVirtualServer(vsr, vs.Spec.Host, r.Path)
1658-
if err != nil {
1659-
warning := fmt.Sprintf("VirtualServerRoute %s is invalid: %v", vsrKey, err)
1660-
warnings = append(warnings, warning)
1661-
continue
16621691
}
16631692

1664-
vsrs = append(vsrs, vsr)
16651693
}
16661694

16671695
return vsrs, warnings

internal/k8s/handlers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func createVirtualServerRouteHandlers(lbc *LoadBalancerController) cache.Resourc
215215

216216
}
217217

218-
if !reflect.DeepEqual(oldVsr.Spec, curVsr.Spec) {
218+
if !reflect.DeepEqual(oldVsr.Spec, curVsr.Spec) || !reflect.DeepEqual(oldVsr.Labels, curVsr.Labels) {
219219
nl.Debugf(lbc.Logger, "VirtualServerRoute %v changed, syncing", curVsr.Name)
220220
lbc.AddSyncQueue(curVsr)
221221
}

0 commit comments

Comments
 (0)