Commit 97e1daf1 authored by Geoff Simmons's avatar Geoff Simmons

Add the PrimaryOnly field for self-sharding to the VCL spec.

parent 120315d6
......@@ -37,6 +37,8 @@ spec:
max-secondary-ttl:
type: string
pattern: '^\d+(\.\d+)?(ms|[smhdwy])$'
primaryOnly:
type: boolean
probe:
type: object
properties:
......
......@@ -47,7 +47,15 @@ sub vcl_init {
}
sub vcl_recv {
if (remote.ip ~ vk8s_cluster_acl) {
{{ if .PrimaryOnly -}}
unset req.http.VK8S-Shard-Primary-Only;
if (remote.ip !~ vk8s_cluster_acl
&& "" + vk8s_cluster.backend(resolve=NOW) != server.identity) {
set req.http.VK8S-Shard-Primary-Only = "true";
set req.backend_hint = cluster.backend(resolve=NOW);
return (pass);
}
else {{ end }}if (remote.ip ~ vk8s_cluster_acl) {
if (req.http.Host == "vk8s_cluster") {
if (req.url == "/vk8s_cluster_health") {
return (synth(200));
......@@ -66,8 +74,19 @@ sub vcl_recv {
return (hash);
}
}
{{ if .PrimaryOnly }}
sub vcl_pass {
if (req.http.VK8S-Shard-Primary-Only) {
return (pass);
}
}
{{ end }}
sub vcl_backend_fetch {
{{- if .PrimaryOnly }}
if (bereq.http.VK8S-Shard-Primary-Only) {
return (fetch);
}
{{- end }}
if (bereq.retries == 0
&& !bereq.uncacheable
&& remote.ip !~ vk8s_cluster_acl
......@@ -79,6 +98,11 @@ sub vcl_backend_fetch {
}
sub vcl_backend_response {
{{- if .PrimaryOnly }}
if (bereq.http.VK8S-Shard-Primary-Only) {
return (deliver);
}
{{- end }}
if (bereq.backend == vk8s_cluster.backend(resolve=LAZY)) {
if (beresp.http.VK8S-Cluster-TTL) {
set beresp.ttl = std.duration(
......@@ -102,6 +126,11 @@ sub vcl_backend_error {
}
sub vcl_deliver {
{{- if .PrimaryOnly }}
if (bereq.http.VK8S-Shard-Primary-Only) {
return (deliver);
}
{{- end }}
unset resp.http.VK8S-Cluster-TTL;
if (remote.ip ~ vk8s_cluster_acl) {
if (! obj.uncacheable) {
......
......@@ -258,6 +258,7 @@ type ShardCluster struct {
Nodes []Service
Probe Probe
MaxSecondaryTTL string
PrimaryOnly bool
}
func (shard ShardCluster) hash(hash hash.Hash) {
......@@ -266,6 +267,9 @@ func (shard ShardCluster) hash(hash hash.Hash) {
}
shard.Probe.hash(hash)
hash.Write([]byte(shard.MaxSecondaryTTL))
if shard.PrimaryOnly {
hash.Write([]byte{1})
}
}
// AuthStatus is the response code to be sent for authentication
......
import std;
import directors;
probe vk8s_probe_varnish {
.request = "HEAD /vk8s_cluster_health HTTP/1.1"
"Host: vk8s_cluster"
"Connection: close";
.timeout = 2s;
.interval = 5s;
.initial = 2;
.window = 8;
.threshold = 3;
}
backend varnish-8445d4f7f-z2b9p {
.host = "172.17.0.12";
.port = "80";
.probe = vk8s_probe_varnish;
}
backend varnish-8445d4f7f-k22dn {
.host = "172.17.0.13";
.port = "80";
.probe = vk8s_probe_varnish;
}
backend varnish-8445d4f7f-ldljf {
.host = "172.17.0.14";
.port = "80";
.probe = vk8s_probe_varnish;
}
acl vk8s_cluster_acl {
"172.17.0.12";
"172.17.0.13";
"172.17.0.14";
}
sub vcl_init {
new vk8s_cluster = directors.shard();
vk8s_cluster.add_backend(varnish-8445d4f7f-z2b9p);
vk8s_cluster.add_backend(varnish-8445d4f7f-k22dn);
vk8s_cluster.add_backend(varnish-8445d4f7f-ldljf);
vk8s_cluster.reconfigure();
}
sub vcl_recv {
unset req.http.VK8S-Shard-Primary-Only;
if (remote.ip !~ vk8s_cluster_acl
&& "" + vk8s_cluster.backend(resolve=NOW) != server.identity) {
set req.http.VK8S-Shard-Primary-Only = "true";
set req.backend_hint = cluster.backend(resolve=NOW);
return (pass);
}
else if (remote.ip ~ vk8s_cluster_acl) {
if (req.http.Host == "vk8s_cluster") {
if (req.url == "/vk8s_cluster_health") {
return (synth(200));
}
return (synth(404));
}
# prevent deadlock for accidental cyclic requests
set req.hash_ignore_busy = true;
# if we're async, don't deliver stale
if (req.http.VK8S-Is-Bgfetch == "true") {
set req.grace = 0s;
}
return (hash);
}
}
sub vcl_pass {
if (req.http.VK8S-Shard-Primary-Only) {
return (pass);
}
}
sub vcl_backend_fetch {
if (bereq.http.VK8S-Shard-Primary-Only) {
return (fetch);
}
if (bereq.retries == 0
&& !bereq.uncacheable
&& remote.ip !~ vk8s_cluster_acl
&& "" + vk8s_cluster.backend(resolve=NOW) != server.identity) {
set bereq.backend = vk8s_cluster.backend(resolve=LAZY);
set bereq.http.VK8S-Is-Bgfetch = bereq.is_bgfetch;
return (fetch);
}
}
sub vcl_backend_response {
if (bereq.http.VK8S-Shard-Primary-Only) {
return (deliver);
}
if (bereq.backend == vk8s_cluster.backend(resolve=LAZY)) {
if (beresp.http.VK8S-Cluster-TTL) {
set beresp.ttl = std.duration(
beresp.http.VK8S-Cluster-TTL + "s", 1s);
if (beresp.ttl > 5m) {
set beresp.ttl = 5m;
}
unset beresp.http.VK8S-Cluster-TTL;
}
else {
set beresp.uncacheable = true;
}
return (deliver);
}
}
sub vcl_backend_error {
if (bereq.backend == vk8s_cluster.backend(resolve=LAZY)) {
return (deliver);
}
}
sub vcl_deliver {
if (bereq.http.VK8S-Shard-Primary-Only) {
return (deliver);
}
unset resp.http.VK8S-Cluster-TTL;
if (remote.ip ~ vk8s_cluster_acl) {
if (! obj.uncacheable) {
set resp.http.VK8S-Cluster-TTL = obj.ttl;
}
return (deliver);
}
}
......@@ -179,9 +179,38 @@ func TestShardTemplate(t *testing.T) {
}
}
func TestPrimaryOnlyShardTemplate(t *testing.T) {
var buf bytes.Buffer
gold := "primaryonly_shard.golden"
tmplName := "self-shard.tmpl"
tmpl, err := template.New(tmplName).Funcs(fMap).ParseFiles(tmplName)
if err != nil {
t.Error("Cannot parse shard template:", err)
return
}
varnishCluster.PrimaryOnly = true
if err := tmpl.Execute(&buf, varnishCluster); err != nil {
t.Error("cluster template Execute():", err)
return
}
ok, err := cmpGold(buf.Bytes(), gold)
if err != nil {
t.Fatalf("Reading %s: %v", gold, err)
}
if !ok {
t.Errorf("Generated VCL for primary-only self-sharding does "+
"not match gold file: %s", gold)
if testing.Verbose() {
t.Logf("Generated: %s", buf.String())
}
}
}
func TestGetSrc(t *testing.T) {
gold := "ingress_shard.golden"
cafeSpec.ShardCluster = varnishCluster
cafeSpec.ShardCluster.PrimaryOnly = false
src, err := cafeSpec.GetSrc()
if err != nil {
t.Error("Spec.GetSrc():", err)
......
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