Skip to content

Commit fdb3458

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 22b3508 commit fdb3458

File tree

4 files changed

+185
-1
lines changed

4 files changed

+185
-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")
@@ -91,7 +94,7 @@ func (o *RouterSelection) RouteUpdate(route *routeapi.Route) {
9194
if len(o.HostnameTemplate) == 0 {
9295
return
9396
}
94-
if !o.OverrideHostname && len(route.Spec.Host) > 0 {
97+
if !o.OverrideHostname && len(route.Spec.Host) > 0 && !hostInDomainList(route.Spec.Host, o.RedactedDomains) {
9598
return
9699
}
97100
s, err := variable.ExpandStrict(o.HostnameTemplate, func(key string) (string, bool) {
@@ -166,6 +169,12 @@ func (o *RouterSelection) Complete() error {
166169
if len(o.HostnameTemplate) == 0 && o.OverrideHostname {
167170
return fmt.Errorf("--override-hostname requires that --hostname-template be specified")
168171
}
172+
173+
o.RedactedDomains = sets.NewString(o.OverrideDomains...)
174+
if len(o.RedactedDomains) > 0 && len(o.HostnameTemplate) == 0 {
175+
return fmt.Errorf("--override-domains requires that --hostname-template be specified")
176+
}
177+
169178
if len(o.LabelSelector) > 0 {
170179
if _, err := labels.Parse(o.LabelSelector); err != nil {
171180
return fmt.Errorf("label selector is not valid: %v", err)

test/extended/router/scoped.go

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

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)