Commit 98ca0ffa authored by Geoff Simmons's avatar Geoff Simmons

Bugfix: an Ingress rule without a host value is not an error.

parent 0a501af1
......@@ -463,13 +463,6 @@ func (worker *NamespaceWorker) ings2VCLSpec(
}
}
for _, rule := range ing.Spec.Rules {
// XXX this should not be an error
if rule.Host == "" {
return vclSpec, bcfgs,
update.MakeFatal(
"Ingress rule contains " +
"empty Host")
}
vclRule := vcl.Rule{Host: rule.Host}
vclRule.PathMap = make(map[string]vcl.Service)
if rule.IngressRuleValue.HTTP == nil {
......
/*
* Copyright (c) 2020 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package vcl
import (
"bytes"
_ "io/ioutil"
_ "path/filepath"
"testing"
)
var cafeNoHostSpec = Spec{
Rules: []Rule{
{
Host: "tea.example.com",
PathMap: map[string]Service{
"/": teaSvc,
},
},
{
PathMap: map[string]Service{
"/tea": teaSvc,
"/coffee": coffeeSvc,
},
},
},
IntSvcs: map[string]Service{
"tea-svc": teaSvc,
"coffee-svc": coffeeSvc,
},
}
func TestIngressFanoutNoHost(t *testing.T) {
var buf bytes.Buffer
gold := "ingress_fanout_nohost.golden"
if err := ingressTmpl.Execute(&buf, cafeNoHostSpec); err != nil {
t.Fatal("Execute():", err)
}
ok, err := cmpGold(buf.Bytes(), gold)
if err != nil {
t.Fatalf("Reading %s: %v", gold, err)
}
if !ok {
t.Errorf("Generated VCL for IngressSpec does not match gold "+
"file: %s", gold)
if testing.Verbose() {
t.Logf("Generated: %s", buf.String())
}
}
}
var h2oSvc = Service{
Name: "water-svc",
Addresses: []Address{
{
IP: "192.0.2.128",
Port: 8000,
},
{
IP: "192.0.2.129",
Port: 8000,
},
{
IP: "192.0.2.130",
Port: 8000,
},
},
}
var cafeVhostNoHostSpec = Spec{
Rules: []Rule{
{
Host: "tea.example.com",
PathMap: map[string]Service{
"/": teaSvc,
},
},
{
Host: "coffee.example.com",
PathMap: map[string]Service{
"/": coffeeSvc,
},
},
{
PathMap: map[string]Service{
"/": h2oSvc,
},
},
},
IntSvcs: map[string]Service{
"tea-svc": teaSvc,
"coffee-svc": coffeeSvc,
"water-svc": h2oSvc,
},
}
func TestIngressVhostNoHost(t *testing.T) {
var buf bytes.Buffer
gold := "ingress_vhost_nohost.golden"
if err := ingressTmpl.Execute(&buf, cafeVhostNoHostSpec); err != nil {
t.Fatal("Execute():", err)
}
ok, err := cmpGold(buf.Bytes(), gold)
if err != nil {
t.Fatalf("Reading %s: %v", gold, err)
}
if !ok {
t.Errorf("Generated VCL for IngressSpec does not match gold "+
"file: %s", gold)
if testing.Verbose() {
t.Logf("Generated: %s", buf.String())
}
}
}
......@@ -153,14 +153,10 @@ sub vcl_init {
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
elsif (vk8s_hosts.which() == 1) {
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_cafe_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_cafe_example_com_url.backend(select=FIRST);
}
......
......@@ -63,14 +63,10 @@ sub vcl_init {
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
elsif (vk8s_hosts.which() == 1) {
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_cafe_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_cafe_example_com_url.backend(select=FIRST);
}
......
......@@ -93,24 +93,20 @@ sub vcl_init {
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
elsif (vk8s_hosts.which() == 1) {
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_cafe_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_cafe_example_com_url.backend(select=FIRST);
}
}
elsif (vk8s_hosts.which() == 2) {
elsif (vk8s_hosts.which(select=FIRST) == 2) {
if (vk8s_whiskey_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_whiskey_example_com_url.backend(select=FIRST);
}
}
elsif (vk8s_hosts.which() == 3) {
elsif (vk8s_hosts.which(select=FIRST) == 3) {
if (vk8s_vodka_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_vodka_example_com_url.backend(select=FIRST);
}
......
......@@ -88,19 +88,15 @@ sub vcl_init {
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
elsif (vk8s_hosts.which() == 1) {
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_tequila_example_edu_url.match(req.url)) {
set req.backend_hint = vk8s_tequila_example_edu_url.backend(select=FIRST);
}
}
elsif (vk8s_hosts.which() == 2) {
elsif (vk8s_hosts.which(select=FIRST) == 2) {
if (vk8s_metaxa_example_edu_url.match(req.url)) {
set req.backend_hint = vk8s_metaxa_example_edu_url.backend(select=FIRST);
}
......
vcl 4.1;
import std;
import directors;
import re2;
import dynamic;
backend vk8s_notfound {
# 192.0.2.0/24 reserved for docs & examples (RFC5737).
.host = "192.0.2.255";
.port = "80";
}
backend vk8s_coffee-svc_192_0_2_4 {
.host = "192.0.2.4";
.port = "80";
}
backend vk8s_coffee-svc_192_0_2_5 {
.host = "192.0.2.5";
.port = "80";
}
backend vk8s_tea-svc_192_0_2_1 {
.host = "192.0.2.1";
.port = "80";
}
backend vk8s_tea-svc_192_0_2_2 {
.host = "192.0.2.2";
.port = "80";
}
backend vk8s_tea-svc_192_0_2_3 {
.host = "192.0.2.3";
.port = "80";
}
sub vcl_init {
new vk8s_hosts = re2.set(anchor=both);
vk8s_hosts.add("\Qtea.example.com\E(:\d+)?");
vk8s_hosts.add("[^:]+(:\d+)?");
vk8s_hosts.compile();
new vk8s_coffee-svc_director = directors.round_robin();
vk8s_coffee-svc_director.add_backend(vk8s_coffee-svc_192_0_2_4
);
vk8s_coffee-svc_director.add_backend(vk8s_coffee-svc_192_0_2_5
);
new vk8s_tea-svc_director = directors.round_robin();
vk8s_tea-svc_director.add_backend(vk8s_tea-svc_192_0_2_1
);
vk8s_tea-svc_director.add_backend(vk8s_tea-svc_192_0_2_2
);
vk8s_tea-svc_director.add_backend(vk8s_tea-svc_192_0_2_3
);
new vk8s_tea_example_com_url = re2.set(posix_syntax=true, anchor=start);
vk8s_tea_example_com_url.add("/",
backend=vk8s_tea-svc_director.backend());
vk8s_tea_example_com_url.compile();
new vk8s_any_host = re2.set(posix_syntax=true, anchor=start);
vk8s_any_host.add("/coffee",
backend=vk8s_coffee-svc_director.backend());
vk8s_any_host.add("/tea",
backend=vk8s_tea-svc_director.backend());
vk8s_any_host.compile();
}
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (0 != 0) {
#
}
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_tea_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_tea_example_com_url.backend(select=FIRST);
}
}
elsif (vk8s_hosts.which(select=FIRST) == 2) {
if (vk8s_any_host.match(req.url)) {
set req.backend_hint = vk8s_any_host.backend(select=FIRST);
}
}
}
if (req.backend_hint == vk8s_notfound) {
return (synth(404));
}
}
sub vcl_miss {
call vk8s_set_backend;
}
sub vcl_pass {
call vk8s_set_backend;
}
sub vcl_pipe {
call vk8s_set_backend;
}
sub vcl_hit {
if (obj.ttl < 0s) {
# Set a backend for a background fetch.
call vk8s_set_backend;
}
}
......@@ -63,14 +63,10 @@ sub vcl_init {
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
elsif (vk8s_hosts.which() == 1) {
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_cafe_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_cafe_example_com_url.backend(select=FIRST);
}
......
vcl 4.1;
import std;
import directors;
import re2;
import dynamic;
backend vk8s_notfound {
# 192.0.2.0/24 reserved for docs & examples (RFC5737).
.host = "192.0.2.255";
.port = "80";
}
backend vk8s_coffee-svc_192_0_2_4 {
.host = "192.0.2.4";
.port = "80";
}
backend vk8s_coffee-svc_192_0_2_5 {
.host = "192.0.2.5";
.port = "80";
}
backend vk8s_tea-svc_192_0_2_1 {
.host = "192.0.2.1";
.port = "80";
}
backend vk8s_tea-svc_192_0_2_2 {
.host = "192.0.2.2";
.port = "80";
}
backend vk8s_tea-svc_192_0_2_3 {
.host = "192.0.2.3";
.port = "80";
}
backend vk8s_water-svc_192_0_2_128 {
.host = "192.0.2.128";
.port = "8000";
}
backend vk8s_water-svc_192_0_2_129 {
.host = "192.0.2.129";
.port = "8000";
}
backend vk8s_water-svc_192_0_2_130 {
.host = "192.0.2.130";
.port = "8000";
}
sub vcl_init {
new vk8s_hosts = re2.set(anchor=both);
vk8s_hosts.add("\Qtea.example.com\E(:\d+)?");
vk8s_hosts.add("\Qcoffee.example.com\E(:\d+)?");
vk8s_hosts.add("[^:]+(:\d+)?");
vk8s_hosts.compile();
new vk8s_coffee-svc_director = directors.round_robin();
vk8s_coffee-svc_director.add_backend(vk8s_coffee-svc_192_0_2_4
);
vk8s_coffee-svc_director.add_backend(vk8s_coffee-svc_192_0_2_5
);
new vk8s_tea-svc_director = directors.round_robin();
vk8s_tea-svc_director.add_backend(vk8s_tea-svc_192_0_2_1
);
vk8s_tea-svc_director.add_backend(vk8s_tea-svc_192_0_2_2
);
vk8s_tea-svc_director.add_backend(vk8s_tea-svc_192_0_2_3
);
new vk8s_water-svc_director = directors.round_robin();
vk8s_water-svc_director.add_backend(vk8s_water-svc_192_0_2_128
);
vk8s_water-svc_director.add_backend(vk8s_water-svc_192_0_2_129
);
vk8s_water-svc_director.add_backend(vk8s_water-svc_192_0_2_130
);
new vk8s_tea_example_com_url = re2.set(posix_syntax=true, anchor=start);
vk8s_tea_example_com_url.add("/",
backend=vk8s_tea-svc_director.backend());
vk8s_tea_example_com_url.compile();
new vk8s_coffee_example_com_url = re2.set(posix_syntax=true, anchor=start);
vk8s_coffee_example_com_url.add("/",
backend=vk8s_coffee-svc_director.backend());
vk8s_coffee_example_com_url.compile();
new vk8s_any_host = re2.set(posix_syntax=true, anchor=start);
vk8s_any_host.add("/",
backend=vk8s_water-svc_director.backend());
vk8s_any_host.compile();
}
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (0 != 0) {
#
}
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_tea_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_tea_example_com_url.backend(select=FIRST);
}
}
elsif (vk8s_hosts.which(select=FIRST) == 2) {
if (vk8s_coffee_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_coffee_example_com_url.backend(select=FIRST);
}
}
elsif (vk8s_hosts.which(select=FIRST) == 3) {
if (vk8s_any_host.match(req.url)) {
set req.backend_hint = vk8s_any_host.backend(select=FIRST);
}
}
}
if (req.backend_hint == vk8s_notfound) {
return (synth(404));
}
}
sub vcl_miss {
call vk8s_set_backend;
}
sub vcl_pass {
call vk8s_set_backend;
}
sub vcl_pipe {
call vk8s_set_backend;
}
sub vcl_hit {
if (obj.ttl < 0s) {
# Set a backend for a background fetch.
call vk8s_set_backend;
}
}
......@@ -63,14 +63,10 @@ sub vcl_init {
sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
elsif (vk8s_hosts.which() == 1) {
elsif (vk8s_hosts.which(select=FIRST) == 1) {
if (vk8s_cafe_example_com_url.match(req.url)) {
set req.backend_hint = vk8s_cafe_example_com_url.backend(select=FIRST);
}
......
......@@ -122,7 +122,7 @@ sub vcl_init {
{{- if .Rules}}
new vk8s_hosts = re2.set(anchor=both);
{{- range $rule := .Rules}}
vk8s_hosts.add("\Q{{$rule.Host}}\E(:\d+)?");
vk8s_hosts.add("{{hostRegex $rule.Host}}(:\d+)?");
{{- end}}
vk8s_hosts.compile();
{{end}}
......@@ -218,15 +218,11 @@ sub vk8s_set_backend {
set req.backend_hint = vk8s_notfound;
{{- if .Rules}}
if (vk8s_hosts.match(req.http.Host)) {
if (vk8s_hosts.nmatches() != 1) {
# Fail fast when the match was not unique.
return (fail);
}
if (0 != 0) {
#
}
{{- range $i, $rule := .Rules}}
elsif (vk8s_hosts.which() == {{plusOne $i}}) {
elsif (vk8s_hosts.which(select=FIRST) == {{plusOne $i}}) {
if ({{urlMatcher $rule}}.match(req.url)) {
set req.backend_hint = {{urlMatcher $rule}}.backend(select=FIRST);
}
......@@ -278,12 +274,23 @@ func backendName(svc Service, addr string) string {
}
func urlMatcher(rule Rule) string {
if rule.Host == "" {
return mangle("any_host")
}
return mangle(strings.Replace(rule.Host, ".", "_", -1) + "_url")
}
func hostRegex(host string) string {
if host == "" {
return "[^:]+"
}
return `\Q` + host + `\E`
}
var vclFuncs = template.FuncMap{
"plusOne": func(i int) int { return i + 1 },
"dirType": func(svc Service) string { return dirType(svc) },
"plusOne": func(i int) int { return i + 1 },
"dirType": func(svc Service) string { return dirType(svc) },
"hostRegex": func(host string) string { return hostRegex(host) },
"probeName": func(name string) string {
return mangle(name + "_probe")
},
......
......@@ -130,6 +130,11 @@ cd ${MYPATH}/../examples/svctypes/
make EXAMPLE=nodeport deploy verify undeploy
make EXAMPLE=lb deploy verify undeploy
echo Varieties of Ingress
cd ${MYPATH}/e2e/ingresses
make EXAMPLE=fanout-nohost deploy verify undeploy
make EXAMPLE=vhost-nohost deploy verify undeploy
echo Ignore deletion of TLS Secrets for non-viking Ingresses
cd ${MYPATH}/e2e/deleteTLSsecret
make deploy verify undeploy
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment