Commit b0694ca8 authored by Geoff Simmons's avatar Geoff Simmons

Generated VCL symbol names never longer than 50 chars.

Workaround for Varnish issue #2880:
https://github.com/varnishcache/varnish-cache/issues/2880

Refactor the test sources a bit while we're here.
parent f55338b7
...@@ -3,11 +3,11 @@ import re2; ...@@ -3,11 +3,11 @@ import re2;
sub vcl_init { sub vcl_init {
{{- range $auth := .Auths}} {{- range $auth := .Auths}}
new {{vclMangle .Realm}}_auth = re2.set(anchor=both); new {{credsMatcher .Realm}} = re2.set(anchor=both);
{{- range $cred := .Credentials}} {{- range $cred := .Credentials}}
{{vclMangle $auth.Realm}}_auth.add("\s*Basic\s+\Q{{$cred}}\E\s*"); {{credsMatcher $auth.Realm}}.add("\s*Basic\s+\Q{{$cred}}\E\s*");
{{- end}} {{- end}}
{{vclMangle .Realm}}_auth.compile(); {{credsMatcher .Realm}}.compile();
{{end -}} {{end -}}
} }
...@@ -21,9 +21,9 @@ sub vcl_recv { ...@@ -21,9 +21,9 @@ sub vcl_recv {
req.url ~ "{{.Condition.URLRegex}}" && req.url ~ "{{.Condition.URLRegex}}" &&
{{- end}} {{- end}}
{{- if eq .Status 401}} {{- if eq .Status 401}}
!{{vclMangle .Realm}}_auth.match(req.http.Authorization) !{{credsMatcher .Realm}}.match(req.http.Authorization)
{{- else}} {{- else}}
!{{vclMangle .Realm}}_auth.match(req.http.Proxy-Authorization) !{{credsMatcher .Realm}}.match(req.http.Proxy-Authorization)
{{- end}} {{- end}}
) { ) {
{{- if .UTF8 }} {{- if .UTF8 }}
......
/*
* Copyright (c) 2018 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 (
"reflect"
"testing"
)
var cafeSpec2 = Spec{
DefaultService: Service{},
Rules: []Rule{{
Host: "cafe.example.com",
PathMap: map[string]Service{
"/tea": teaSvc,
"/coffee": coffeeSvc3,
},
}},
AllServices: map[string]Service{
"tea-svc": teaSvc,
"coffee-svc": coffeeSvc3,
},
}
func TestDeepHash(t *testing.T) {
if cafeSpec.DeepHash() == cafeSpec2.DeepHash() {
t.Errorf("DeepHash(): Distinct specs have equal hashes")
if testing.Verbose() {
t.Logf("spec1: %+v", cafeSpec)
t.Logf("spec2: %+v", cafeSpec2)
t.Logf("hash: %0x", cafeSpec.DeepHash())
}
}
}
var teaSvcShuf = Service{
Name: "tea-svc",
Addresses: []Address{
{
IP: "192.0.2.3",
Port: 80,
},
{
IP: "192.0.2.1",
Port: 80,
},
{
IP: "192.0.2.2",
Port: 80,
},
},
}
var coffeeSvcShuf = Service{
Name: "coffee-svc",
Addresses: []Address{
{
IP: "192.0.2.5",
Port: 80,
},
{
IP: "192.0.2.4",
Port: 80,
},
},
}
var cafeSpecShuf = Spec{
DefaultService: Service{},
Rules: []Rule{{
Host: "cafe.example.com",
PathMap: map[string]Service{
"/coffee": coffeeSvcShuf,
"/tea": teaSvcShuf,
},
}},
AllServices: map[string]Service{
"coffee-svc": coffeeSvcShuf,
"tea-svc": teaSvcShuf,
},
}
func TestCanoncial(t *testing.T) {
canonCafe := cafeSpec.Canonical()
canonShuf := cafeSpecShuf.Canonical()
if !reflect.DeepEqual(canonCafe, canonShuf) {
t.Error("Canonical(): Equivalent VCL specs not deeply equal")
if testing.Verbose() {
t.Log("Canonical cafe:", canonCafe)
t.Log("Canonical shuffled cafe:", canonShuf)
}
}
if canonCafe.DeepHash() != canonShuf.DeepHash() {
t.Error("Canonical(): Unequal hashes for equivalent specs")
if testing.Verbose() {
t.Logf("spec1 canonical: %+v", canonCafe)
t.Logf("spec1 hash: %0x", canonCafe.DeepHash())
t.Logf("spec2 canonical: %+v", canonShuf)
t.Logf("spec2 hash: %0x", canonShuf.DeepHash())
}
}
}
var names = []string{
"vk8s_cafe_example_com_url",
"vk8s_very_long_name_that_breaks_the_symbol_length_upper_bound",
}
func TestBound(t *testing.T) {
for _, n := range names {
if len(bound(n, maxSymLen)) > maxSymLen {
t.Errorf("bound(\"%s\", %d) not shortened as "+
"expected: len(\"%s\")=%d", n, maxSymLen,
bound(n, maxSymLen), len(bound(n, maxSymLen)))
}
if len(n) <= maxSymLen && n != bound(n, maxSymLen) {
t.Errorf("bound(\"%s\", %d) exp=\"%s\" got=\"%s\"",
n, maxSymLen, n, bound(n, maxSymLen))
}
}
}
...@@ -31,6 +31,8 @@ package vcl ...@@ -31,6 +31,8 @@ package vcl
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"hash/fnv"
"math/big"
"path" "path"
"regexp" "regexp"
"strings" "strings"
...@@ -55,7 +57,13 @@ var fMap = template.FuncMap{ ...@@ -55,7 +57,13 @@ var fMap = template.FuncMap{
return urlMatcher(rule) return urlMatcher(rule)
}, },
"aclName": func(name string) string { "aclName": func(name string) string {
return mangle(name) + "_acl" return mangle(name + "_acl")
},
"probeName": func(name string) string {
return mangle(name + "_probe")
},
"credsMatcher": func(realm string) string {
return mangle(realm + "_auth")
}, },
} }
...@@ -64,6 +72,11 @@ const ( ...@@ -64,6 +72,11 @@ const (
shardTmplSrc = "self-shard.tmpl" shardTmplSrc = "self-shard.tmpl"
authTmplSrc = "auth.tmpl" authTmplSrc = "auth.tmpl"
aclTmplSrc = "acl.tmpl" aclTmplSrc = "acl.tmpl"
// maxSymLen is a workaround for Varnish issue #2880
// https://github.com/varnishcache/varnish-cache/issues/2880
// Will be unnecssary as of the March 2019 release
maxSymLen = 50
) )
var ( var (
...@@ -141,6 +154,19 @@ func (spec Spec) GetSrc() (string, error) { ...@@ -141,6 +154,19 @@ func (spec Spec) GetSrc() (string, error) {
return buf.String(), nil return buf.String(), nil
} }
func bound(s string, l int) string {
if len(s) <= l {
return s
}
b := []byte(s)
h := fnv.New32a()
h.Write(b)
i := big.NewInt(int64(h.Sum32()))
b[l-7] = byte('_')
copy(b[l-6:l], []byte(i.Text(62)))
return string(b[0:l])
}
func mangle(s string) string { func mangle(s string) string {
if s == "" { if s == "" {
return s return s
...@@ -148,7 +174,7 @@ func mangle(s string) string { ...@@ -148,7 +174,7 @@ func mangle(s string) string {
prefixed := "vk8s_" + s prefixed := "vk8s_" + s
bytes := []byte(prefixed) bytes := []byte(prefixed)
mangled := vclIllegal.ReplaceAllFunc(bytes, replIllegal) mangled := vclIllegal.ReplaceAllFunc(bytes, replIllegal)
return string(mangled) return bound(string(mangled), maxSymLen)
} }
func backendName(svc Service, addr string) string { func backendName(svc Service, addr string) string {
......
...@@ -13,7 +13,7 @@ backend vk8s_notfound { ...@@ -13,7 +13,7 @@ backend vk8s_notfound {
{{- range $name, $svc := .AllServices}} {{- range $name, $svc := .AllServices}}
{{- if $svc.Probe}} {{- if $svc.Probe}}
{{with $svc.Probe}} {{with $svc.Probe}}
probe {{vclMangle $name}}_probe { probe {{probeName $name}} {
{{- if ne .URL ""}} {{- if ne .URL ""}}
.url = "{{.URL}}"; .url = "{{.URL}}";
{{- else if .Request}} {{- else if .Request}}
...@@ -71,7 +71,7 @@ backend {{backendName $svc $addr.IP}} { ...@@ -71,7 +71,7 @@ backend {{backendName $svc $addr.IP}} {
.max_connections = {{.MaxConnections}}; .max_connections = {{.MaxConnections}};
{{- end}} {{- end}}
{{- if .Probe}} {{- if .Probe}}
.probe = {{vclMangle $name}}_probe; .probe = {{probeName $name}};
{{- end}} {{- end}}
{{- end}} {{- end}}
} }
......
...@@ -34,7 +34,6 @@ import ( ...@@ -34,7 +34,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"testing" "testing"
"text/template" "text/template"
) )
...@@ -146,100 +145,6 @@ var coffeeSvc3 = Service{ ...@@ -146,100 +145,6 @@ var coffeeSvc3 = Service{
}, },
} }
var cafeSpec2 = Spec{
DefaultService: Service{},
Rules: []Rule{{
Host: "cafe.example.com",
PathMap: map[string]Service{
"/tea": teaSvc,
"/coffee": coffeeSvc3,
},
}},
AllServices: map[string]Service{
"tea-svc": teaSvc,
"coffee-svc": coffeeSvc3,
},
}
func TestDeepHash(t *testing.T) {
if cafeSpec.DeepHash() == cafeSpec2.DeepHash() {
t.Errorf("DeepHash(): Distinct specs have equal hashes")
if testing.Verbose() {
t.Logf("spec1: %+v", cafeSpec)
t.Logf("spec2: %+v", cafeSpec2)
t.Logf("hash: %0x", cafeSpec.DeepHash())
}
}
}
var teaSvcShuf = Service{
Name: "tea-svc",
Addresses: []Address{
{
IP: "192.0.2.3",
Port: 80,
},
{
IP: "192.0.2.1",
Port: 80,
},
{
IP: "192.0.2.2",
Port: 80,
},
},
}
var coffeeSvcShuf = Service{
Name: "coffee-svc",
Addresses: []Address{
{
IP: "192.0.2.5",
Port: 80,
},
{
IP: "192.0.2.4",
Port: 80,
},
},
}
var cafeSpecShuf = Spec{
DefaultService: Service{},
Rules: []Rule{{
Host: "cafe.example.com",
PathMap: map[string]Service{
"/coffee": coffeeSvcShuf,
"/tea": teaSvcShuf,
},
}},
AllServices: map[string]Service{
"coffee-svc": coffeeSvcShuf,
"tea-svc": teaSvcShuf,
},
}
func TestCanoncial(t *testing.T) {
canonCafe := cafeSpec.Canonical()
canonShuf := cafeSpecShuf.Canonical()
if !reflect.DeepEqual(canonCafe, canonShuf) {
t.Error("Canonical(): Equivalent VCL specs not deeply equal")
if testing.Verbose() {
t.Log("Canonical cafe:", canonCafe)
t.Log("Canonical shuffled cafe:", canonShuf)
}
}
if canonCafe.DeepHash() != canonShuf.DeepHash() {
t.Error("Canonical(): Unequal hashes for equivalent specs")
if testing.Verbose() {
t.Logf("spec1 canonical: %+v", canonCafe)
t.Logf("spec1 hash: %0x", canonCafe.DeepHash())
t.Logf("spec2 canonical: %+v", canonShuf)
t.Logf("spec2 hash: %0x", canonShuf.DeepHash())
}
}
}
var varnishCluster = ShardCluster{ var varnishCluster = ShardCluster{
Nodes: []Service{ Nodes: []Service{
Service{ Service{
......
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