Merge ~pjdc/ubuntu-mirror-charm/+git/ubuntu-mirror-charm:linuxcontainers into ubuntu-mirror-charm:master

Proposed by Paul Collins
Status: Merged
Approved by: Paul Collins
Approved revision: f08fd0ed505169a5de682cd77cfee04228dfa68e
Merged at revision: c69b05c81bc8af2b1f25e38872d99f58576db775
Proposed branch: ~pjdc/ubuntu-mirror-charm/+git/ubuntu-mirror-charm:linuxcontainers
Merge into: ubuntu-mirror-charm:master
Diff against target: 1231 lines (+1038/-9)
13 files modified
config.yaml (+80/-1)
files/check-mirror.sh (+11/-2)
files/mirror-linuxcontainers.sh (+97/-0)
hooks/Config.py (+1/-0)
hooks/hooks.py (+34/-6)
keys/juju-tools.asc (+51/-0)
keys/lxc-devel.asc (+29/-0)
templates/apache-linuxcontainers-api.include.tmpl (+41/-0)
templates/apache-linuxcontainers-tls.include.tmpl (+16/-0)
templates/apache-linuxcontainers.tmpl (+74/-0)
tests/unit/test_linuxcontainers.py (+56/-0)
tests/unit/testdata/linuxcontainers/linuxcontainers.txt (+429/-0)
tests/unit/testdata/linuxcontainers/thirdparty.txt (+119/-0)
Reviewer Review Type Date Requested Status
Barry Price Approve
Canonical IS Reviewers Pending
Review via email: mp+396537@code.launchpad.net

Commit message

add linuxcontainers support

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Barry Price (barryprice) wrote :

LGTM

review: Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision c69b05c81bc8af2b1f25e38872d99f58576db775

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/config.yaml b/config.yaml
2index f2b4616..2f5f38c 100644
3--- a/config.yaml
4+++ b/config.yaml
5@@ -511,7 +511,7 @@ options:
6 type: string
7 description: "Root location of mirrored files for the MAAS images mirror"
8 mirror_maas-images_description:
9- default: "Ubuntu Old Releases"
10+ default: "MAAS images"
11 type: string
12 description: "A brief welcome message for the MAAS images mirror"
13 mirror_maas-images_rsync_log:
14@@ -563,6 +563,85 @@ options:
15 description: >
16 Local path of the key file to use when triggering downstream
17 mirrors. If empty, downstream mirrors are not triggered.
18+ mirror_linuxcontainers_name:
19+ default: "images.linuxcontainers.org"
20+ type: string
21+ description: >
22+ FQDN of the Linux Containers image mirror.
23+
24+ When set to "image.linuxcontainers.org", the virtualhost will
25+ redirect to the uk or us subdomain based on the source IP
26+ location as determined by GeoIP.
27+ mirror_linuxcontainers_aliases:
28+ default: '["uk.images.linuxcontainers.org", "us.images.linuxcontainers.org"]'
29+ type: string
30+ description: >
31+ List of Apache aliases for the Linux Containers image mirror.
32+
33+ When mirror_linuxcontainers_name is set to "images.linuxcontainers.org",
34+ a separate virtualhost will be generated for each alias to act
35+ as destinations for GeoIP-based redirects and to log traffic to
36+ each alias separately.
37+
38+ Otherwise, these aliases will simple be declared as standard
39+ Apache aliases using the ServerAlias directive.
40+ mirror_linuxcontainers_path:
41+ default: "/srv/ftp.root/lxc-images"
42+ type: string
43+ description: "Root location of mirrored files for the Linux Containers image mirror"
44+ mirror_linuxcontainers_description:
45+ default: "Linux Containers (LXC/LXD) Images"
46+ type: string
47+ description: "A brief welcome message for the Linux Containers image mirror"
48+ mirror_linuxcontainers_rsync_log:
49+ default: false
50+ type: boolean
51+ description: "Whether to log rsync requests for the Linux Containers image mirror"
52+ mirror_linuxcontainers_command:
53+ default: "mirror-linuxcontainers.sh"
54+ type: string
55+ description: "The command to use to sync the Linux Containers image mirror"
56+ mirror_linuxcontainers_source_url:
57+ default: "rsync://rsync.images.linuxcontainers.org/lxc-images"
58+ type: string
59+ description: "The URL the Linux Containers image mirror will be fetched from"
60+ mirror_linuxcontainers_rsync_auth:
61+ default: '{}'
62+ type: string
63+ description: "Optional rsync authentication details for mirror_linuxcontainers_source_url"
64+ mirror_linuxcontainers_rsync_module:
65+ default: "lxc-images"
66+ type: string
67+ description: "The name of the rsync module for this mirror role"
68+ mirror_linuxcontainers_sync_time:
69+ default: "ondemand"
70+ type: string
71+ description: "When mirror updates should be run. Either a cron(5) format time specification or 'ondemand' for ssh triggering"
72+ mirror_linuxcontainers_trigger:
73+ default: ""
74+ type: string
75+ description: "A base64 string containing the ssh trigger public key"
76+ mirror_linuxcontainers_apache_early_extra:
77+ default: ""
78+ type: string
79+ description: "A base64 string containing apache configuration options to be included early in the config file"
80+ mirror_linuxcontainers_apache_late_extra:
81+ default: ""
82+ type: string
83+ description: "A base64 string containing apache configuration options to be included late in the config file"
84+ mirror_linuxcontainers_downstream_mirrors:
85+ default: ""
86+ type: "string"
87+ description: >
88+ A space-separated list of mirrors to trigger following a sync.
89+ Username defaults to the mirror_user config setting, and
90+ otherwise may be specified by "user@host" syntax.
91+ mirror_linuxcontainers_trigger_keyfile:
92+ default: ""
93+ type: "string"
94+ description: >
95+ Local path of the key file to use when triggering downstream
96+ mirrors. If empty, downstream mirrors are not triggered.
97 mirror_old-releases_name:
98 default: "old-releases.ubuntu.com"
99 type: string
100diff --git a/files/check-mirror.sh b/files/check-mirror.sh
101index a04d177..003b48a 100755
102--- a/files/check-mirror.sh
103+++ b/files/check-mirror.sh
104@@ -63,14 +63,17 @@ case ${role} in
105 unsigned=xenial/current/SHA256SUMS
106 signed=${unsigned}.gpg
107 ;;
108+ linuxcontainers)
109+ unsigned=streams/v1/index.json
110+ signed=${unsigned}.gpg
111+ ;;
112 old-releases)
113 unsigned=ubuntu/dists/warty/Release
114 signed=${unsigned}.gpg
115 ;;
116 simple-streams)
117- # TODO(pjdc): key is not packaged; fetch from install hook?
118 unsigned=juju/images/releases/streams/v1/index.json
119- signed=${unsigned}.gpg # not used
120+ signed=${unsigned}.gpg
121 ;;
122 maas-images)
123 # NOTE(pjdc): ephemeral-v3 is the current stuff and seems to have no fixed paths to signed files we could check
124@@ -99,12 +102,18 @@ case ${role} in
125 cloud-images)
126 keyring_file=/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg
127 ;;
128+ linuxcontainers)
129+ keyring_file=/usr/local/share/ubuntu-mirror-charm.gpg
130+ ;;
131 old-releases)
132 keyring_file=/usr/share/keyrings/ubuntu-archive-removed-keys.gpg
133 ;;
134 ubuntu-cloud-archive)
135 keyring_file=/usr/share/keyrings/ubuntu-cloud-keyring.gpg
136 ;;
137+ simple-streams)
138+ keyring_file=/usr/local/share/ubuntu-mirror-charm.gpg
139+ ;;
140 *)
141 keyring_file=/usr/share/keyrings/ubuntu-archive-keyring.gpg
142 ;;
143diff --git a/files/mirror-linuxcontainers.sh b/files/mirror-linuxcontainers.sh
144new file mode 100755
145index 0000000..4f0e3fb
146--- /dev/null
147+++ b/files/mirror-linuxcontainers.sh
148@@ -0,0 +1,97 @@
149+#!/bin/bash
150+#
151+#-------------------------------------------------------#
152+# This file is Juju managed - do not make local changes #
153+#-------------------------------------------------------#
154+#
155+# Author: Chris Stratford <chris.stratford@canonical.com>
156+# Copyright 2014,2021 Canonical Ltd.
157+#
158+# Triple-pass rsync mirror for images.linuxcontainers.org
159+#
160+# ${role}.conf should look like:
161+# DEST_DIR=/srv/ftp.root/lxc-images
162+# SOURCE_URL=rsync://rsync.image.linuxcontainers.org/lxc-images
163+# RSYNC_PASSWORD=secret
164+
165+if [ $# -lt 1 ]; then
166+ myname=$(basename $0)
167+ echo "Usage: ${myname} <role>"
168+ exit 1
169+fi
170+
171+role=$1
172+myhostname=$(hostname)
173+logfile=${HOME}/log/mirror-${role}.log
174+
175+# Magic to make sure things keep running in the background
176+# after ssh has gone away
177+if [ "$2" != "go" ]; then
178+ annotate-output $0 $1 go > ${logfile} 2>&1 &
179+ exit 0
180+fi
181+
182+set -u
183+
184+function log {
185+ echo $1
186+}
187+
188+function fatal {
189+ log $1
190+ exit 1
191+}
192+
193+if [ -f ${HOME}/mirror-config/${role}.conf ]; then
194+ . ${HOME}/mirror-config/${role}.conf
195+else
196+ fatal "${role}.conf file missing - aborting"
197+fi
198+
199+export RSYNC_PASSWORD
200+lockfile="Archive-Update-in-Progress-${role}-${myhostname}"
201+lockpath="${DEST_DIR}/${lockfile}"
202+
203+if lockfile -! -l 43200 -r 0 "${lockpath}"; then
204+ fatal "${myhostname} is unable to start an rsync for ${role}. Lockfile exists"
205+fi
206+trap "rm -f ${lockpath} > /dev/null 2>&1" exit
207+
208+if [ ! -d ${DEST_DIR} ]; then
209+ log "${DEST_DIR} does not exist yet, trying to create it..."
210+ mkdir -p ${DEST_DIR} || fatal "Creation of ${DEST_DIR} failed."
211+fi
212+
213+if [ -n "${RSYNC_USER}" ]; then
214+ url=$(echo ${SOURCE_URL}|sed -e "s,//,//${RSYNC_USER}@,")
215+else
216+ url=${SOURCE_URL}
217+fi
218+
219+# If upstream is close to us and triggers us via ssh, we may start
220+# syncing before it has deleted its local lock file, which then
221+# becomes a "file has vanished" and non-zero exit, causing the trace
222+# file to not update, which makes the mirror seem stale when it isn't.
223+# Therefore, let's just:
224+log "== Sleeping to allow upstream delete its lock file =="
225+sleep 5
226+
227+
228+# Here we use a three-phase sunc as per RT#126178.
229+log "== Phase 1: Syncing new images from source =="
230+rsync --timeout 10800 -a --include='/images/***' --exclude='*' ${SOURCE_URL} ${DEST_DIR} || fatal "Phase 1 sync from $url failed"
231+
232+log "== Phase 2: Syncing metadata from source =="
233+rsync --timeout 10800 -a --exclude "${lockpath}" --exclude '/images/***' --delete ${SOURCE_URL} ${DEST_DIR} || fatal "Phase 2 sync from $url failed"
234+
235+log "== Phase 3: Removing images no longer present on source =="
236+rsync --timeout 10800 -a --include='/images/***' --exclude='*' --delete ${SOURCE_URL} ${DEST_DIR} || fatal "Phase 3 sync from $url failed"
237+
238+if [ -n "${DOWNSTREAM_MIRRORS}" -a -n "${TRIGGER_KEYFILE}" ]; then
239+ t=15m
240+ log "== Triggering downstream mirrors (will give up after $t) =="
241+ timeout $t ${SCRIPT_DIR}/trigger-downstream-mirrors.sh $role $TRIGGER_KEYFILE $DOWNSTREAM_MIRRORS
242+fi
243+
244+savelog ${logfile} > /dev/null 2>&1
245+rm -f ${lockpath} > /dev/null 2>&1
246diff --git a/hooks/Config.py b/hooks/Config.py
247index 03f840a..5f41727 100755
248--- a/hooks/Config.py
249+++ b/hooks/Config.py
250@@ -241,6 +241,7 @@ class Config:
251 return [
252 "cdimage",
253 "cloud-image",
254+ "linuxcontainers",
255 "maas-images",
256 "old-releases",
257 "ports",
258diff --git a/hooks/hooks.py b/hooks/hooks.py
259index 3c1b3b4..24a6cc8 100755
260--- a/hooks/hooks.py
261+++ b/hooks/hooks.py
262@@ -18,6 +18,8 @@ import sys
263 import types
264 import yaml
265
266+from glob import glob
267+
268 from charmhelpers.core.host import (
269 adduser,
270 lsb_release,
271@@ -63,11 +65,13 @@ required_pkgs = [
272 'apache2',
273 'curl', # for check-mirror.sh
274 'devscripts', # provides annotate-output
275+ 'geoip-database',
276+ 'libapache2-mod-geoip',
277 'logrotate',
278 'procmail', # provides lockfile
279 'rsync',
280- 'vsftpd',
281 'ubuntu-cloud-keyring', # for check-mirror.sh
282+ 'vsftpd',
283 'xinetd',
284 ]
285
286@@ -75,6 +79,7 @@ service_affecting_packages = ['apache2']
287
288 apache_modules = [
289 'expires',
290+ 'geoip',
291 'headers',
292 'rewrite',
293 ]
294@@ -82,6 +87,7 @@ apache_modules = [
295 scripts_to_copy = [
296 'mirror-1stage.sh',
297 'mirror-2stage.sh',
298+ 'mirror-linuxcontainers.sh',
299 'check-mirror.sh',
300 'check-updates.sh',
301 ]
302@@ -522,8 +528,15 @@ def configure_apache(conf, hostname): # noqa: C901
303 tmpl_data["logdir"] = apache_logdir
304 tmpl_data["addresses"] = role_config.get('addresses', ['*'])
305 all_addresses.update(tmpl_data["addresses"])
306- tmpl_data["ports"] = [80, 443] if role_config.get('https') else [80]
307- all_ports.update(tmpl_data["ports"])
308+
309+ ports = [80]
310+ if role_config.get('https'):
311+ ports.append(443)
312+ if role == 'linuxcontainers':
313+ ports.append(8443)
314+ all_ports.update(ports)
315+ tmpl_data["ports"] = ports
316+
317 file_from_template(mirror['tmpl_file'], sites_available, tmpl_data)
318 ensure_symlink(sites_available, sites_enabled)
319
320@@ -543,8 +556,11 @@ def configure_apache(conf, hostname): # noqa: C901
321 os.chown(mirror["path"], mirror_userinfo.pw_uid, mirror_userinfo.pw_gid)
322 ensure_symlink(mirror["path"], linkdest)
323
324- # Update ports file
325- all_addresses.discard('*') # archive.ubuntu.com must not open port 443.
326+ # archive.ubuntu.com must not open port 443. Three factors align
327+ # to prevent this: 1) we do not set "addresses" or "https" in the
328+ # role_map; 2) the template doesn't make non-port-80 sockets for
329+ # members of "addresses"; 3) the wildcard address is discarded.
330+ all_addresses.discard('*')
331 file_from_template('apache-listen-ports.conf.tmpl', '/etc/apache2/ports.conf',
332 {'addresses': sorted(all_addresses), 'ports': sorted(all_ports)})
333
334@@ -939,7 +955,10 @@ def configure_nrpe(conf, hostname): # noqa: C901
335 tmpl_data["hostname"] = hostname
336 tmpl_data["use"] = "active-service"
337 tmpl_data["nagios_hostname"] = conf.nagios_hostname()
338- tmpl_data["tracepath"] = os.path.join(mirror["path"], ".trace", mirror["base_role"] + "-" + hostname)
339+ if role == "linuxcontainers":
340+ tmpl_data["tracepath"] = os.path.join(mirror["path"], ".serial")
341+ else:
342+ tmpl_data["tracepath"] = os.path.join(mirror["path"], ".trace", mirror["base_role"] + "-" + hostname)
343
344 for check, check_details in role_checks.items():
345 if check_details.get('when') and not role_config.get(check_details['when']):
346@@ -1104,6 +1123,14 @@ def configure_directories(conf, hostname):
347 mkdir("/srv/ftp.root")
348
349
350+def configure_keyring(conf, hostname):
351+ import_cmd = [
352+ '/usr/bin/gpg', '--no-default-keyring', '--keyring', '/usr/local/share/ubuntu-mirror-charm.gpg', '--import']
353+ keys = glob(os.path.join(charm_dir(), 'keys', '*.asc'))
354+ import_cmd.extend(keys)
355+ check_call(import_cmd)
356+
357+
358 @hooks.hook("install.real")
359 def install():
360 conf = Config()
361@@ -1134,6 +1161,7 @@ def config_changed():
362 configure_nrpe(conf, hostname)
363 configure_log_archiving(conf, hostname)
364 configure_sysctl(conf, hostname)
365+ configure_keyring(conf, hostname)
366
367
368 @hooks.hook("upgrade-charm")
369diff --git a/keys/juju-tools.asc b/keys/juju-tools.asc
370new file mode 100644
371index 0000000..0bf2290
372--- /dev/null
373+++ b/keys/juju-tools.asc
374@@ -0,0 +1,51 @@
375+-----BEGIN PGP PUBLIC KEY BLOCK-----
376+
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
424+=hQAI
425+-----END PGP PUBLIC KEY BLOCK-----
426diff --git a/keys/lxc-devel.asc b/keys/lxc-devel.asc
427new file mode 100644
428index 0000000..90af404
429--- /dev/null
430+++ b/keys/lxc-devel.asc
431@@ -0,0 +1,29 @@
432+-----BEGIN PGP PUBLIC KEY BLOCK-----
433+
434+mQINBFLQvwwBEADNVxfLfsKibZbF5v2Tct9N0gxdFViOzVd/IRDrJ6pTEAcMlWdS
435+h3VM3lV0qd1WtMlqCTgcbbk6zUAYnPQ2RsagCpOlaIZqbZ8Cv4390PuVAhG2QQvt
436+9YrED00unJBomsC3QuF+xg0SBpHChmFUgJxomsFuAjowdMoh8XExM2v4TEe+vm9Z
437+7ohBCxkw7C5cV9cQHeC1XiGBCccRe1Ib1U7+GmPUxAtGzHUsQQ4MjE/j830dmPJw
438+w/ZNauKyNqSzpBsMnEiX+8RwqYEeYtqBAw9pnA3BMSshfA5L5ORw3zYecowUWt+l
439+r5lhzBq2v3LLjzjwsb4wel8L7HZnUD+1bQe0QQkxWDKlHOIsB02DCwmz3fc9bvBI
440+KZwRQZ8al7HicpWc4zJPBb7U0BSHE+YwTdOffFFL7YfbRS+4yfn0JBSmtyfTPaOp
441+FvHV8MES52Mam3vyXWCKXC//3EXcWhhX4ZHfkcWJtEkDf1FwupptV6HEgx2d6UTZ
442+0vEK20Dx+Hzlg0mpR10SS/ltch8w1Zl2co467oTMspdnPosTrxG0p2G+s/gUA/+E
443+LY8fB/heXfNSb5IB3JJ8OTI+cwqN1Aw9X4aKPQcvPGvfQ5Mz8FZ4gkV38QzzMHsr
444+6eeZGUPcCctP6FVfCHO0Mzxwv2VOnTbH+k72Acni2piTwn0APd9LKilXOwARAQAB
445+tDpMWEMgcHJlLWJ1aWx0IGltYWdlcyA8bHhjLWRldmVsQGxpc3RzLmxpbnV4Y29u
446+dGFpbmVycy5vcmc+iQI4BBMBAgAiBQJS0L8MAhsDBgsJCAcDAgYVCAIJCgsEFgID
447+AQIeAQIXgAAKCRC67/iMIvbiFtzVD/933Dv/NsyPAiwT6BFLlqtq/Tl3NxcUogDS
448+Rkv1oMiIunaKZRE/pQbLJVTSbt/eC3Kz7I40juDNsFGXXhD/sQCovMc58NpTKNPR
449+zs3jC5vDIW721cLOhYqITvdWN+RKDCJqxBBNJztKEv29uA0PONssKBmC/apTdB6D
450+QLLy3ddO/LzxDrCtC8ePLGjeVoEelZHR3tg8QZE+oVBuL3ZC2NTg/XaLSDO4zGCg
451+Jyd1IHGKhi20Q/sBLmsFifnWt5b6ovmRqwlsZXqcS+a7Z+WSmZWT9hKIR2XSzYUW
452+pmlJNO4VPzHgEcaCxlw3HxQqX0Loz4R8Y91shKuJ591ZMtmyf4j6Yl9KZfLs+lZH
453+iX7uazhw4miXdpCvOKe8fPLa+68JGIYPxG22l2jqPJ9FIOtpSrJX3D/i8xed5h2V
454+Vd38fZBn+cH1Wqbw1Ni94/f66Rp5GzJyMoVO7A016Ek3wx920SmX4HkCSEel77pF
455+gvCBZkQDiD6TNCJxjHQpxoSGo6SDEfP0FjntB0yVy0zi+Iij9F3O1bPIIuses4OQ
456+FkUGJb6V0L1wXl5hOARmVtgn6klwhsLf0EsjuH9yJN2GCuaKdjAdR8J1TsjW+q4h
457+DKMvYOZ99YJUE+qujz9u93tJRZTuD8pQsGRez7qrZ0LUAdd/aOjNDLWzJ8AzeQE+
458+OKVNmCzO9A==
459+=euOK
460+-----END PGP PUBLIC KEY BLOCK-----
461diff --git a/templates/apache-linuxcontainers-api.include.tmpl b/templates/apache-linuxcontainers-api.include.tmpl
462new file mode 100644
463index 0000000..36cf273
464--- /dev/null
465+++ b/templates/apache-linuxcontainers-api.include.tmpl
466@@ -0,0 +1,41 @@
467+## This template does not use any Cheetah features (yet?) but for
468+## consistency it is not included raw, and therefore $ is escaped.
469+ # LXD: Recursive queries
470+ RewriteCond %{QUERY_STRING} recursion=1
471+ RewriteRule ^/1.0.*\$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
472+
473+ # LXD: Normal queries
474+ RewriteRule ^/1.0.*\$ /meta/lxd%{REQUEST_URI}/index.json [L]
475+
476+ <Location />
477+ Require all granted
478+ </Location>
479+
480+ # LXC: Allow image listing
481+ <Location /images>
482+ Options +Indexes
483+ </Location>
484+
485+ # LXD: API root
486+ <Location /1.0/>
487+ ErrorDocument 404 /meta/lxd/404.json
488+ Options -Indexes
489+ </Location>
490+
491+ # LXD: images
492+ <Location /1.0/images/>
493+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
494+ Options +FollowSymlinks
495+ </Location>
496+
497+ # LXD: aliases
498+ <Location /1.0/images/aliases/>
499+ ErrorDocument 404 /meta/lxd/404.json
500+ </Location>
501+
502+ # LXD: downloads
503+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
504+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
505+ </LocationMatch>
506+ # Simplestreams: redirect
507+ RewriteRule ^/streams(.*)\$ /meta/simplestreams\$1 [L]
508diff --git a/templates/apache-linuxcontainers-tls.include.tmpl b/templates/apache-linuxcontainers-tls.include.tmpl
509new file mode 100644
510index 0000000..3851d19
511--- /dev/null
512+++ b/templates/apache-linuxcontainers-tls.include.tmpl
513@@ -0,0 +1,16 @@
514+#if $port == 80
515+#set $proto = 'http'
516+#else if $port == 443
517+#set $proto = 'https'
518+#else
519+#set $proto = 'https'
520+#end if
521+ # SSL configuration
522+ SSLEngine On
523+ SSLCertificateFile /etc/ssl/certs/${name}.crt
524+ SSLCertificateKeyFile /etc/ssl/private/${name}.key
525+ SSLCertificateChainFile /etc/ssl/certs/${name}_chain.crt
526+ Header always set Strict-Transport-Security "max-age=31536000"
527+ RequestHeader set X_FORWARDED_PORT "${port}"
528+ RequestHeader set X_FORWARDED_PROTO "${proto}"
529+
530diff --git a/templates/apache-linuxcontainers.tmpl b/templates/apache-linuxcontainers.tmpl
531new file mode 100644
532index 0000000..f2c9391
533--- /dev/null
534+++ b/templates/apache-linuxcontainers.tmpl
535@@ -0,0 +1,74 @@
536+#for $port in $ports
537+#set global $port = $port
538+#set $sockets = ' '.join(sorted(['{}:{}'.format(address, port) for address in $addresses]))
539+#if $port == 80
540+#set global $proto = 'http'
541+#set $uk_url = 'http://uk.{}/'.format($name)
542+#set $us_url = 'http://us.{}/'.format($name)
543+#else if $port == 443
544+#set global $proto = 'https'
545+#set $uk_url = 'https://uk.{}/'.format($name)
546+#set $us_url = 'https://us.{}/'.format($name)
547+#else
548+#set global $proto = 'https'
549+#set $uk_url = 'https://uk.{}:{}/'.format($name, $port)
550+#set $us_url = 'https://us.{}:{}/'.format($name, $port)
551+#end if
552+<VirtualHost ${sockets}>
553+ ServerName ${name}
554+#if $name != "images.linuxcontainers.org"
555+ #for $alias in $aliases
556+ ServerAlias ${alias}
557+ #end for
558+#end if
559+ CustomLog \${APACHE_LOG_DIR}/${name}.log vhost_combined
560+ DocumentRoot /srv/${name}/www
561+
562+ <Location />
563+ Require all granted
564+ </Location>
565+
566+#if $proto == "https"
567+#include 'templates/apache-linuxcontainers-tls.include.tmpl'
568+#end if
569+ RewriteEngine on
570+ AllowEncodedSlashes On
571+
572+#if $name == "images.linuxcontainers.org"
573+ # GeoIP: Redirect everything to appropriate country server
574+ GeoIPEnable On
575+ GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
576+ GeoIPDBFile /usr/share/GeoIP/GeoIPv6.dat
577+
578+ # Send North America, Oceania and South America to the US server
579+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE} ^(NA|OC|SA)\$
580+ RewriteRule ^/(.*)\$ ${us_url}\$1 [R=301,L]
581+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE_V6} ^(NA|OC|SA)\$
582+ RewriteRule ^/(.*)\$ ${us_url}\$1 [R=301,L]
583+
584+ # Send Africa, Antarctica, Asia, Europe, and all else to the UK server
585+ RewriteRule ^/(.*)\$ ${uk_url}\$1 [R=301,L]
586+#else
587+#include 'templates/apache-linuxcontainers-api.include.tmpl'
588+#end if
589+</VirtualHost>
590+
591+#if $name == "images.linuxcontainers.org"
592+#for $alias in $aliases
593+<VirtualHost ${sockets}>
594+ ServerName ${alias}
595+ CustomLog \${APACHE_LOG_DIR}/${alias}.log vhost_combined
596+ DocumentRoot /srv/${name}/www
597+
598+#if $proto == "https"
599+#include 'templates/apache-linuxcontainers-tls.include.tmpl'
600+#end if
601+ RewriteEngine on
602+ AllowEncodedSlashes On
603+
604+#include 'templates/apache-linuxcontainers-api.include.tmpl'
605+</VirtualHost>
606+
607+#end for
608+#end if
609+#end for
610diff --git a/tests/unit/test_linuxcontainers.py b/tests/unit/test_linuxcontainers.py
611new file mode 100644
612index 0000000..5a485ea
613--- /dev/null
614+++ b/tests/unit/test_linuxcontainers.py
615@@ -0,0 +1,56 @@
616+import os
617+import pytest
618+import unittest
619+
620+from Cheetah.Template import Template
621+
622+TEMPLATE = 'apache-linuxcontainers.tmpl'
623+
624+THIRDPARTY_SEARCH_LIST = {
625+ 'addresses': ['*'],
626+ 'name': 'lxd.example.net',
627+ 'aliases': ['uk.lxd.example.net', 'us.lxd.example.net'],
628+ 'ports': [80, 443],
629+}
630+
631+LINUXCONTAINERS_SEARCH_LIST = {
632+ 'addresses': ['91.189.88.247', '[2001:67c:1360:8001::33]'],
633+ 'name': 'images.linuxcontainers.org',
634+ 'aliases': ['uk.images.linuxcontainers.org', 'us.images.linuxcontainers.org'],
635+ 'ports': [80, 443, 8443],
636+}
637+
638+
639+class TestLinuxcontainers(unittest.TestCase):
640+ def setUp(self):
641+ self.addTypeEqualityFunc(str, self.assertMultiLineEqual)
642+ self.maxDiff = None
643+ self.testdata_dir = os.path.join(os.path.dirname(__file__), 'testdata', 'linuxcontainers')
644+
645+ def _template_compare(self, template, search_list, wanted_file):
646+ template_file = os.path.join(os.getcwd(), template)
647+ template = Template(file=template_file, searchList=search_list)
648+ wanted = open(wanted_file).read()
649+ self.assertEqual(str(template), wanted)
650+
651+ # Cheetah warns about using the Python version of NameMapper, so
652+ # we ignore it here. Matching more closely by the message doesn't
653+ # seem to work, probably because it begins with a newline and
654+ # Python's warnings matching code anchors the message regexp.
655+ @pytest.mark.filterwarnings("ignore::UserWarning:Cheetah")
656+ def test_template_linuxcontainers(self):
657+ self._template_compare(
658+ os.path.join(os.getcwd(), 'templates', TEMPLATE),
659+ LINUXCONTAINERS_SEARCH_LIST,
660+ os.path.join(self.testdata_dir, 'linuxcontainers.txt'))
661+
662+ # Cheetah warns about using the Python version of NameMapper, so
663+ # we ignore it here. Matching more closely by the message doesn't
664+ # seem to work, probably because it begins with a newline and
665+ # Python's warnings matching code anchors the message regexp.
666+ @pytest.mark.filterwarnings("ignore::UserWarning:Cheetah")
667+ def test_template_thirdparty(self):
668+ self._template_compare(
669+ os.path.join(os.getcwd(), 'templates', TEMPLATE),
670+ THIRDPARTY_SEARCH_LIST,
671+ os.path.join(self.testdata_dir, 'thirdparty.txt'))
672diff --git a/tests/unit/testdata/linuxcontainers/linuxcontainers.txt b/tests/unit/testdata/linuxcontainers/linuxcontainers.txt
673new file mode 100644
674index 0000000..1056067
675--- /dev/null
676+++ b/tests/unit/testdata/linuxcontainers/linuxcontainers.txt
677@@ -0,0 +1,429 @@
678+<VirtualHost 91.189.88.247:80 [2001:67c:1360:8001::33]:80>
679+ ServerName images.linuxcontainers.org
680+ CustomLog ${APACHE_LOG_DIR}/images.linuxcontainers.org.log vhost_combined
681+ DocumentRoot /srv/images.linuxcontainers.org/www
682+
683+ <Location />
684+ Require all granted
685+ </Location>
686+
687+ RewriteEngine on
688+ AllowEncodedSlashes On
689+
690+ # GeoIP: Redirect everything to appropriate country server
691+ GeoIPEnable On
692+ GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
693+ GeoIPDBFile /usr/share/GeoIP/GeoIPv6.dat
694+
695+ # Send North America, Oceania and South America to the US server
696+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE} ^(NA|OC|SA)$
697+ RewriteRule ^/(.*)$ http://us.images.linuxcontainers.org/$1 [R=301,L]
698+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE_V6} ^(NA|OC|SA)$
699+ RewriteRule ^/(.*)$ http://us.images.linuxcontainers.org/$1 [R=301,L]
700+
701+ # Send Africa, Antarctica, Asia, Europe, and all else to the UK server
702+ RewriteRule ^/(.*)$ http://uk.images.linuxcontainers.org/$1 [R=301,L]
703+</VirtualHost>
704+
705+<VirtualHost 91.189.88.247:80 [2001:67c:1360:8001::33]:80>
706+ ServerName uk.images.linuxcontainers.org
707+ CustomLog ${APACHE_LOG_DIR}/uk.images.linuxcontainers.org.log vhost_combined
708+ DocumentRoot /srv/images.linuxcontainers.org/www
709+
710+ RewriteEngine on
711+ AllowEncodedSlashes On
712+
713+ # LXD: Recursive queries
714+ RewriteCond %{QUERY_STRING} recursion=1
715+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
716+
717+ # LXD: Normal queries
718+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
719+
720+ <Location />
721+ Require all granted
722+ </Location>
723+
724+ # LXC: Allow image listing
725+ <Location /images>
726+ Options +Indexes
727+ </Location>
728+
729+ # LXD: API root
730+ <Location /1.0/>
731+ ErrorDocument 404 /meta/lxd/404.json
732+ Options -Indexes
733+ </Location>
734+
735+ # LXD: images
736+ <Location /1.0/images/>
737+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
738+ Options +FollowSymlinks
739+ </Location>
740+
741+ # LXD: aliases
742+ <Location /1.0/images/aliases/>
743+ ErrorDocument 404 /meta/lxd/404.json
744+ </Location>
745+
746+ # LXD: downloads
747+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
748+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
749+ </LocationMatch>
750+ # Simplestreams: redirect
751+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
752+</VirtualHost>
753+
754+<VirtualHost 91.189.88.247:80 [2001:67c:1360:8001::33]:80>
755+ ServerName us.images.linuxcontainers.org
756+ CustomLog ${APACHE_LOG_DIR}/us.images.linuxcontainers.org.log vhost_combined
757+ DocumentRoot /srv/images.linuxcontainers.org/www
758+
759+ RewriteEngine on
760+ AllowEncodedSlashes On
761+
762+ # LXD: Recursive queries
763+ RewriteCond %{QUERY_STRING} recursion=1
764+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
765+
766+ # LXD: Normal queries
767+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
768+
769+ <Location />
770+ Require all granted
771+ </Location>
772+
773+ # LXC: Allow image listing
774+ <Location /images>
775+ Options +Indexes
776+ </Location>
777+
778+ # LXD: API root
779+ <Location /1.0/>
780+ ErrorDocument 404 /meta/lxd/404.json
781+ Options -Indexes
782+ </Location>
783+
784+ # LXD: images
785+ <Location /1.0/images/>
786+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
787+ Options +FollowSymlinks
788+ </Location>
789+
790+ # LXD: aliases
791+ <Location /1.0/images/aliases/>
792+ ErrorDocument 404 /meta/lxd/404.json
793+ </Location>
794+
795+ # LXD: downloads
796+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
797+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
798+ </LocationMatch>
799+ # Simplestreams: redirect
800+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
801+</VirtualHost>
802+
803+<VirtualHost 91.189.88.247:443 [2001:67c:1360:8001::33]:443>
804+ ServerName images.linuxcontainers.org
805+ CustomLog ${APACHE_LOG_DIR}/images.linuxcontainers.org.log vhost_combined
806+ DocumentRoot /srv/images.linuxcontainers.org/www
807+
808+ <Location />
809+ Require all granted
810+ </Location>
811+
812+ # SSL configuration
813+ SSLEngine On
814+ SSLCertificateFile /etc/ssl/certs/images.linuxcontainers.org.crt
815+ SSLCertificateKeyFile /etc/ssl/private/images.linuxcontainers.org.key
816+ SSLCertificateChainFile /etc/ssl/certs/images.linuxcontainers.org_chain.crt
817+ Header always set Strict-Transport-Security "max-age=31536000"
818+ RequestHeader set X_FORWARDED_PORT "443"
819+ RequestHeader set X_FORWARDED_PROTO "https"
820+
821+ RewriteEngine on
822+ AllowEncodedSlashes On
823+
824+ # GeoIP: Redirect everything to appropriate country server
825+ GeoIPEnable On
826+ GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
827+ GeoIPDBFile /usr/share/GeoIP/GeoIPv6.dat
828+
829+ # Send North America, Oceania and South America to the US server
830+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE} ^(NA|OC|SA)$
831+ RewriteRule ^/(.*)$ https://us.images.linuxcontainers.org/$1 [R=301,L]
832+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE_V6} ^(NA|OC|SA)$
833+ RewriteRule ^/(.*)$ https://us.images.linuxcontainers.org/$1 [R=301,L]
834+
835+ # Send Africa, Antarctica, Asia, Europe, and all else to the UK server
836+ RewriteRule ^/(.*)$ https://uk.images.linuxcontainers.org/$1 [R=301,L]
837+</VirtualHost>
838+
839+<VirtualHost 91.189.88.247:443 [2001:67c:1360:8001::33]:443>
840+ ServerName uk.images.linuxcontainers.org
841+ CustomLog ${APACHE_LOG_DIR}/uk.images.linuxcontainers.org.log vhost_combined
842+ DocumentRoot /srv/images.linuxcontainers.org/www
843+
844+ # SSL configuration
845+ SSLEngine On
846+ SSLCertificateFile /etc/ssl/certs/images.linuxcontainers.org.crt
847+ SSLCertificateKeyFile /etc/ssl/private/images.linuxcontainers.org.key
848+ SSLCertificateChainFile /etc/ssl/certs/images.linuxcontainers.org_chain.crt
849+ Header always set Strict-Transport-Security "max-age=31536000"
850+ RequestHeader set X_FORWARDED_PORT "443"
851+ RequestHeader set X_FORWARDED_PROTO "https"
852+
853+ RewriteEngine on
854+ AllowEncodedSlashes On
855+
856+ # LXD: Recursive queries
857+ RewriteCond %{QUERY_STRING} recursion=1
858+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
859+
860+ # LXD: Normal queries
861+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
862+
863+ <Location />
864+ Require all granted
865+ </Location>
866+
867+ # LXC: Allow image listing
868+ <Location /images>
869+ Options +Indexes
870+ </Location>
871+
872+ # LXD: API root
873+ <Location /1.0/>
874+ ErrorDocument 404 /meta/lxd/404.json
875+ Options -Indexes
876+ </Location>
877+
878+ # LXD: images
879+ <Location /1.0/images/>
880+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
881+ Options +FollowSymlinks
882+ </Location>
883+
884+ # LXD: aliases
885+ <Location /1.0/images/aliases/>
886+ ErrorDocument 404 /meta/lxd/404.json
887+ </Location>
888+
889+ # LXD: downloads
890+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
891+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
892+ </LocationMatch>
893+ # Simplestreams: redirect
894+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
895+</VirtualHost>
896+
897+<VirtualHost 91.189.88.247:443 [2001:67c:1360:8001::33]:443>
898+ ServerName us.images.linuxcontainers.org
899+ CustomLog ${APACHE_LOG_DIR}/us.images.linuxcontainers.org.log vhost_combined
900+ DocumentRoot /srv/images.linuxcontainers.org/www
901+
902+ # SSL configuration
903+ SSLEngine On
904+ SSLCertificateFile /etc/ssl/certs/images.linuxcontainers.org.crt
905+ SSLCertificateKeyFile /etc/ssl/private/images.linuxcontainers.org.key
906+ SSLCertificateChainFile /etc/ssl/certs/images.linuxcontainers.org_chain.crt
907+ Header always set Strict-Transport-Security "max-age=31536000"
908+ RequestHeader set X_FORWARDED_PORT "443"
909+ RequestHeader set X_FORWARDED_PROTO "https"
910+
911+ RewriteEngine on
912+ AllowEncodedSlashes On
913+
914+ # LXD: Recursive queries
915+ RewriteCond %{QUERY_STRING} recursion=1
916+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
917+
918+ # LXD: Normal queries
919+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
920+
921+ <Location />
922+ Require all granted
923+ </Location>
924+
925+ # LXC: Allow image listing
926+ <Location /images>
927+ Options +Indexes
928+ </Location>
929+
930+ # LXD: API root
931+ <Location /1.0/>
932+ ErrorDocument 404 /meta/lxd/404.json
933+ Options -Indexes
934+ </Location>
935+
936+ # LXD: images
937+ <Location /1.0/images/>
938+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
939+ Options +FollowSymlinks
940+ </Location>
941+
942+ # LXD: aliases
943+ <Location /1.0/images/aliases/>
944+ ErrorDocument 404 /meta/lxd/404.json
945+ </Location>
946+
947+ # LXD: downloads
948+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
949+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
950+ </LocationMatch>
951+ # Simplestreams: redirect
952+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
953+</VirtualHost>
954+
955+<VirtualHost 91.189.88.247:8443 [2001:67c:1360:8001::33]:8443>
956+ ServerName images.linuxcontainers.org
957+ CustomLog ${APACHE_LOG_DIR}/images.linuxcontainers.org.log vhost_combined
958+ DocumentRoot /srv/images.linuxcontainers.org/www
959+
960+ <Location />
961+ Require all granted
962+ </Location>
963+
964+ # SSL configuration
965+ SSLEngine On
966+ SSLCertificateFile /etc/ssl/certs/images.linuxcontainers.org.crt
967+ SSLCertificateKeyFile /etc/ssl/private/images.linuxcontainers.org.key
968+ SSLCertificateChainFile /etc/ssl/certs/images.linuxcontainers.org_chain.crt
969+ Header always set Strict-Transport-Security "max-age=31536000"
970+ RequestHeader set X_FORWARDED_PORT "8443"
971+ RequestHeader set X_FORWARDED_PROTO "https"
972+
973+ RewriteEngine on
974+ AllowEncodedSlashes On
975+
976+ # GeoIP: Redirect everything to appropriate country server
977+ GeoIPEnable On
978+ GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
979+ GeoIPDBFile /usr/share/GeoIP/GeoIPv6.dat
980+
981+ # Send North America, Oceania and South America to the US server
982+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE} ^(NA|OC|SA)$
983+ RewriteRule ^/(.*)$ https://us.images.linuxcontainers.org:8443/$1 [R=301,L]
984+ RewriteCond %{ENV:GEOIP_CONTINENT_CODE_V6} ^(NA|OC|SA)$
985+ RewriteRule ^/(.*)$ https://us.images.linuxcontainers.org:8443/$1 [R=301,L]
986+
987+ # Send Africa, Antarctica, Asia, Europe, and all else to the UK server
988+ RewriteRule ^/(.*)$ https://uk.images.linuxcontainers.org:8443/$1 [R=301,L]
989+</VirtualHost>
990+
991+<VirtualHost 91.189.88.247:8443 [2001:67c:1360:8001::33]:8443>
992+ ServerName uk.images.linuxcontainers.org
993+ CustomLog ${APACHE_LOG_DIR}/uk.images.linuxcontainers.org.log vhost_combined
994+ DocumentRoot /srv/images.linuxcontainers.org/www
995+
996+ # SSL configuration
997+ SSLEngine On
998+ SSLCertificateFile /etc/ssl/certs/images.linuxcontainers.org.crt
999+ SSLCertificateKeyFile /etc/ssl/private/images.linuxcontainers.org.key
1000+ SSLCertificateChainFile /etc/ssl/certs/images.linuxcontainers.org_chain.crt
1001+ Header always set Strict-Transport-Security "max-age=31536000"
1002+ RequestHeader set X_FORWARDED_PORT "8443"
1003+ RequestHeader set X_FORWARDED_PROTO "https"
1004+
1005+ RewriteEngine on
1006+ AllowEncodedSlashes On
1007+
1008+ # LXD: Recursive queries
1009+ RewriteCond %{QUERY_STRING} recursion=1
1010+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
1011+
1012+ # LXD: Normal queries
1013+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
1014+
1015+ <Location />
1016+ Require all granted
1017+ </Location>
1018+
1019+ # LXC: Allow image listing
1020+ <Location /images>
1021+ Options +Indexes
1022+ </Location>
1023+
1024+ # LXD: API root
1025+ <Location /1.0/>
1026+ ErrorDocument 404 /meta/lxd/404.json
1027+ Options -Indexes
1028+ </Location>
1029+
1030+ # LXD: images
1031+ <Location /1.0/images/>
1032+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
1033+ Options +FollowSymlinks
1034+ </Location>
1035+
1036+ # LXD: aliases
1037+ <Location /1.0/images/aliases/>
1038+ ErrorDocument 404 /meta/lxd/404.json
1039+ </Location>
1040+
1041+ # LXD: downloads
1042+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
1043+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
1044+ </LocationMatch>
1045+ # Simplestreams: redirect
1046+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
1047+</VirtualHost>
1048+
1049+<VirtualHost 91.189.88.247:8443 [2001:67c:1360:8001::33]:8443>
1050+ ServerName us.images.linuxcontainers.org
1051+ CustomLog ${APACHE_LOG_DIR}/us.images.linuxcontainers.org.log vhost_combined
1052+ DocumentRoot /srv/images.linuxcontainers.org/www
1053+
1054+ # SSL configuration
1055+ SSLEngine On
1056+ SSLCertificateFile /etc/ssl/certs/images.linuxcontainers.org.crt
1057+ SSLCertificateKeyFile /etc/ssl/private/images.linuxcontainers.org.key
1058+ SSLCertificateChainFile /etc/ssl/certs/images.linuxcontainers.org_chain.crt
1059+ Header always set Strict-Transport-Security "max-age=31536000"
1060+ RequestHeader set X_FORWARDED_PORT "8443"
1061+ RequestHeader set X_FORWARDED_PROTO "https"
1062+
1063+ RewriteEngine on
1064+ AllowEncodedSlashes On
1065+
1066+ # LXD: Recursive queries
1067+ RewriteCond %{QUERY_STRING} recursion=1
1068+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
1069+
1070+ # LXD: Normal queries
1071+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
1072+
1073+ <Location />
1074+ Require all granted
1075+ </Location>
1076+
1077+ # LXC: Allow image listing
1078+ <Location /images>
1079+ Options +Indexes
1080+ </Location>
1081+
1082+ # LXD: API root
1083+ <Location /1.0/>
1084+ ErrorDocument 404 /meta/lxd/404.json
1085+ Options -Indexes
1086+ </Location>
1087+
1088+ # LXD: images
1089+ <Location /1.0/images/>
1090+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
1091+ Options +FollowSymlinks
1092+ </Location>
1093+
1094+ # LXD: aliases
1095+ <Location /1.0/images/aliases/>
1096+ ErrorDocument 404 /meta/lxd/404.json
1097+ </Location>
1098+
1099+ # LXD: downloads
1100+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
1101+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
1102+ </LocationMatch>
1103+ # Simplestreams: redirect
1104+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
1105+</VirtualHost>
1106+
1107diff --git a/tests/unit/testdata/linuxcontainers/thirdparty.txt b/tests/unit/testdata/linuxcontainers/thirdparty.txt
1108new file mode 100644
1109index 0000000..0b1e58d
1110--- /dev/null
1111+++ b/tests/unit/testdata/linuxcontainers/thirdparty.txt
1112@@ -0,0 +1,119 @@
1113+<VirtualHost *:80>
1114+ ServerName lxd.example.net
1115+ ServerAlias uk.lxd.example.net
1116+ ServerAlias us.lxd.example.net
1117+ CustomLog ${APACHE_LOG_DIR}/lxd.example.net.log vhost_combined
1118+ DocumentRoot /srv/lxd.example.net/www
1119+
1120+ <Location />
1121+ Require all granted
1122+ </Location>
1123+
1124+ RewriteEngine on
1125+ AllowEncodedSlashes On
1126+
1127+ # LXD: Recursive queries
1128+ RewriteCond %{QUERY_STRING} recursion=1
1129+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
1130+
1131+ # LXD: Normal queries
1132+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
1133+
1134+ <Location />
1135+ Require all granted
1136+ </Location>
1137+
1138+ # LXC: Allow image listing
1139+ <Location /images>
1140+ Options +Indexes
1141+ </Location>
1142+
1143+ # LXD: API root
1144+ <Location /1.0/>
1145+ ErrorDocument 404 /meta/lxd/404.json
1146+ Options -Indexes
1147+ </Location>
1148+
1149+ # LXD: images
1150+ <Location /1.0/images/>
1151+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
1152+ Options +FollowSymlinks
1153+ </Location>
1154+
1155+ # LXD: aliases
1156+ <Location /1.0/images/aliases/>
1157+ ErrorDocument 404 /meta/lxd/404.json
1158+ </Location>
1159+
1160+ # LXD: downloads
1161+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
1162+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
1163+ </LocationMatch>
1164+ # Simplestreams: redirect
1165+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
1166+</VirtualHost>
1167+
1168+<VirtualHost *:443>
1169+ ServerName lxd.example.net
1170+ ServerAlias uk.lxd.example.net
1171+ ServerAlias us.lxd.example.net
1172+ CustomLog ${APACHE_LOG_DIR}/lxd.example.net.log vhost_combined
1173+ DocumentRoot /srv/lxd.example.net/www
1174+
1175+ <Location />
1176+ Require all granted
1177+ </Location>
1178+
1179+ # SSL configuration
1180+ SSLEngine On
1181+ SSLCertificateFile /etc/ssl/certs/lxd.example.net.crt
1182+ SSLCertificateKeyFile /etc/ssl/private/lxd.example.net.key
1183+ SSLCertificateChainFile /etc/ssl/certs/lxd.example.net_chain.crt
1184+ Header always set Strict-Transport-Security "max-age=31536000"
1185+ RequestHeader set X_FORWARDED_PORT "443"
1186+ RequestHeader set X_FORWARDED_PROTO "https"
1187+
1188+ RewriteEngine on
1189+ AllowEncodedSlashes On
1190+
1191+ # LXD: Recursive queries
1192+ RewriteCond %{QUERY_STRING} recursion=1
1193+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index-rec.json [L]
1194+
1195+ # LXD: Normal queries
1196+ RewriteRule ^/1.0.*$ /meta/lxd%{REQUEST_URI}/index.json [L]
1197+
1198+ <Location />
1199+ Require all granted
1200+ </Location>
1201+
1202+ # LXC: Allow image listing
1203+ <Location /images>
1204+ Options +Indexes
1205+ </Location>
1206+
1207+ # LXD: API root
1208+ <Location /1.0/>
1209+ ErrorDocument 404 /meta/lxd/404.json
1210+ Options -Indexes
1211+ </Location>
1212+
1213+ # LXD: images
1214+ <Location /1.0/images/>
1215+ ErrorDocument 404 /meta/lxd/1.0/images/404.json
1216+ Options +FollowSymlinks
1217+ </Location>
1218+
1219+ # LXD: aliases
1220+ <Location /1.0/images/aliases/>
1221+ ErrorDocument 404 /meta/lxd/404.json
1222+ </Location>
1223+
1224+ # LXD: downloads
1225+ <LocationMatch "^/1.0/images/[0-9a-f]*/export">
1226+ Header set Content-Type "multipart/form-data; boundary=f012e447-25dd-4f6d-8a14-105c3b27a768"
1227+ </LocationMatch>
1228+ # Simplestreams: redirect
1229+ RewriteRule ^/streams(.*)$ /meta/simplestreams$1 [L]
1230+</VirtualHost>
1231+

Subscribers

People subscribed via source and target branches