Skip to content

Commit 54811f8

Browse files
committed
WIP router: add basic support for config via ingress
1 parent ba5e5e9 commit 54811f8

File tree

11 files changed

+1524
-28
lines changed

11 files changed

+1524
-28
lines changed

pkg/api/helpers.go

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package api
33
import (
44
"fmt"
55

6+
kapi "k8s.io/kubernetes/pkg/api"
67
"k8s.io/kubernetes/pkg/api/validation"
78
"k8s.io/kubernetes/pkg/api/validation/path"
89
)
@@ -33,3 +34,10 @@ func GetFieldLabelConversionFunc(supportedLabels map[string]string, overrideLabe
3334
return "", "", fmt.Errorf("field label not supported: %s", label)
3435
}
3536
}
37+
38+
// GetResourceKey returns a string of the form [namespace]/[name] for
39+
// the given resource. This is a common way of ensuring a key for a
40+
// resource that is unique across the cluster.
41+
func GetResourceKey(obj kapi.ObjectMeta) string {
42+
return fmt.Sprintf("%s/%s", obj.Namespace, obj.Name)
43+
}

pkg/cmd/infra/router/router.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,22 @@ func (o *RouterSelection) RouteSelectionFunc() controller.RouteHostFunc {
7979
if !o.OverrideHostname && len(route.Spec.Host) > 0 {
8080
return route.Spec.Host
8181
}
82+
nameForHost := route.Name
83+
if controller.IsGeneratedRoute(route) {
84+
// Use the resource name embedded in the route name to
85+
// construct the host. The name of routes generated from
86+
// ingress rules will be 'ingress/[name]/[host]/[path]'.
87+
//
88+
// When a route and ingress in the same namespace share a
89+
// name, the route and the ingress' rules should receive
90+
// the same generated host.
91+
nameParts := strings.Split(nameForHost, "/")
92+
nameForHost = nameParts[1]
93+
}
8294
s, err := variable.ExpandStrict(o.HostnameTemplate, func(key string) (string, bool) {
8395
switch key {
8496
case "name":
85-
return route.Name, true
97+
return nameForHost, true
8698
case "namespace":
8799
return route.Namespace, true
88100
default:

pkg/route/api/v1/defaults.go

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package v1
22

33
import "k8s.io/kubernetes/pkg/runtime"
44

5+
// If adding or changing route defaults, updates may be required to
6+
// pkg/router/controller/controller.go to ensure the routes generated from
7+
// ingress resources will match routes created via the api.
8+
59
func SetDefaults_RouteSpec(obj *RouteSpec) {
610
if len(obj.WildcardPolicy) == 0 {
711
obj.WildcardPolicy = WildcardPolicyNone

pkg/router/controller/controller.go

+101-14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/golang/glog"
99
kapi "k8s.io/kubernetes/pkg/api"
10+
"k8s.io/kubernetes/pkg/apis/extensions"
1011
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
1112
"k8s.io/kubernetes/pkg/util/sets"
1213
utilwait "k8s.io/kubernetes/pkg/util/wait"
@@ -30,25 +31,37 @@ type RouterController struct {
3031
NextRoute func() (watch.EventType, *routeapi.Route, error)
3132
NextNode func() (watch.EventType, *kapi.Node, error)
3233
NextEndpoints func() (watch.EventType, *kapi.Endpoints, error)
34+
NextIngress func() (watch.EventType, *extensions.Ingress, error)
35+
NextSecret func() (watch.EventType, *kapi.Secret, error)
3336

3437
RoutesListConsumed func() bool
3538
EndpointsListConsumed func() bool
39+
IngressesListConsumed func() bool
40+
SecretsListConsumed func() bool
3641
routesListConsumed bool
3742
endpointsListConsumed bool
43+
ingressesListConsumed bool
44+
secretsListConsumed bool
3845
filteredByNamespace bool
3946
syncing bool
4047

4148
RoutesListSuccessfulAtLeastOnce func() bool
4249
EndpointsListSuccessfulAtLeastOnce func() bool
50+
IngressesListSuccessfulAtLeastOnce func() bool
51+
SecretsListSuccessfulAtLeastOnce func() bool
4352
RoutesListCount func() int
4453
EndpointsListCount func() int
54+
IngressesListCount func() int
55+
SecretsListCount func() int
4556

4657
WatchNodes bool
4758

4859
Namespaces NamespaceLister
4960
NamespaceSyncInterval time.Duration
5061
NamespaceWaitInterval time.Duration
5162
NamespaceRetries int
63+
64+
IngressTranslator *IngressTranslator
5265
}
5366

5467
// Run begins watching and syncing.
@@ -63,6 +76,8 @@ func (c *RouterController) Run() {
6376
if c.WatchNodes {
6477
go utilwait.Forever(c.HandleNode, 0)
6578
}
79+
go utilwait.Forever(c.HandleIngress, 0)
80+
go utilwait.Forever(c.HandleSecret, 0)
6681
go c.watchForFirstSync()
6782
}
6883

@@ -74,22 +89,29 @@ func (c *RouterController) handleFirstSync() bool {
7489

7590
synced := c.RoutesListSuccessfulAtLeastOnce() &&
7691
c.EndpointsListSuccessfulAtLeastOnce() &&
77-
(c.Namespaces == nil || c.filteredByNamespace)
92+
(c.Namespaces == nil || c.filteredByNamespace) &&
93+
c.IngressesListSuccessfulAtLeastOnce() &&
94+
c.SecretsListSuccessfulAtLeastOnce()
7895
if !synced {
7996
return false
8097
}
8198

82-
// If either of the event queues were empty after the initial
83-
// List, the tracking listConsumed variable's default value of
84-
// 'false' may prevent the router from committing the readiness
85-
// status. Set the value to 'true' to ensure that state will be
86-
// committed if necessary.
99+
// If any of the event queues were empty after the initial List,
100+
// the tracking listConsumed variable's default value of 'false'
101+
// may prevent the router from committing. Set the value to
102+
// 'true' to ensure that state can be committed if necessary.
87103
if c.RoutesListCount() == 0 {
88104
c.routesListConsumed = true
89105
}
90106
if c.EndpointsListCount() == 0 {
91107
c.endpointsListConsumed = true
92108
}
109+
if c.IngressesListCount() == 0 {
110+
c.ingressesListConsumed = true
111+
}
112+
if c.SecretsListCount() == 0 {
113+
c.secretsListConsumed = true
114+
}
93115
c.commit()
94116

95117
return true
@@ -161,13 +183,7 @@ func (c *RouterController) HandleRoute() {
161183
c.lock.Lock()
162184
defer c.lock.Unlock()
163185

164-
glog.V(4).Infof("Processing Route: %s -> %s", route.Name, route.Spec.To.Name)
165-
glog.V(4).Infof(" Alias: %s", route.Spec.Host)
166-
glog.V(4).Infof(" Event: %s", eventType)
167-
168-
if err := c.Plugin.HandleRoute(eventType, route); err != nil {
169-
utilruntime.HandleError(err)
170-
}
186+
c.processRoute(eventType, route)
171187

172188
// Change the local sync state within the lock to ensure that all
173189
// event handlers have the same view of sync state.
@@ -196,10 +212,60 @@ func (c *RouterController) HandleEndpoints() {
196212
c.commit()
197213
}
198214

215+
// HandleIngress handles a single Ingress event and synchronizes the router backend.
216+
func (c *RouterController) HandleIngress() {
217+
eventType, ingress, err := c.NextIngress()
218+
if err != nil {
219+
utilruntime.HandleError(fmt.Errorf("unable to read ingress: %v", err))
220+
return
221+
}
222+
223+
// The ingress translator synchronizes access to its cache with a
224+
// lock, so calls to it are made outside of the controller lock to
225+
// avoid unintended interaction.
226+
events := c.IngressTranslator.TranslateIngressEvent(eventType, ingress)
227+
228+
c.lock.Lock()
229+
defer c.lock.Unlock()
230+
231+
c.processIngressEvents(events)
232+
233+
// Change the local sync state within the lock to ensure that all
234+
// event handlers have the same view of sync state.
235+
c.ingressesListConsumed = c.IngressesListConsumed()
236+
c.commit()
237+
}
238+
239+
// HandleSecret handles a single Secret event and synchronizes the router backend.
240+
func (c *RouterController) HandleSecret() {
241+
eventType, secret, err := c.NextSecret()
242+
if err != nil {
243+
utilruntime.HandleError(fmt.Errorf("unable to read secret: %v", err))
244+
return
245+
246+
}
247+
248+
// The ingress translator synchronizes access to its cache with a
249+
// lock, so calls to it are made outside of the controller lock to
250+
// avoid unintended interaction.
251+
events := c.IngressTranslator.TranslateSecretEvent(eventType, secret)
252+
253+
c.lock.Lock()
254+
defer c.lock.Unlock()
255+
256+
c.processIngressEvents(events)
257+
258+
// Change the local sync state within the lock to ensure that all
259+
// event handlers have the same view of sync state.
260+
c.secretsListConsumed = c.SecretsListConsumed()
261+
c.commit()
262+
}
263+
199264
// commit notifies the plugin that it is safe to commit state.
200265
func (c *RouterController) commit() {
201266
syncing := !(c.endpointsListConsumed && c.routesListConsumed &&
202-
(c.Namespaces == nil || c.filteredByNamespace))
267+
(c.Namespaces == nil || c.filteredByNamespace) &&
268+
c.ingressesListConsumed && c.secretsListConsumed)
203269
c.logSyncState(syncing)
204270
if syncing {
205271
return
@@ -219,3 +285,24 @@ func (c *RouterController) logSyncState(syncing bool) {
219285
}
220286
}
221287
}
288+
289+
// processRoute logs and propagates a route event to the plugin
290+
func (c *RouterController) processRoute(eventType watch.EventType, route *routeapi.Route) {
291+
glog.V(4).Infof("Processing Route: %s/%s -> %s", route.Namespace, route.Name, route.Spec.To.Name)
292+
glog.V(4).Infof(" Alias: %s", route.Spec.Host)
293+
glog.V(4).Infof(" Event: %s", eventType)
294+
295+
if err := c.Plugin.HandleRoute(eventType, route); err != nil {
296+
utilruntime.HandleError(err)
297+
}
298+
}
299+
300+
// processIngressEvents logs and propagates the route events resulting from an ingress event
301+
func (c *RouterController) processIngressEvents(events []ingressRouteEvents) {
302+
for _, ingressEvent := range events {
303+
glog.V(4).Infof("Processing Ingress %s", ingressEvent.ingressKey)
304+
for _, routeEvent := range ingressEvent.routeEvents {
305+
c.processRoute(routeEvent.eventType, routeEvent.route)
306+
}
307+
}
308+
}

0 commit comments

Comments
 (0)