Skip to content

Commit 570ef0f

Browse files
committed
Allow routes from certain domains (ala defaulted domains) to be replaced
with the subdomain/hostname-template that the router environment is running under. Fixes issue #16797
1 parent fedbc3b commit 570ef0f

File tree

4 files changed

+190
-1
lines changed

4 files changed

+190
-1
lines changed

pkg/cmd/infra/router/router.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ type RouterSelection struct {
3535

3636
HostnameTemplate string
3737
OverrideHostname bool
38+
OverrideDomains []string
39+
RedactedDomains sets.String
3840

3941
LabelSelector string
4042
FieldSelector string
@@ -71,6 +73,7 @@ func (o *RouterSelection) Bind(flag *pflag.FlagSet) {
7173
flag.DurationVar(&o.ResyncInterval, "resync-interval", controllerfactory.DefaultResyncInterval, "The interval at which the route list should be fully refreshed")
7274
flag.StringVar(&o.HostnameTemplate, "hostname-template", cmdutil.Env("ROUTER_SUBDOMAIN", ""), "If specified, a template that should be used to generate the hostname for a route without spec.host (e.g. '${name}-${namespace}.myapps.mycompany.com')")
7375
flag.BoolVar(&o.OverrideHostname, "override-hostname", isTrue(cmdutil.Env("ROUTER_OVERRIDE_HOSTNAME", "")), "Override the spec.host value for a route with --hostname-template")
76+
flag.StringSliceVar(&o.OverrideDomains, "override-domains", envVarAsStrings("ROUTER_OVERRIDE_DOMAINS", "", ","), "List of comma separated domains to override if present in any routes. This overrides the spec.host value in any matching routes with --hostname-template")
7477
flag.StringVar(&o.LabelSelector, "labels", cmdutil.Env("ROUTE_LABELS", ""), "A label selector to apply to the routes to watch")
7578
flag.StringVar(&o.FieldSelector, "fields", cmdutil.Env("ROUTE_FIELDS", ""), "A field selector to apply to routes to watch")
7679
flag.StringVar(&o.ProjectLabelSelector, "project-labels", cmdutil.Env("PROJECT_LABELS", ""), "A label selector to apply to projects to watch; if '*' watches all projects the client can access")
@@ -92,7 +95,7 @@ func (o *RouterSelection) RouteSelectionFunc() controller.RouteHostFunc {
9295
return controller.HostForRoute
9396
}
9497
return func(route *routeapi.Route) string {
95-
if !o.OverrideHostname && len(route.Spec.Host) > 0 {
98+
if !o.OverrideHostname && len(route.Spec.Host) > 0 && !hostInDomainList(route.Spec.Host, o.RedactedDomains) {
9699
return route.Spec.Host
97100
}
98101
s, err := variable.ExpandStrict(o.HostnameTemplate, func(key string) (string, bool) {
@@ -165,6 +168,12 @@ func (o *RouterSelection) Complete() error {
165168
if len(o.HostnameTemplate) == 0 && o.OverrideHostname {
166169
return fmt.Errorf("--override-hostname requires that --hostname-template be specified")
167170
}
171+
172+
o.RedactedDomains = sets.NewString(o.OverrideDomains...)
173+
if len(o.RedactedDomains) > 0 && len(o.HostnameTemplate) == 0 {
174+
return fmt.Errorf("--override-domains requires that --hostname-template be specified")
175+
}
176+
168177
if len(o.LabelSelector) > 0 {
169178
if _, err := labels.Parse(o.LabelSelector); err != nil {
170179
return fmt.Errorf("label selector is not valid: %v", err)

test/extended/router/scoped.go

+64
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,70 @@ var _ = g.Describe("[Conformance][Area:Networking][Feature:Router]", func() {
151151
o.Expect(status).To(o.Equal(kapi.ConditionTrue))
152152
o.Expect(condition.LastTransitionTime).NotTo(o.BeNil())
153153
})
154+
155+
g.It("should override the route host for overriden domains with a custom value", func() {
156+
defer func() {
157+
if g.CurrentGinkgoTestDescription().Failed {
158+
dumpScopedRouterLogs(oc, g.CurrentGinkgoTestDescription().FullTestText)
159+
}
160+
}()
161+
oc.SetOutputDir(exutil.TestContext.OutputDir)
162+
ns := oc.KubeFramework().Namespace.Name
163+
execPodName := exutil.CreateExecPodOrFail(oc.AdminKubeClient().CoreV1(), ns, "execpod")
164+
defer func() { oc.AdminKubeClient().CoreV1().Pods(ns).Delete(execPodName, metav1.NewDeleteOptions(1)) }()
165+
166+
g.By(fmt.Sprintf("creating a scoped router with overriden domains from a config file %q", configPath))
167+
168+
var routerIP string
169+
err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
170+
pod, err := oc.KubeFramework().ClientSet.CoreV1().Pods(ns).Get("router-override-domains", metav1.GetOptions{})
171+
if err != nil {
172+
return false, err
173+
}
174+
if len(pod.Status.PodIP) == 0 {
175+
return false, nil
176+
}
177+
routerIP = pod.Status.PodIP
178+
return true, nil
179+
})
180+
181+
o.Expect(err).NotTo(o.HaveOccurred())
182+
183+
// router expected to listen on port 80
184+
routerURL := fmt.Sprintf("http://%s", routerIP)
185+
pattern := "%s-%s.apps.veto.test"
186+
187+
g.By("waiting for the healthz endpoint to respond")
188+
healthzURI := fmt.Sprintf("http://%s:1936/healthz", routerIP)
189+
err = waitForRouterOKResponseExec(ns, execPodName, healthzURI, routerIP, changeTimeoutSeconds)
190+
o.Expect(err).NotTo(o.HaveOccurred())
191+
192+
g.By("waiting for the valid route to respond")
193+
err = waitForRouterOKResponseExec(ns, execPodName, routerURL+"/Letter", fmt.Sprintf(pattern, "route-override-domain-1", ns), changeTimeoutSeconds)
194+
o.Expect(err).NotTo(o.HaveOccurred())
195+
196+
g.By("checking that the stored domain name does not match a route")
197+
host := "y.a.null.ptr"
198+
err = expectRouteStatusCodeExec(ns, execPodName, routerURL+"/Letter", host, http.StatusServiceUnavailable)
199+
o.Expect(err).NotTo(o.HaveOccurred())
200+
201+
for _, host := range []string{"route-override-domain-1", "route-override-domain-2"} {
202+
host = fmt.Sprintf(pattern, host, ns)
203+
g.By(fmt.Sprintf("checking that %s matches a route", host))
204+
err = expectRouteStatusCodeExec(ns, execPodName, routerURL+"/Letter", host, http.StatusOK)
205+
o.Expect(err).NotTo(o.HaveOccurred())
206+
}
207+
208+
g.By("checking that the router reported the correct ingress and override")
209+
r, err := oc.RouteClient().Route().Routes(ns).Get("route-override-domain-2", metav1.GetOptions{})
210+
o.Expect(err).NotTo(o.HaveOccurred())
211+
ingress := ingressForName(r, "test-override-domains")
212+
o.Expect(ingress).NotTo(o.BeNil())
213+
o.Expect(ingress.Host).To(o.Equal(fmt.Sprintf(pattern, "route-override-domain-2", ns)))
214+
status, condition := routeapi.IngressConditionStatus(ingress, routeapi.RouteAdmitted)
215+
o.Expect(status).To(o.Equal(kapi.ConditionTrue))
216+
o.Expect(condition.LastTransitionTime).NotTo(o.BeNil())
217+
})
154218
})
155219
})
156220

test/extended/testdata/bindata.go

+58
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/extended/testdata/scoped-router.yaml

+58
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,34 @@ objects:
6262
protocol: TCP
6363
serviceAccountName: default
6464

65+
# a router that overrides domains
66+
- apiVersion: v1
67+
kind: Pod
68+
metadata:
69+
name: router-override-domains
70+
labels:
71+
test: router-override-domains
72+
spec:
73+
terminationGracePeriodSeconds: 1
74+
containers:
75+
- name: router
76+
image: ${IMAGE}
77+
imagePullPolicy: IfNotPresent
78+
env:
79+
- name: POD_NAMESPACE
80+
valueFrom:
81+
fieldRef:
82+
fieldPath: metadata.namespace
83+
args: ["--name=test-override-domains", "--namespace=$(POD_NAMESPACE)", "--loglevel=4", "--override-domains=null.ptr,void.str", "--hostname-template=${name}-${namespace}.apps.veto.test"]
84+
hostNetwork: false
85+
ports:
86+
- containerPort: 80
87+
- containerPort: 443
88+
- containerPort: 1936
89+
name: stats
90+
protocol: TCP
91+
serviceAccountName: default
92+
6593

6694
# ensure the router can access routes and endpoints
6795
- apiVersion: v1
@@ -104,6 +132,36 @@ objects:
104132
ports:
105133
- targetPort: http
106134

135+
# routes that contain overriden domains
136+
- apiVersion: v1
137+
kind: Route
138+
metadata:
139+
name: route-override-domain-1
140+
labels:
141+
test: router
142+
select: override-domains
143+
spec:
144+
host: y.a.null.ptr
145+
path: /Letter
146+
to:
147+
name: endpoints
148+
ports:
149+
- targetPort: 8080
150+
- apiVersion: v1
151+
kind: Route
152+
metadata:
153+
name: route-override-domain-2
154+
labels:
155+
test: router
156+
select: override-domains
157+
spec:
158+
host: main.void.str
159+
path: /Letter
160+
to:
161+
name: endpoints
162+
ports:
163+
- targetPort: 8080
164+
107165
# a service to be routed to
108166
- apiVersion: v1
109167
kind: Service

0 commit comments

Comments
 (0)