Skip to content

Commit 0b7f529

Browse files
author
Matthew Fisher
committed
ref(router): split domains to its own custom directive
In order to support multiple certs on multiple custom domains bound to the same application, we need to split out each custom domain to its own `server {}` directive. In master, the domain etcd keys are set like so: SET /deis/domains/go "www.bacongobbler.com foo.bacongobbler.com" In confd v0.5.0, there is no way to split strings by whitespace so there's no way to iterate through each domain bound to an application. In this commit, there's a controller data migration script which will migrate existing etcd keys for custom domain endpoints over to the new syntax: SET /deis/domains/www.bacongobbler.com "go" SET /deis/domains/foo.bacongobbler.com "go" Confd v0.8.0 has support for splitting strings, but with this approach we can start providing support for migrations such as the one proposed in #3399.
1 parent 7c11861 commit 0b7f529

5 files changed

Lines changed: 103 additions & 28 deletions

File tree

controller/api/models.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -977,29 +977,26 @@ def _etcd_publish_cert(**kwargs):
977977

978978
def _etcd_purge_cert(**kwargs):
979979
cert = kwargs['instance']
980-
_etcd_client.delete('/deis/certs/{}'.format(cert),
981-
prevExist=True, dir=True, recursive=True)
980+
try:
981+
_etcd_client.delete('/deis/certs/{}'.format(cert),
982+
prevExist=True, dir=True, recursive=True)
983+
except KeyError:
984+
pass
982985

983986

984987
def _etcd_publish_domains(**kwargs):
985-
app = kwargs['instance'].app
986-
app_domains = app.domain_set.all()
987-
if app_domains:
988-
_etcd_client.write('/deis/domains/{}'.format(app),
989-
' '.join(str(d.domain) for d in app_domains))
988+
domain = kwargs['instance']
989+
if kwargs['created']:
990+
_etcd_client.write('/deis/domains/{}'.format(domain), domain.app)
990991

991992

992993
def _etcd_purge_domains(**kwargs):
993-
app = kwargs['instance'].app
994-
app_domains = app.domain_set.all()
995-
if app_domains:
996-
_etcd_client.write('/deis/domains/{}'.format(app),
997-
' '.join(str(d.domain) for d in app_domains))
998-
else:
999-
try:
1000-
_etcd_client.delete('/deis/domains/{}'.format(app))
1001-
except KeyError:
1002-
pass
994+
domain = kwargs['instance']
995+
try:
996+
_etcd_client.delete('/deis/certs/{}'.format(domain),
997+
prevExist=True, dir=True, recursive=True)
998+
except KeyError:
999+
pass
10031000

10041001

10051002
# Log significant app-related events

controller/bin/boot

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ etcd_safe_mkdir /deis/services
5656
etcd_safe_mkdir /deis/domains
5757
etcd_safe_mkdir /deis/platform
5858

59+
# run etcd data migrations
60+
echo "controller: running etcd data migrations..."
61+
for script in $(ls /app/migrations/data/*.sh);
62+
do
63+
. $script;
64+
done
65+
echo "controller: done running etcd data migrations."
66+
5967
# wait for confd to run once and install initial templates
6068
until confd -onetime -node $ETCD --confdir /app --interval 5 --quiet 2>/dev/null; do
6169
echo "controller: waiting for confd to write initial templates..."

controller/migrations/data/0001.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
3+
ETCD_PORT=${ETCD_PORT:-4001}
4+
ETCD="$HOST:$ETCD_PORT"
5+
ETCDCTL="etcdctl -C $ETCD"
6+
7+
if [[ "$($ETCDCTL get /deis/migrations/data/0001 2> /dev/null)" != "done" ]];
8+
then
9+
for i in $($ETCDCTL ls /deis/domains 2> /dev/null);
10+
do
11+
for j in $($ETCDCTL get $i);
12+
do
13+
$ETCDCTL set /deis/domains/$j "$(basename $i)" 1> /dev/null;
14+
echo "migrated $j"
15+
done;
16+
$ETCDCTL rm $i;
17+
done
18+
$ETCDCTL set /deis/migrations/data/0001 "done"
19+
fi

router/image/templates/deis.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
server_name_in_redirect off;
22
port_in_redirect off;
3+
listen 80;
34

45
{{ if .deis_router_sslCert }}
5-
listen 80;
66
listen 443 ssl spdy;
77
ssl_certificate /etc/ssl/deis.cert;
88
ssl_certificate_key /etc/ssl/deis.key;

router/image/templates/nginx.conf

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,10 @@ http {
139139
## end deis-store-gateway
140140

141141
## start service definitions for each application
142-
{{ $useSSL := or .deis_router_sslCert "false" }}
143142
{{ $affinityArg := .deis_router_affinityArg }}
144143
{{ $certs := .deis_certs }}
145-
{{ $domains := .deis_domains }}{{ range $service := .deis_services }}{{ if $service.Nodes }}
144+
{{ $domains := .deis_domains }}
145+
{{ range $service := .deis_services }}{{ if $service.Nodes }}
146146
upstream {{ Base $service.Key }} {
147147
{{ if $affinityArg }}hash $arg_{{ $affinityArg }} consistent;
148148
{{ end }}
@@ -151,21 +151,72 @@ http {
151151
}
152152
{{ end }}
153153

154+
## server entries for custom domains
155+
{{ range $domain := $domains }}{{ if eq (Base $service.Key) $domain.Value }}
154156
server {
155-
server_name ~^{{ Base $service.Key }}\.(?<domain>.+)${{ range $app_domains := $domains }}{{ if eq (Base $service.Key) (Base $app_domains.Key) }} {{ $app_domains.Value }}{{ end }}{{ end }};
156-
{{ range $domain := $domains }}{{ range $cert := $certs }}
157-
{{ if eq $domain.Value (Base $cert.Key) }}
158-
{{ $useSSL := "true" }}
157+
server_name {{ Base $domain.Key }};
159158
server_name_in_redirect off;
160159
port_in_redirect off;
161160
listen 80;
161+
{{/* if a SSL certificate is installed for this domain, use SSL */}}
162+
{{/* Note (bacongobbler): domains are separate from the default platform domain, */}}
163+
{{/* so we can't rely on deis.conf as each domain is an island */}}
164+
{{ range $cert := $certs }}{{ if eq (Base $domain.Key) (Base $cert.Key) }}
162165
listen 443 ssl spdy;
163-
ssl_certificate /etc/ssl/deis/certs/{{ Base $cert.Key }}.cert;
164-
ssl_certificate_key /etc/ssl/deis/keys/{{ Base $cert.Key }}.key;
166+
ssl_certificate /etc/ssl/deis/certs/{{ Base $domain.Key }}.cert;
167+
ssl_certificate_key /etc/ssl/deis/keys/{{ Base $domain.Key }}.key;
168+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
169+
{{ end }}{{ end }}
170+
171+
{{ if $service.Nodes }}
172+
location / {
173+
{{ if eq $useFirewall "true" }}include /opt/nginx/firewall/active-mode.rules;{{ end }}
174+
proxy_buffering off;
175+
proxy_set_header Host $host;
176+
set $access_ssl 'off';
177+
set $access_port '80';
178+
if ($access_scheme ~ https) {
179+
set $access_ssl 'on';
180+
set $access_port '443';
181+
}
182+
proxy_set_header X-Forwarded-Port $access_port;
183+
proxy_set_header X-Forwarded-Proto $access_scheme;
184+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
185+
proxy_set_header X-Forwarded-Ssl $access_ssl;
186+
proxy_redirect off;
187+
proxy_connect_timeout 30s;
188+
proxy_send_timeout 1200s;
189+
proxy_read_timeout 1200s;
190+
proxy_http_version 1.1;
191+
proxy_set_header Upgrade $http_upgrade;
192+
proxy_set_header Connection $connection_upgrade;
193+
194+
proxy_next_upstream error timeout http_502 http_503 http_504;
195+
196+
{{ if eq $enforceHTTPS "true" }}
197+
if ($access_scheme != "https") {
198+
return 301 https://$server_name$request_uri;
199+
}
200+
{{ end }}
201+
202+
proxy_pass http://{{ Base $service.Key }};
203+
}
165204
{{ else }}
166-
include deis.conf;
205+
location / {
206+
return 503;
207+
}
167208
{{ end }}
168-
{{ end }}{{ end }}
209+
210+
{{ if eq $useFirewall "true" }}location /RequestDenied {
211+
return {{ $firewallErrorCode }};
212+
}{{ end }}
213+
}
214+
{{ end }}{{ end }}
215+
## end entries for custom domains
216+
217+
server {
218+
server_name ~^{{ Base $service.Key }}\.(?<domain>.+)$;
219+
include deis.conf;
169220

170221
{{ if $service.Nodes }}
171222
location / {

0 commit comments

Comments
 (0)