Skip to content

Commit

Permalink
Allow routes from certain domains (ala defaulted domains) to be replaced
Browse files Browse the repository at this point in the history
with the subdomain/hostname-template that the router environment is
running under.
Fixes issue openshift#16797
  • Loading branch information
ramr committed Apr 24, 2018
1 parent 22b3508 commit fdb3458
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 1 deletion.
11 changes: 10 additions & 1 deletion pkg/cmd/infra/router/router.go
Expand Up @@ -35,6 +35,8 @@ type RouterSelection struct {

HostnameTemplate string
OverrideHostname bool
OverrideDomains []string
RedactedDomains sets.String

LabelSelector string
FieldSelector string
Expand Down Expand Up @@ -71,6 +73,7 @@ func (o *RouterSelection) Bind(flag *pflag.FlagSet) {
flag.DurationVar(&o.ResyncInterval, "resync-interval", controllerfactory.DefaultResyncInterval, "The interval at which the route list should be fully refreshed")
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')")
flag.BoolVar(&o.OverrideHostname, "override-hostname", isTrue(cmdutil.Env("ROUTER_OVERRIDE_HOSTNAME", "")), "Override the spec.host value for a route with --hostname-template")
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")
flag.StringVar(&o.LabelSelector, "labels", cmdutil.Env("ROUTE_LABELS", ""), "A label selector to apply to the routes to watch")
flag.StringVar(&o.FieldSelector, "fields", cmdutil.Env("ROUTE_FIELDS", ""), "A field selector to apply to routes to watch")
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")
Expand All @@ -91,7 +94,7 @@ func (o *RouterSelection) RouteUpdate(route *routeapi.Route) {
if len(o.HostnameTemplate) == 0 {
return
}
if !o.OverrideHostname && len(route.Spec.Host) > 0 {
if !o.OverrideHostname && len(route.Spec.Host) > 0 && !hostInDomainList(route.Spec.Host, o.RedactedDomains) {
return
}
s, err := variable.ExpandStrict(o.HostnameTemplate, func(key string) (string, bool) {
Expand Down Expand Up @@ -166,6 +169,12 @@ func (o *RouterSelection) Complete() error {
if len(o.HostnameTemplate) == 0 && o.OverrideHostname {
return fmt.Errorf("--override-hostname requires that --hostname-template be specified")
}

o.RedactedDomains = sets.NewString(o.OverrideDomains...)
if len(o.RedactedDomains) > 0 && len(o.HostnameTemplate) == 0 {
return fmt.Errorf("--override-domains requires that --hostname-template be specified")
}

if len(o.LabelSelector) > 0 {
if _, err := labels.Parse(o.LabelSelector); err != nil {
return fmt.Errorf("label selector is not valid: %v", err)
Expand Down
59 changes: 59 additions & 0 deletions test/extended/router/scoped.go
Expand Up @@ -165,6 +165,65 @@ var _ = g.Describe("[Conformance][Area:Networking][Feature:Router]", func() {
o.Expect(status).To(o.Equal(kapi.ConditionTrue))
o.Expect(condition.LastTransitionTime).NotTo(o.BeNil())
})

g.It("should override the route host for overriden domains with a custom value", func() {
oc.SetOutputDir(exutil.TestContext.OutputDir)
ns := oc.KubeFramework().Namespace.Name
execPodName := exutil.CreateExecPodOrFail(oc.AdminKubeClient().CoreV1(), ns, "execpod")
defer func() { oc.AdminKubeClient().CoreV1().Pods(ns).Delete(execPodName, metav1.NewDeleteOptions(1)) }()

g.By(fmt.Sprintf("creating a scoped router with overriden domains from a config file %q", configPath))

var routerIP string
err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
pod, err := oc.KubeFramework().ClientSet.CoreV1().Pods(ns).Get("router-override-domains", metav1.GetOptions{})
if err != nil {
return false, err
}
if len(pod.Status.PodIP) == 0 {
return false, nil
}
routerIP = pod.Status.PodIP
return true, nil
})

o.Expect(err).NotTo(o.HaveOccurred())

// router expected to listen on port 80
routerURL := fmt.Sprintf("http://%s", routerIP)
pattern := "%s-%s.apps.veto.test"

g.By("waiting for the healthz endpoint to respond")
healthzURI := fmt.Sprintf("http://%s:1936/healthz", routerIP)
err = waitForRouterOKResponseExec(ns, execPodName, healthzURI, routerIP, changeTimeoutSeconds)
o.Expect(err).NotTo(o.HaveOccurred())

g.By("waiting for the valid route to respond")
err = waitForRouterOKResponseExec(ns, execPodName, routerURL+"/Letter", fmt.Sprintf(pattern, "route-override-domain-1", ns), changeTimeoutSeconds)
o.Expect(err).NotTo(o.HaveOccurred())

g.By("checking that the stored domain name does not match a route")
host := "y.a.null.ptr"
err = expectRouteStatusCodeExec(ns, execPodName, routerURL+"/Letter", host, http.StatusServiceUnavailable)
o.Expect(err).NotTo(o.HaveOccurred())

for _, host := range []string{"route-override-domain-1", "route-override-domain-2"} {
host = fmt.Sprintf(pattern, host, ns)
g.By(fmt.Sprintf("checking that %s matches a route", host))
err = expectRouteStatusCodeExec(ns, execPodName, routerURL+"/Letter", host, http.StatusOK)
o.Expect(err).NotTo(o.HaveOccurred())
}

g.By("checking that the router reported the correct ingress and override")
r, err := oc.RouteClient().Route().Routes(ns).Get("route-override-domain-2", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
ingress := ingressForName(r, "test-override-domains")
o.Expect(ingress).NotTo(o.BeNil())
o.Expect(ingress.Host).To(o.Equal(fmt.Sprintf(pattern, "route-override-domain-2", ns)))
status, condition := routeapi.IngressConditionStatus(ingress, routeapi.RouteAdmitted)
o.Expect(status).To(o.Equal(kapi.ConditionTrue))
o.Expect(condition.LastTransitionTime).NotTo(o.BeNil())
})
})
})

Expand Down
58 changes: 58 additions & 0 deletions test/extended/testdata/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 58 additions & 0 deletions test/extended/testdata/scoped-router.yaml
Expand Up @@ -62,6 +62,34 @@ objects:
protocol: TCP
serviceAccountName: default

# a router that overrides domains
- apiVersion: v1
kind: Pod
metadata:
name: router-override-domains
labels:
test: router-override-domains
spec:
terminationGracePeriodSeconds: 1
containers:
- name: router
image: ${IMAGE}
imagePullPolicy: IfNotPresent
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
args: ["--name=test-override-domains", "--namespace=$(POD_NAMESPACE)", "--loglevel=4", "--override-domains=null.ptr,void.str", "--hostname-template=${name}-${namespace}.apps.veto.test"]
hostNetwork: false
ports:
- containerPort: 80
- containerPort: 443
- containerPort: 1936
name: stats
protocol: TCP
serviceAccountName: default


# ensure the router can access routes and endpoints
- apiVersion: v1
Expand Down Expand Up @@ -104,6 +132,36 @@ objects:
ports:
- targetPort: http

# routes that contain overriden domains
- apiVersion: v1
kind: Route
metadata:
name: route-override-domain-1
labels:
test: router
select: override-domains
spec:
host: y.a.null.ptr
path: /Letter
to:
name: endpoints
ports:
- targetPort: 8080
- apiVersion: v1
kind: Route
metadata:
name: route-override-domain-2
labels:
test: router
select: override-domains
spec:
host: main.void.str
path: /Letter
to:
name: endpoints
ports:
- targetPort: 8080

# a service to be routed to
- apiVersion: v1
kind: Service
Expand Down

0 comments on commit fdb3458

Please sign in to comment.