Commit 1c30186f authored by Rafael Monnerat's avatar Rafael Monnerat

Update Release Candidate

parents a61a1add 9af029ea
[buildout]
extends =
../../component/golang/buildout.cfg
gowork.cfg
parts =
gowork
caddy
[gowork]
install =
github.com/mholt/caddy
[caddy]
recipe = slapos.recipe.cmmi
path = ${go_github.com_mholt_caddy:location}
go = ${gowork:golang}/bin/go
configure-command = :
make-targets =
make-binary = cd ${:path}/caddy && ${:go} install -v
environment =
PATH=${pkgconfig:location}/bin:${gowork:golang}/bin:${buildout:bin-directory}:%(PATH)s
GOPATH=${gowork:directory}
output = ${gowork:bin}/caddy
......@@ -10,4 +10,4 @@ depends_gitfetch =
<= go-git-package
go.importpath = github.com/mholt/caddy
repository = https://github.com/mholt/caddy
revision = v0.10.11-0-gd3f338ddab
revision = v0.11.0-11-ge263566673
[buildout]
parts = embulk
[embulk]
recipe = slapos.recipe.build:download
url = https://dl.bintray.com/embulk/maven/embulk-0.9.7.jar
md5sum = 05f41d3750ec359fc10c1dc3e30f238e
filename = embulk.jar
[libmaxminddb]
recipe = slapos.recipe.cmmi
location = ${buildout:parts-directory}/${:_buildout_section_name_}
url = https://github.com/maxmind/libmaxminddb/releases/download/${:version}/libmaxminddb-${:version}.tar.gz
version = 1.3.2
md5sum = 67a861965b30d045bf29a2126bcc05ed
[maxminddb-python]
recipe = zc.recipe.egg:custom
egg = maxminddb
include-dirs =
${libmaxminddb:location}/include
library-dirs =
${libmaxminddb:location}/lib
rpath = ${:library-dirs}
[geolite2-country]
recipe = slapos.recipe.build:download-unpacked
url = http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
md5sum = 17ee7db01dc5ac73a09e2009f9e5ed04
strip-top-level-dir = true
......@@ -28,13 +28,11 @@ parts =
[mariadb]
recipe = slapos.recipe.cmmi
url = https://downloads.mariadb.org/f/mariadb-${:version}/source/mariadb-${:version}.tar.gz/from/http%3A//fr.mirror.babylon.network/mariadb/?serve
version = 10.1.33
md5sum = 164e4cbcfe4c6be235a133de91f866af
version = 10.1.34
md5sum = 2fc6c7809be74e9e7718e8863df26b2b
patch-options = -p0
patches =
${:_profile_base_location_}/mariadb_10.1.21_create_system_tables__no_test.patch#3c76aa9564a162f13aced7c0a3f783b3
${:stable-patches}
stable-patches =
location = ${buildout:parts-directory}/${:_buildout_section_name_}
configure-command = ${cmake:location}/bin/cmake
configure-options =
......
# 33_scripts__mysql_create_system_tables__no_test.dpatch by <ch@debian.org>
A user with no password prevents a normal user from login under certain
circumstances as it is checked first.
See http://bugs.debian.org/301741
and http://bugs.mysql.com/bug.php?id=6901
--- scripts/mysql_system_tables_data.sql.orig 2018-06-25 11:13:26.000000000 +0000
+++ scripts/mysql_system_tables_data.sql 2018-06-29 10:50:42.032343572 +0000
@@ -30,8 +30,6 @@
-- Fill "db" table with default grants for anyone to
-- access database 'test' and 'test_%' if "db" table didn't exist
CREATE TEMPORARY TABLE tmp_db LIKE db;
-INSERT INTO tmp_db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');
-INSERT INTO tmp_db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y');
INSERT INTO db SELECT * FROM tmp_db WHERE @had_db_table=0;
DROP TABLE tmp_db;
@@ -51,9 +49,6 @@
IF @auth_root_socket is not null THEN
IF not exists(select 1 from information_schema.plugins where plugin_name='unix_socket') THEN
INSTALL SONAME 'auth_socket'; END IF; END IF;
--- Anonymous user with no privileges.
-INSERT INTO tmp_user_anonymous (host,user) VALUES ('localhost','');
-INSERT INTO tmp_user_anonymous (host,user) SELECT @current_hostname,'' FROM dual WHERE @current_hostname != 'localhost';
INSERT INTO user SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @skip_auth_root_nopasswd IS NULL;
INSERT INTO user SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL;
# Do not extend any file that touch buildout:parts.
[mariadb]
version = 10.2.14
md5sum = d98cce6f3c0e2971afa061fc67183b91
stable-patches =
version = 10.2.16
md5sum = 234156a94f8ea6cff92c4751880b8316
patches =
${:_profile_base_location_}/mariadb_10.2.16_create_system_tables__no_test.patch#3fd5f9febabdb42d4b6653969a0194f9
configure-options +=
-DCMAKE_C_COMPILER=${gcc:location}/bin/gcc
-DCMAKE_CXX_COMPILER=${gcc:location}/bin/g++
......
......@@ -10,8 +10,9 @@ parts =
[openvpn]
recipe = slapos.recipe.cmmi
url = https://swupdate.openvpn.org/community/releases/openvpn-2.3.14.tar.xz
md5sum = 70fc1e9c74ba2e6d7f7e320313dc3a7b
url = https://swupdate.openvpn.org/community/releases/openvpn-${:version}.tar.xz
version = 2.3.18
md5sum = 844ec9c64aae62051478784b8562f881
configure-options =
--disable-dependency-tracking
--disable-plugin-auth-pam
......
......@@ -19,8 +19,8 @@ extends =
[kvm]
recipe = slapos.recipe.cmmi
# qemu-kvm and qemu are now the same since 1.3.
url = http://wiki.qemu-project.org/download/qemu-2.11.0.tar.bz2
md5sum = 335994a755bc655e88a87aeb36bfc0b9
url = http://wiki.qemu-project.org/download/qemu-2.12.0.tar.xz
md5sum = ca553eb04c933f58111c304452fc4cc5
configure-options =
--target-list="$(uname -m 2>/dev/null|sed 's,^i[456]86$,i386,')-softmmu"
--enable-system
......
[buildout]
extends =
../babeld/buildout.cfg
../geoip2/buildout.cfg
../openvpn/buildout.cfg
../python-cryptography/buildout.cfg
......@@ -10,13 +11,15 @@ parts =
[re6stnet]
recipe = zc.recipe.egg
eggs =
${maxminddb-python:egg}
${python-cffi:egg}
${python-cryptography:egg}
pyOpenSSL
re6stnet
re6stnet[geoip]
# Note: For now original PATH is appended to the end, as not all tools are
# provided by SlapOS
initialization =
import os
os.environ['PATH'] = "${openvpn:location}/sbin:${babeld:location}/bin:${openssl:location}/bin:${python2.7:location}/bin:" + os.environ.get('PATH', '/bin:/sbin:/usr/bin/:/usr/local/sbin')
os.environ['GEOIP2_MMDB'] = "${geolite2-country:location}/GeoLite2-Country.mmdb"
os.environ['PATH'] = "${openvpn:location}/sbin:${babeld:location}/bin:${openssl:location}/bin:${python2.7:location}/bin:" + os.environ.get('PATH', '/usr/sbin:/usr/bin:/sbin:/bin')
......@@ -5,7 +5,7 @@ parts =
[zstd]
recipe = slapos.recipe.cmmi
location = ${buildout:parts-directory}/${:_buildout_section_name_}
url = https://github.com/facebook/zstd/archive/v1.3.4.tar.gz
md5sum = 10bf0353e3dedd8bae34a188c25d4261
url = https://github.com/facebook/zstd/archive/v1.3.5.tar.gz
md5sum = d2fc97be4852d666f086282053c02319
configure-command = :
make-options = PREFIX=${:location}
......@@ -101,7 +101,6 @@ setup(name=name,
'duplicity = slapos.recipe.duplicity:Recipe',
'equeue = slapos.recipe.equeue:Recipe',
'erp5.promise = slapos.recipe.erp5_promise:Recipe',
'erp5.test = slapos.recipe.erp5_test:Recipe',
'erp5scalabilitytestbed = slapos.recipe.erp5scalabilitytestbed:Recipe',
'erp5testnode = slapos.recipe.erp5testnode:Recipe',
'firefox = slapos.recipe.firefox:Recipe',
......
......@@ -25,74 +25,10 @@
#
##############################################################################
from slapos.recipe.librecipe import GenericBaseRecipe
import urlparse
# The follow recipes should be unified somehow in order to improve
# code mantainence.
class Recipe(GenericBaseRecipe):
def install(self):
testinstance = self.options['test-instance-path']
mysql_connection_string_list = []
path_list = []
# XXX: assume existence of 100 test databases, because slaves are not
# functional yet in slapos: testdb_0...testdb_100, with testuser_N
mysql_template = "%s@%s:%s %s %s"
mysql_url_list = self.options.get('mysql-url-list')
if mysql_url_list is None:
mysql_parsed = urlparse.urlparse(self.options['mysql-url'])
for i in range(0, 100):
mysql_connection_string_list.append(mysql_template % ('testdb_%s'% i,
mysql_parsed.hostname, mysql_parsed.port, 'testuser_%s'% i, mysql_parsed.password))
mysql_connection_string = mysql_template % ('erp5_test', mysql_parsed.hostname,
mysql_parsed.port, 'erp5_test', mysql_parsed.password)
else:
for mysql_url in mysql_url_list:
mysql_parsed = urlparse.urlparse(mysql_url)
mysql_connection_string_list.append(mysql_template % (
mysql_parsed.path.lstrip('/'),
mysql_parsed.hostname,
mysql_parsed.port,
mysql_parsed.username,
mysql_parsed.password,
))
mysql_connection_string = mysql_connection_string_list.pop()
cloudooo_url = self.options['cloudooo-url']
cloudooo_parsed = urlparse.urlparse(cloudooo_url)
memcached_parsed = urlparse.urlparse(self.options['memcached-url'])
kumofs_parsed = urlparse.urlparse(self.options['kumofs-url'])
common_dict = dict(
instance_home=testinstance,
prepend_path=self.options['prepend-path'],
openssl_binary=self.options['openssl-binary'],
test_ca_path=self.options['certificate-authority-path'],
)
common_list = (
'--conversion_server_url=' + cloudooo_url,
'--conversion_server_retry_count=%s' % self.options.get('cloudooo-retry-count', 2),
# BBB: We still have test suites that only accept the following 2 options.
'--conversion_server_hostname=%s' % cloudooo_parsed.hostname,
'--conversion_server_port=%s' % cloudooo_parsed.port,
'--volatile_memcached_server_hostname=%s' % memcached_parsed.hostname,
'--volatile_memcached_server_port=%s' % memcached_parsed.port,
'--persistent_memcached_server_hostname=%s' % kumofs_parsed.hostname,
'--persistent_memcached_server_port=%s' % kumofs_parsed.port,
)
path_list.append(self.createPythonScript(self.options['run-unit-test'],
__name__ + '.test.runUnitTest',
((self.options['run-unit-test-binary'],
'--erp5_sql_connection_string', mysql_connection_string,
'--extra_sql_connection_string_list', ','.join(
mysql_connection_string_list),
) + common_list, common_dict)))
path_list.append(self.createPythonScript(self.options['run-test-suite'],
__name__ + '.test.runTestSuite',
((self.options['run-test-suite-binary'],
'--db_list', ','.join(mysql_connection_string_list),
) + common_list, common_dict)))
return path_list
class CloudoooRecipe(GenericBaseRecipe):
def install(self):
path_list = []
......
......@@ -18,7 +18,7 @@ md5sum = f686f765e55d1dce2e55a400f0714b3e
[template-apache-frontend]
filename = instance-apache-frontend.cfg
md5sum = d6570c7a7e3c48efa7305677fe7c7ceb
md5sum = 274788ae9701ee1aabe26d1237f174e7
[template-apache-replicate]
filename = instance-apache-replicate.cfg.in
......
......@@ -15,6 +15,7 @@ parts =
frontend-nginx-graceful
dynamic-template-default-vh
not-found-html
port-redirection
promise-frontend-apache-configuration
promise-apache-frontend-v4-https
promise-apache-frontend-v4-http
......@@ -758,3 +759,13 @@ port = $${instance-parameter:configuration.plain_nginx_port}
recipe = slapos.cookbook:wrapper
command-line = ${buildout:bin-directory}/is-process-older-than-dependency-set $${nginx-configuration:pid-file}
wrapper-path = $${directory:promise}/promise-nginx-is-process-older-than-dependency-set
[port-redirection]
<= jinja2-template-base
template = inline:
[{"srcPort": 80, "destPort": {{ http_port }}}, {"srcPort": 443, "destPort": {{ https_port }}}]
rendered = $${buildout:directory}/.slapos-port-redirect
mode = 0644
extra-context =
key http_port instance-parameter:configuration.plain_http_port
key https_port instance-parameter:configuration.port
==============
Caddy Frontend
==============
Frontend system using Caddy, based on apache-frontend software release, allowing to rewrite and proxy URLs like myinstance.myfrontenddomainname.com to real IP/URL of myinstance.
Caddy Frontend works using the master instance / slave instance design. It means that a single main instance of Caddy will be used to act as frontend for many slaves.
Software type
=============
Caddy frontend is available in 4 software types:
* ``default`` : The standard way to use the Caddy frontend configuring everything with a few given parameters
* ``custom-personal`` : This software type allow each slave to edit its Caddy configuration file
* ``default-slave`` : XXX
* ``custom-personal-slave`` : XXX
About frontend replication
==========================
Slaves of the root instance are sent as a parameter to requested frontends which will process them. The only difference is that they will then return the would-be published information to the root instance instead of publishing it. The root instance will then do a synthesis and publish the information to its slaves. The replicate instance only use 5 type of parameters for itself and will transmit the rest to requested frontends.
These parameters are :
* ``-frontend-type`` : the type to deploy frontends with. (default to 2)
* ``-frontend-quantity`` : The quantity of frontends to request (default to "default")
* ``-frontend-i-state``: The state of frontend i
* ``-frontend-config-i-foo``: Frontend i will be requested with parameter foo
* ``-frontend-software-release-url``: Software release to be used for frontends, default to the current software release
* ``-sla-i-foo`` : where "i" is the number of the concerned frontend (between 1 and "-frontend-quantity") and "foo" a sla parameter.
ex::
<parameter id="-frontend-quantity">3</parameter>
<parameter id="-frontend-type">custom-personal</parameter>
<parameter id="-frontend-2-state">stopped</parameter>
<parameter id="-sla-3-computer_guid">COMP-1234</parameter>
<parameter id="-frontend-software-release-url">https://lab.nexedi.com/nexedi/slapos/raw/someid/software/caddy-frontend/software.cfg</parameter>
will request the third frontend on COMP-1234. All frontends will be of software type ``custom-personal``. The second frontend will be requested with the state stopped
*Note*: the way slaves are transformed to a parameter avoid modifying more than 3 lines in the frontend logic.
**Important NOTE**: The way you ask for slave to a replicate frontend is the same as the one you would use for the software given in "-frontend-quantity". Do not forget to use "replicate" for software type. XXXXX So far it is not possible to do a simple request on a replicate frontend if you do not know the software_guid or other sla-parameter of the master instance. In fact we do not know yet the software type of the "requested" frontends. TO BE IMPLEMENTED
XXX Should be moved to specific JSON File
Extra-parameter per frontend with default::
ram-cache-size = 1G
disk-cache-size = 8G
How to deploy a frontend server
===============================
This is to deploy an entire frontend server with a public IPv4. If you want to use an already deployed frontend to make your service available via ipv4, switch to the "Example" parts.
First, you will need to request a "master" instance of Caddy Frontend with:
* A ``domain`` parameter where the frontend will be available
* A ``public-ipv4`` parameter to state which public IPv4 will be used
like::
<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="domain">moulefrite.org</parameter>
<parameter id="public-ipv4">xxx.xxx.xxx.xxx</parameter>
</instance>
Then, it is possible to request many slave instances (currently only from slapconsole, UI doesn't work yet) of Caddy Frontend, like::
instance = request(
software_release=caddy_frontend,
partition_reference='frontend2',
shared=True,
partition_parameter_kw={"url":"https://[1:2:3:4]:1234/someresource"}
)
Those slave instances will be redirected to the "master" instance, and you will see on the "master" instance the associated proper directives of all slave instances.
Finally, the slave instance will be accessible from: https://someidentifier.moulefrite.org.
About SSL
=========
``default`` and ``custom-personl`` software type can handle specific ssl for one slave instance.
**IMPORTANT**: One Caddy can not serve more than one specific SSL site and be compatible with obsolete browser (i.e.: IE8). See http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI
How to have custom configuration in frontend server - XXX - to be written
=========================================================================
In your instance directory, you, as sysadmin, can directly edit two
configuration files that won't be overwritten by SlapOS to customize your
instance:
* ``$PARTITION_PATH/srv/srv/apache-conf.d/apache_frontend.custom.conf``
* ``$PARTITION_PATH/srv/srv/apache-conf.d/apache_frontend.virtualhost.custom.conf``
The first one is included in the end of the main apache configuration file.
The second one is included in the virtualhost of the main apache configuration file.
SlapOS will just create those two files for you, then completely forget them.
*Note*: make sure that the UNIX user of the instance has read access to those
files if you edit them.
Instance Parameters
===================
Master Instance Parameters
--------------------------
The parameters for instances are described at `instance-caddy-input-schema.json <instance-caddy-input-schema.json>`_.
Here some additional informations about the parameters listed, below:
domain
~~~~~~
Name of the domain to be used (example: mydomain.com). Sub domains of this domain will be used for the slave instances (example: instance12345.mydomain.com). It is then recommended to add a wild card in DNS for the sub domains of the chosen domain like::
*.mydomain.com. IN A 123.123.123.123
Using the IP given by the Master Instance. "domain" is a mandatory Parameter.
public-ipv4
~~~~~~~~~~~
Public ipv4 of the frontend (the one Caddy will be indirectly listening to)
port
~~~~
Port used by Caddy. Optional parameter, defaults to 4443.
plain_http_port
~~~~~~~~~~~~~~~
Port used by Caddy to serve plain http (only used to redirect to https).
Optional parameter, defaults to 8080.
Slave Instance Parameters
-------------------------
The parameters for instances are described at `instance-slave-caddy-input-schema.json <instance-slave-caddy-input-schema.json>`_.
Here some additional informations about the parameters listed, below:
path
~~~~
Only used if type is "zope".
Will append the specified path to the "VirtualHostRoot" of the zope's VirtualHostMonster.
"path" is an optional parameter, ignored if not specified.
Example of value: "/erp5/web_site_module/hosting/"
apache_custom_https
~~~~~~~~~~~~~~~~~~~
Raw Caddy configuration in python template format (i.e. write "%%" for one "%") for the slave listening to the https port. Its content will be templatified in order to access functionalities such as cache access, ssl certificates... The list is available above.
apache_custom_http
~~~~~~~~~~~~~~~~~~
Raw Caddy configuration in python template format (i.e. write "%%" for one "%") for the slave listening to the http port. Its content will be templatified in order to access functionalities such as cache access, ssl certificates... The list is available above
url
~~~
Necessary to activate cache. ``url`` of backend to use.
``url`` is an optional parameter.
Example: http://mybackend.com/myresource
domain
~~~~~~
Necessary to activate cache.
The frontend will be accessible from this domain.
``domain`` is an optional parameter.
Example: www.mycustomdomain.com
enable_cache
~~~~~~~~~~~~
Necessary to activate cache.
``enable_cache`` is an optional parameter.
ssl_key, ssl_crt, ssl_ca_crt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SSL certificates of the slave.
They are optional.
Functionalities for Caddy configuration
---------------------------------------
In the slave Caddy configuration you can use parameters that will be replaced during instantiation. They should be entered as python templates parameters ex: ``%(parameter)s``:
* ``cache_access`` : url of the cache. Should replace backend url in configuration to use the cache
* ``access_log`` : path of the slave error log in order to log in a file.
* ``error_log`` : path of the slave access log in order to log in a file.
* ``ssl_key``, ``ssl_crt``, ``ssl_ca_crt``, ``ssl_crs`` : paths of the certificates given in slave instance parameters
Examples
========
Here are some example of how to make your SlapOS service available through an already deployed frontend.
Simple Example (default)
------------------------
Request slave frontend instance so that https://[1:2:3:4:5:6:7:8]:1234 will be
redirected and accessible from the proxy::
instance = request(
software_release=caddy_frontend,
software_type="RootSoftwareInstance",
partition_reference='my frontend',
shared=True,
partition_parameter_kw={
"url":"https://[1:2:3:4:5:6:7:8]:1234",
}
)
Zope Example (default)
----------------------
Request slave frontend instance using a Zope backend so that
https://[1:2:3:4:5:6:7:8]:1234 will be redirected and accessible from the
proxy::
instance = request(
software_release=caddy_frontend,
software_type="RootSoftwareInstance",
partition_reference='my frontend',
shared=True,
partition_parameter_kw={
"url":"https://[1:2:3:4:5:6:7:8]:1234",
"type":"zope",
}
)
Advanced example
-----------------
Request slave frontend instance using a Zope backend, with Varnish activated,
listening to a custom domain and redirecting to /erp5/ so that
https://[1:2:3:4:5:6:7:8]:1234/erp5/ will be redirected and accessible from
the proxy::
instance = request(
software_release=caddy_frontend,
software_type="RootSoftwareInstance",
partition_reference='my frontend',
shared=True,
partition_parameter_kw={
"url":"https://[1:2:3:4:5:6:7:8]:1234",
"enable_cache":"true",
"type":"zope",
"path":"/erp5",
"domain":"mycustomdomain.com",
}
)
Simple Example
---------------
Request slave frontend instance so that https://[1:2:3:4:5:6:7:8]:1234 will be::
instance = request(
software_release=caddy_frontend,
software_type="RootSoftwareInstance",
partition_reference='my frontend',
shared=True,
software_type="custom-personal",
partition_parameter_kw={
"url":"https://[1:2:3:4:5:6:7:8]:1234",
"apache_custom_https":'
https://www.example.com:%(https_port)s, https://example.com:%(https_port)s {
bind %(local_ipv4)s
tls %(ssl_crt)s %(ssl_key)s
log / %(access_log)s {combined}
errors %(error_log)s
proxy / https://[1:2:3:4:5:6:7:8]:1234 {
transparent
timeout 600s
insecure_skip_verify
}
}
"apache_custom_http":'
http://www.example.com:%(http_port)s, http://example.com:%(http_port)s {
bind %(local_ipv4)s
log / %(access_log)s {combined}
errors %(error_log)s
proxy / https://[1:2:3:4:5:6:7:8]:1234/ {
transparent
timeout 600s
insecure_skip_verify
}
}
Simple Cache Example - XXX - to be written
------------------------------------------
Request slave frontend instance so that https://[1:2:3:4:5:6:7:8]:1234 will be::
instance = request(
software_release=caddy_frontend,
software_type="RootSoftwareInstance",
partition_reference='my frontend',
shared=True,
software_type="custom-personal",
partition_parameter_kw={
"url":"https://[1:2:3:4:5:6:7:8]:1234",
"domain": "www.example.org",
"enable_cache": "True",
"apache_custom_https":'
ServerName www.example.org
ServerAlias www.example.org
ServerAlias example.org
ServerAdmin geronimo@example.org
SSLEngine on
SSLProxyEngine on
# Rewrite part
ProxyVia On
ProxyPreserveHost On
ProxyTimeout 600
RewriteEngine On
RewriteRule ^/(.*) %(cache_access)s/$1 [L,P]',
"apache_custom_http":'
ServerName www.example.org
ServerAlias www.example.org
ServerAlias example.org
ServerAdmin geronimo@example.org
SSLProxyEngine on
# Rewrite part
ProxyVia On
ProxyPreserveHost On
ProxyTimeout 600
RewriteEngine On
# Not using HTTPS? Ask that guy over there.
# Dummy redirection to https. Note: will work only if https listens
# on standard port (443).
RewriteRule ^/(.*) %(cache_access)s/$1 [L,P],
}
)
Advanced example - XXX - to be written
--------------------------------------
Request slave frontend instance using custom apache configuration, willing to use cache and ssl certificates.
Listening to a custom domain and redirecting to /erp5/ so that
https://[1:2:3:4:5:6:7:8]:1234/erp5/ will be redirected and accessible from
the proxy::
instance = request(
software_release=caddy_frontend,
software_type="RootSoftwareInstance",
partition_reference='my frontend',
shared=True,
software_type="custom-personal",
partition_parameter_kw={
"url":"https://[1:2:3:4:5:6:7:8]:1234",
"enable_cache":"true",
"type":"zope",
"path":"/erp5",
"domain":"example.org",
"apache_custom_https":'
ServerName www.example.org
ServerAlias www.example.org
ServerAdmin example.org
SSLEngine on
SSLProxyEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
# Use personal ssl certificates
SSLCertificateFile %(ssl_crt)s
SSLCertificateKeyFile %(ssl_key)s
SSLCACertificateFile %(ssl_ca_crt)s
SSLCertificateChainFile %(ssl_ca_crt)s
# Configure personal logs
ErrorLog "%(error_log)s"
LogLevel info
LogFormat "%%h %%l %%{REMOTE_USER}i %%t \"%%r\" %%>s %%b \"%%{Referer}i\" \"%%{User-Agent}i\" %%D" combined
CustomLog "%(access_log)s" combined
# Rewrite part
ProxyVia On
ProxyPreserveHost On
ProxyTimeout 600
RewriteEngine On
# Redirect / to /index.html
RewriteRule ^/$ /index.html [R=302,L]
# Use cache
RewriteRule ^/(.*) %(cache_access)s/VirtualHostBase/https/www.example.org:443/erp5/VirtualHostRoot/$1 [L,P]',
"apache_custom_http":'
ServerName www.example.org
ServerAlias www.example.org
ServerAlias example.org
ServerAdmin geronimo@example.org
SSLProxyEngine on
# Rewrite part
ProxyVia On
ProxyPreserveHost On
ProxyTimeout 600
RewriteEngine On
# Configure personal logs
ErrorLog "%(error_log)s"
LogLevel info
LogFormat "%%h %%l %%{REMOTE_USER}i %%t \"%%r\" %%>s %%b \"%%{Referer}i\" \"%%{User-Agent}i\" %%D" combined
CustomLog "%(access_log)s" combined
# Not using HTTPS? Ask that guy over there.
# Dummy redirection to https. Note: will work only if https listens
# on standard port (443).
RewriteRule ^/(.*)$ https://%%{SERVER_NAME}%%{REQUEST_URI}',
"ssl_key":"-----BEGIN RSA PRIVATE KEY-----
XXXXXXX..........XXXXXXXXXXXXXXX
-----END RSA PRIVATE KEY-----",
"ssl_crt":'-----BEGIN CERTIFICATE-----
XXXXXXXXXXX.............XXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----',
"ssl_ca_crt":'-----BEGIN CERTIFICATE-----
XXXXXXXXX...........XXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----',
"ssl_csr":'-----BEGIN CERTIFICATE REQUEST-----
XXXXXXXXXXXXXXX.............XXXXXXXXXXXXXXXXXX
-----END CERTIFICATE REQUEST-----',
}
)
Notes
=====
It is not possible with slapos to listen to port <= 1024, because process are
not run as root.
Solution 1 (IPv4 only)
----------------------
It is a good idea then to go on the node where the instance is
and set some ``iptables`` rules like (if using default ports)::
iptables -t nat -A PREROUTING -p tcp -d {public_ipv4} --dport 443 -j DNAT --to-destination {listening_ipv4}:4443
iptables -t nat -A PREROUTING -p tcp -d {public_ipv4} --dport 80 -j DNAT --to-destination {listening_ipv4}:8080
Where ``{public ip}`` is the public IP of your server, or at least the LAN IP to where your NAT will forward to, and ``{listening ip}`` is the private ipv4 (like 10.0.34.123) that the instance is using and sending as connection parameter.
Solution 2 (IPv6 only)
----------------------
It is also possible to directly allow the service to listen on 80 and 443 ports using the following command::
setcap 'cap_net_bind_service=+ep' /opt/slapgrid/$CADDY_FRONTEND_SOFTWARE_RELEASE_MD5/go.work/bin/caddy
Then specify in the instance parameters ``port`` and ``plain_http_port`` to be ``443`` and ``80``, respectively.
Generally things to be done with ``caddy-frontend``:
* ``apache-ca-certificate`` shall be merged with ``apache-certificate``
* (new) ``type:websocket`` slave
* ``type:eventsource``:
* **Jérome Perrin**: *For event source, if I understand https://github.com/mholt/caddy/issues/1355 correctly, we could use caddy as a proxy in front of nginx-push-stream . If we have a "central shared" caddy instance, can it handle keeping connections opens for many clients ?*
* ``ssl_ca_crt``
* ``prefer-gzip-encoding-to-backend`` (requires writing middleware plugin for Caddy)::
RequestHeader edit Accept-Encoding "(^gzip,.*|.*, gzip,.*|.*, gzip$|^gzip$)" "gzip"
* ``disabled-cookie-list`` (requires writing middleware plugin for Caddy)::
RequestHeader edit Cookie "(^%(disabled_cookie)s=[^;]*; |; %(disabled_cookie)s=[^;]*|^%(disabled_cookie)s=[^;]*$)" ""' % dict(disabled_cookie=disabled_cookie) }}
* ``ssl_proxy_ca_crt`` for ``ssl_proxy_verify``, this is related to bug https://github.com/mholt/caddy/issues/1550, proposed solution `just adding your CA to the system's trust store`
* ``check-error-on-caddy-log`` like ``check-error-on-apache-log``
* cover test suite like resilient tests for KVM and prove it works the same way as Caddy
* have ``caddy-frontend`` specific parameters, with backward compatibility to ``apache-frontend`` ones (like ``apache_custom_http`` --> ``caddy_custom_http``)
* change ``switch-softwaretype`` to way how ``software/erp5`` does, which will help with dropping jinja2 template for ``caddy-wrapper``, which is workaround for current situation https://lab.nexedi.com/nexedi/slapos/merge_requests/312#note_62678
* use `slapos!326 <https://lab.nexedi.com/nexedi/slapos/merge_requests/326>`_, and especially `note about complex restart scenarios <https://lab.nexedi.com/nexedi/slapos/merge_requests/326#note_60198>`_, instead of self-developed graceful restart scripts
* move out `test/utils.py` and use it from shared python distribution
* provide various tricks for older browsers::
# The following directives modify normal HTTP response behavior to
# handle known problems with browser implementations.
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
# The following directive disables redirects on non-GET requests for
# a directory that does not include the trailing slash. This fixes a
# problem with Microsoft WebFolders which does not appropriately handle
# redirects for folders with DAV methods.
# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "MS FrontPage" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
BrowserMatch "^gnome-vfs" redirect-carefully
BrowserMatch "^XML Spy" redirect-carefully
BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
* check, and if needed apply, Apache-like SSL configuration switches::
# SSL Configuration
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
* reduce the time of configuration validation (in ``instance-apache-frontend.cfg`` sections ``[configtest]``, ``[caddy-configuration]``, ``[nginx-configuration]``), as it is not scalable on frontend with 2000+ slaves (takes few minutes instead of few, < 5, seconds), issue posted `upstream <https://github.com/mholt/caddy/issues/2220>`_
* drop ``6tunnel`` and use ``bind`` in Caddy configuration, as soon as multiple binds will be possible, tracked in upstream `bind: support multiple values <https://github.com/mholt/caddy/pull/2128>`_ and `ipv6: does not bind on ipv4 and ipv6 for sites that resolve to both <https://github.com/mholt/caddy/issues/864>`_
Things which can't be implemented:
* use certificates valid forever in tests using `cryptography <https://pypi.org/project/cryptography/>`_, with `available example <https://lab.nexedi.com/nexedi/caucase/blob/1c9b9b6dfb062551549566d9792a1608f5e0c2d9/caucase/ca.py#L460-552>`_
* **REASON**: it is impossible to generate certificate without `Not Valid After`, even with `cryptography <https://pypi.org/project/cryptography/>`_
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[template]
filename = instance.cfg
md5sum = 906e5bd66b1265b8109a86b6ab46e91f
[template-apache-frontend]
filename = instance-apache-frontend.cfg
md5sum = 5602b4635e3da27ea6ff491824b0d8a5
[template-apache-replicate]
filename = instance-apache-replicate.cfg.in
md5sum = cd83f92b43904e1f3826072013cd682b
[template-slave-list]
filename = templates/apache-custom-slave-list.cfg.in
md5sum = 3993419eea72ad4b62c0d479860f3c17
[template-slave-configuration]
filename = templates/custom-virtualhost.conf.in
md5sum = 74275ad73b03114c69f80c8f8ae73374
[template-replicate-publish-slave-information]
filename = templates/replicate-publish-slave-information.cfg.in
md5sum = 8d318af17da5631d4242c0d6d1531066
[template-caddy-frontend-configuration]
filename = templates/Caddyfile.in
md5sum = 6689d96fc18d9aad78d77fe87770d4da
[template-custom-slave-list]
filename = templates/apache-custom-slave-list.cfg.in
md5sum = 3993419eea72ad4b62c0d479860f3c17
[template-not-found-html]
filename = templates/notfound.html
md5sum = f20d6c3d2d94fb685f8d26dfca1e822b
[template-default-slave-virtualhost]
filename = templates/default-virtualhost.conf.in
md5sum = e9eccaa99077d9bc12b538d40f5421b0
[template-cached-slave-virtualhost]
filename = templates/cached-virtualhost.conf.in
md5sum = 0e7d8df879ec363f771740d017cb7512
[template-log-access]
filename = templates/template-log-access.conf.in
md5sum = cbf492b2fd8a955b0f92eb512fe9163f
[template-empty]
filename = templates/empty.in
md5sum = c2314c3a9c3412a38d14b312d3df83c1
[template-wrapper]
filename = templates/wrapper.in
md5sum = 8cde04bfd0c0e9bd56744b988275cfd8
[template-caddy-wrapper]
filename = templates/caddy-wrapper.in
md5sum = c5816275757124613920078b6bec1caf
[template-trafficserver-records-config]
filename = templates/trafficserver/records.config.jinja2
md5sum = 84baef0a49c9a65e8f2d2ffdb8c1d39c
[template-trafficserver-storage-config]
filename = templates/trafficserver/storage.config.jinja2
md5sum = 117238225b3fc3c5b5be381815f44c67
[template-nginx-configuration]
filename = templates/nginx.cfg.in
md5sum = fadb2fcaf0f2b4fe735617fac222f7ed
[template-nginx-eventsource-slave-virtualhost]
filename = templates/nginx-eventsource-slave.conf.in
md5sum = 69d65e461cd7cd5ef5b1ccd0098b50c8
[template-nginx-notebook-slave-virtualhost]
filename = templates/nginx-notebook-slave.conf.in
md5sum = 21a102ac2ee98f9a7f168fa0a1390068
[template-apache-lazy-script-call]
filename = templates/apache-lazy-script-call.sh.in
md5sum = ebe5d3d19923eb812a40019cb11276d8
[template-caddy-graceful-script]
filename = templates/caddy-graceful-script.sh.in
md5sum = 455f8765a3afd39fb78562fb9e326c42
[buildout]
extends =
buildout.hash.cfg
../../stack/slapos.cfg
../../component/dash/buildout.cfg
../../component/caddy/buildout.cfg
../../component/gzip/buildout.cfg
../../component/dcron/buildout.cfg
../../component/logrotate/buildout.cfg
../../component/rdiff-backup/buildout.cfg
../../component/trafficserver/buildout.cfg
../../component/6tunnel/buildout.cfg
../../stack/nodejs.cfg
# Monitoring stack (keep on bottom)
../../stack/monitor/buildout.cfg
parts +=
template
template-caddy-frontend
template-caddy-replicate
caddy
dcron
logrotate
rdiff-backup
npm-modules
proxy-by-url
http-proxy
# Extent extra-eggs.
[extra-eggs]
eggs +=
websockify
erp5.util
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg
output = ${buildout:directory}/template.cfg
mode = 0644
[template-caddy-frontend]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-apache-frontend.cfg
output = ${buildout:directory}/template-caddy-frontend.cfg
mode = 0644
[template-caddy-replicate]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/instance-apache-replicate.cfg.in
mode = 0644
[download-template]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/${:filename}
mode = 640
[template-slave-list]
<=download-template
filename = apache-custom-slave-list.cfg.in
[template-slave-configuration]
<=download-template
filename = custom-virtualhost.conf.in
[template-replicate-publish-slave-information]
<=download-template
filename = replicate-publish-slave-information.cfg.in
[template-caddy-frontend-configuration]
<=download-template
filename = Caddyfile.in
[template-custom-slave-list]
<=download-template
filename = caddy-default-slave-list.cfg.in
[template-not-found-html]
<=download-template
filename = notfound.html
[template-default-slave-virtualhost]
<=download-template
filename = default-virtualhost.conf.in
[template-cached-slave-virtualhost]
<=download-template
filename = cached-virtualhost.conf.in
[template-log-access]
<=download-template
filename = template-log-access.conf.in
[template-empty]
<=download-template
filename = empty.in
[template-caddy-wrapper]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/templates/caddy-wrapper.in
output = ${buildout:directory}/template-caddy-wrapper.cfg
mode = 0644
[template-wrapper]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/templates/wrapper.in
output = ${buildout:directory}/template-wrapper.cfg
mode = 0644
[template-trafficserver-records-config]
recipe = hexagonit.recipe.download
ignore-existing = true
url = ${:_profile_base_location_}/templates/trafficserver/${:filename}
location = ${buildout:parts-directory}/${:_buildout_section_name_}
filename = records.config.jinja2
download-only = true
mode = 0644
[template-trafficserver-storage-config]
recipe = hexagonit.recipe.download
ignore-existing = true
url = ${:_profile_base_location_}/templates/trafficserver/${:filename}
location = ${buildout:parts-directory}/${:_buildout_section_name_}
filename = storage.config.jinja2
download-only = true
mode = 0644
# NGINX Configuration
[template-nginx-configuration]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/templates/nginx.cfg.in
output = ${buildout:directory}/template-nginx.cfg.in
mode = 0644
[template-caddy-lazy-script-call]
<=download-template
filename = apache-lazy-script-call.sh.in
[template-caddy-graceful-script]
<=download-template
filename = caddy-graceful-script.sh.in
[template-nginx-eventsource-slave-virtualhost]
<=download-template
filename = nginx-eventsource-slave.conf.in
[template-nginx-notebook-slave-virtualhost]
<=download-template
filename = nginx-notebook-slave.conf.in
# Migrated from KVM recipe
[http-proxy]
# https://github.com/nodejitsu/node-http-proxy
recipe = slapos.recipe.build:download-unpacked
# use upstream when merged
url = https://lab.nexedi.com/nexedi/node-http-proxy/repository/archive.zip?ref=a5d3aff428ee8d840068b439f6ce121077f1144f
md5sum = 65602466066444c718215de41f546585
[proxy-by-url]
# https://github.com/dominictarr/proxy-by-url
recipe = slapos.recipe.build:download-unpacked
# use upstream when merged
url = https://lab.nexedi.com/nexedi/proxy-by-url/repository/archive.zip?ref=59fcb11a3e00c45b4b0362e76f29653abb313072
md5sum = c383e0c5ff31b56f7987466e8304c941
[npm-modules]
recipe = plone.recipe.command
destination = ${buildout:parts-directory}/${:_buildout_section_name_}
location = ${buildout:parts-directory}/${:_buildout_section_name_}
command =
export HOME=${:location};
rm -fr ${:destination} &&
mkdir -p ${:destination} &&
cd ${:destination} &&
${nodejs:location}/bin/node ${nodejs:location}/bin/npm install colors@0.6.0-1 &&
${nodejs:location}/bin/node ${nodejs:location}/bin/npm install socket.io@0.8.7 &&
${nodejs:location}/bin/node ${nodejs:location}/bin/npm install socket.io-client@0.8.7 &&
${nodejs:location}/bin/node ${nodejs:location}/bin/npm install optimist@0.3.1 &&
${nodejs:location}/bin/node ${nodejs:location}/bin/npm install pkginfo@0.2.3
# Development profile of caddy-frontend.
# Exactly the same as software.cfg, but fetch the slapos.cookbook
# from git repository instead of fetching stable version,
# allowing to play with bleeding edge environment.
# You'll need to run buildout twice for this profile.
[buildout]
extends =
# Extend in this order, otherwise "parts" will be taken from git profile
common.cfg
parts +=
slapos.toolbox-dev
[slapos.toolbox-dev]
recipe = zc.recipe.egg:develop
egg = slapos.toolbox
setup = ${slapos.toolbox-repository:location}
[buildout]
parts =
directory
configtest
logrotate
cron
cron-entry-logrotate
ca-frontend
certificate-authority
logrotate-entry-caddy
logrotate-entry-nginx
caddy-frontend
switch-caddy-softwaretype
frontend-caddy-graceful
frontend-nginx-graceful
not-found-html
port-redirection
promise-frontend-caddy-configuration
promise-caddy-frontend-v4-https
promise-caddy-frontend-v4-http
promise-caddy-frontend-v6-https
promise-caddy-frontend-v6-http
promise-caddy-frontend-cached
promise-caddy-frontend-ssl-cached
promise-caddy-is-process-older-than-dependency-set
promise-nginx-frontend-v4-https
promise-nginx-frontend-v4-http
promise-nginx-frontend-v6-https
promise-nginx-frontend-v6-http
promise-nginx-configuration
promise-nginx-is-process-older-than-dependency-set
trafficserver-launcher
trafficserver-reload
trafficserver-configuration-directory
trafficserver-records-config
trafficserver-remap-config
trafficserver-plugin-config
trafficserver-storage-config
trafficserver-promise-listen-port
trafficserver-promise-cache-availability
## Nginx
nginx-frontend
## Monitor for Caddy
monitor-base
monitor-ats-cache-stats-wrapper
monitor-traffic-summary-last-stats-wrapper
monitor-caddy-server-status-wrapper
monitor-verify-re6st-connectivity
extends = ${monitor-template:output}
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
# Create all needed directories
[directory]
recipe = slapos.cookbook:mkdirectory
bin = $${buildout:directory}/bin/
etc = $${buildout:directory}/etc/
srv = $${buildout:directory}/srv/
var = $${buildout:directory}/var/
template = $${buildout:directory}/template/
backup = $${:srv}/backup
log = $${:var}/log
run = $${:var}/run
service = $${:etc}/service
etc-run = $${:etc}/run
promise = $${:etc}/promise
logrotate-backup = $${:backup}/logrotate
logrotate-entries = $${:etc}/logrotate.d
cron-entries = $${:etc}/cron.d
crontabs = $${:etc}/crontabs
cronstamps = $${:etc}/cronstamps
ca-dir = $${:srv}/ssl
varnginx = $${:var}/nginx
[switch-caddy-softwaretype]
recipe = slapos.cookbook:softwaretype
single-default = $${dynamic-custom-personal-template-slave-list:rendered}
single-custom-personal = $${dynamic-custom-personal-template-slave-list:rendered}
[instance-parameter]
# Fetches parameters defined in SlapOS Master for this instance.
# Always the same.
recipe = slapos.cookbook:slapconfiguration.serialised
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
# Define default parameter(s) that will be used later, in case user didn't
# specify it
# All parameters are available through the configuration.XX syntax.
# All possible parameters should have a default.
configuration.domain = example.org
configuration.public-ipv4 =
configuration.port = 4443
configuration.plain_http_port = 8080
configuration.plain_nginx_port = 8081
configuration.nginx_port = 9443
configuration.server-admin = admin@example.com
configuration.apache_custom_https = ""
configuration.apache_custom_http = ""
configuration.apache-key =
configuration.apache-certificate =
configuration.apache-ca-certificate =
configuration.open-port = 80 443
configuration.extra_slave_instance_list =
configuration.disk-cache-size = 8G
configuration.ram-cache-size = 1G
configuration.trafficserver-autoconf-port = 8083
configuration.trafficserver-mgmt-port = 8084
configuration.re6st-verification-url = http://[2001:67c:1254:4::1]/index.html
configuration.enable-http2-by-default = true
configuration.mpm-graceful-shutdown-timeout = 5
configuration.monitor-cors-domains =
configuration.monitor-httpd-port = 8072
[frontend-configuration]
template-log-access = ${template-log-access:target}
log-access-configuration = $${directory:etc}/log-access.conf
caddy-directory = ${caddy:location}
caddy-ipv6 = $${instance-parameter:ipv6-random}
caddy-https-port = $${instance-parameter:configuration.port}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = $${buildout:directory}/$${:filename}
extra-context =
context =
import json_module json
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type instance-parameter:slap-software-type
key slapparameter_dict instance-parameter:configuration
section directory directory
$${:extra-context}
[software-release-path]
template-empty = ${template-empty:target}
template-slave-configuration = ${template-slave-configuration:target}
template-default-slave-virtualhost = ${template-default-slave-virtualhost:target}
template-cached-slave-virtualhost = ${template-cached-slave-virtualhost:target}
caddy-location = ${caddy:location}
template-nginx-eventsource-slave-virtualhost = ${template-nginx-eventsource-slave-virtualhost:target}
template-nginx-notebook-slave-virtualhost = ${template-nginx-notebook-slave-virtualhost:target}
[dynamic-custom-personal-template-slave-list]
< = jinja2-template-base
template = ${template-slave-list:target}
filename = custom-personal-instance-slave-list.cfg
extensions = jinja2.ext.do
extra-context =
key caddy_configuration_directory caddy-directory:slave-configuration
key nginx_configuration_directory caddy-directory:nginx-slave-configuration
key caddy_cached_configuration_directory caddy-directory:slave-with-cache-configuration
key slave_with_cache_configuration_directory caddy-directory:slave-with-cache-configuration
key http_port instance-parameter:configuration.plain_http_port
key https_port instance-parameter:configuration.port
key nginx_http_port instance-parameter:configuration.plain_nginx_port
key nginx_https_port instance-parameter:configuration.nginx_port
key public_ipv4 instance-parameter:configuration.public-ipv4
key slave_instance_list instance-parameter:slave-instance-list
key extra_slave_instance_list instance-parameter:configuration.extra_slave_instance_list
key custom_ssl_directory caddy-directory:vh-ssl
key caddy_log_directory caddy-directory:slave-log
key local_ipv4 instance-parameter:ipv4-random
key local_ipv6 instance-parameter:ipv6-random
key global_ipv6 slap-network-information:global-ipv6
key varnginx directory:varnginx
key empty_template software-release-path:template-empty
key template_custom_slave_configuration software-release-path:template-slave-configuration
key template_default_slave_configuration software-release-path:template-default-slave-virtualhost
key template_cached_slave_configuration software-release-path:template-cached-slave-virtualhost
key template_eventsource_slave_configuration software-release-path:template-nginx-eventsource-slave-virtualhost
key template_notebook_slave_configuration software-release-path:template-nginx-notebook-slave-virtualhost
raw software_type single-custom-personal
key frontend_lazy_graceful_reload frontend-caddy-lazy-graceful:rendered
section logrotate_dict logrotate
section frontend_configuration frontend-configuration
section caddy_configuration caddy-configuration
section nginx_configuration nginx-configuration
key monitor_base_url monitor-instance-parameter:monitor-base-url
key promise_directory monitor-directory:promises
key report_directory monitor-directory:reports
raw bin_directory ${buildout:bin-directory}
key login_certificate ca-frontend:cert-file
key login_key ca-frontend:key-file
key login_ca_crt ca-custom-frontend:rendered
key enable_http2_by_default instance-parameter:configuration.enable-http2-by-default
key access_log caddy-configuration:access-log
key error_log caddy-configuration:error-log
raw sixtunnel_executable ${6tunnel:location}/bin/6tunnel
raw service_directory $${directory:service}
key not_found_file caddy-configuration:not-found-file
[dynamic-virtualhost-template-slave]
<= jinja2-template-base
template = ${template-slave-configuration:target}
rendered = $${directory:template}/slave-virtualhost.conf.in
extensions = jinja2.ext.do
extra-context =
key https_port instance-parameter:configuration.port
key http_port instance-parameter:configuration.plain_http_port
key apache_custom_https instance-parameter:configuration.apache_custom_https
key apache_custom_http instance-parameter:configuration.apache_custom_http
# Deploy Caddy Frontend with Jinja power
[dynamic-caddy-frontend-template]
< = jinja2-template-base
template = ${template-caddy-frontend-configuration:target}
rendered = $${caddy-configuration:frontend-configuration}
extra-context =
key httpd_home software-release-path:caddy-location
key httpd_mod_ssl_cache_directory caddy-directory:mod-ssl
key instance_home buildout:directory
key server_admin instance-parameter:configuration.server-admin
key login_certificate ca-frontend:cert-file
key login_key ca-frontend:key-file
key login_ca_crt ca-custom-frontend:rendered
key ca_dir certificate-authority:ca-dir
key ca_crl certificate-authority:ca-crl
key access_log caddy-configuration:access-log
key slave_configuration_directory caddy-directory:slave-configuration
key cached_port caddy-configuration:cache-through-port
key ssl_cached_port caddy-configuration:ssl-cache-through-port
key slave_with_cache_configuration_directory caddy-directory:slave-with-cache-configuration
section frontend_configuration frontend-configuration
key http_port instance-parameter:configuration.plain_http_port
key https_port instance-parameter:configuration.port
key local_ipv4 instance-parameter:ipv4-random
key global_ipv6 slap-network-information:global-ipv6
key error_log caddy-configuration:error-log
key not_found_file caddy-configuration:not-found-file
key username slap-parameter:monitor-username
key password slap-parameter:monitor-password
[caddy-wrapper]
< = jinja2-template-base
template = ${template-caddy-wrapper:output}
rendered = $${directory:bin}/caddy-wrapper
mode = 0700
extra-context =
raw caddy ${caddy:output}
key conf dynamic-caddy-frontend-template:rendered
key log caddy-configuration:error-log
key grace instance-parameter:configuration.mpm-graceful-shutdown-timeout
[caddy-frontend]
recipe = slapos.cookbook:wrapper
command-line = $${caddy-wrapper:rendered} -pidfile $${caddy-configuration:pid-file}
wrapper-path = $${directory:service}/frontend_caddy
wait-for-files =
$${ca-frontend:cert-file}
$${ca-frontend:key-file}
[not-found-html]
recipe = slapos.cookbook:symbolic.link
target-directory = $${caddy-directory:document-root}
link-binary =
${template-not-found-html:target}
[caddy-directory]
recipe = slapos.cookbook:mkdirectory
document-root = $${directory:srv}/htdocs
slave-configuration = $${directory:etc}/caddy-slave-conf.d/
slave-with-cache-configuration = $${directory:etc}/caddy-slave-with-cache-conf.d/
cache = $${directory:var}/cache
mod-ssl = $${:cache}/httpd_mod_ssl
vh-ssl = $${:slave-configuration}/ssl
slave-log = $${directory:log}/httpd
nginx-slave-configuration = $${directory:etc}/nginx-slave-conf.d/
[caddy-configuration]
frontend-configuration = $${directory:etc}/Caddyfile
access-log = $${directory:log}/frontend-access.log
error-log = $${directory:log}/frontend-error.log
pid-file = $${directory:run}/httpd.pid
frontend-configuration-verification = $${caddy-wrapper:rendered} -validate > /dev/null
frontend-graceful-command = $${:frontend-configuration-verification}; if [ $? -eq 0 ]; then kill -USR1 $(cat $${:pid-file}); fi
not-found-file = $${caddy-directory:document-root}/notfound.html
# Communication with ATS
cache-port = $${trafficserver-variable:input-port}
cache-through-port = 26011
ssl-cache-through-port = 26012
[configtest]
recipe = slapos.cookbook:wrapper
command-line = $${caddy-wrapper:rendered} -validate
wrapper-path = $${directory:bin}/caddy-configtest
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = ${openssl:location}/bin/openssl
ca-dir = $${directory:ca-dir}
requests-directory = $${cadirectory:requests}
wrapper = $${directory:service}/certificate_authority
ca-private = $${cadirectory:private}
ca-certs = $${cadirectory:certs}
ca-newcerts = $${cadirectory:newcerts}
ca-crl = $${cadirectory:crl}
[cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = $${directory:ca-dir}/requests/
private = $${directory:ca-dir}/private/
certs = $${directory:ca-dir}/certs/
newcerts = $${directory:ca-dir}/newcerts/
crl = $${directory:ca-dir}/crl/
[ca-frontend]
<= certificate-authority
recipe = slapos.cookbook:certificate_authority.request
key-file = $${cadirectory:certs}/frontend.key
cert-file = $${cadirectory:certs}/frontend.crt
executable = $${directory:service}/frontend_caddy
wrapper = $${directory:service}/frontend_caddy
key-content = $${instance-parameter:configuration.apache-key}
cert-content = $${instance-parameter:configuration.apache-certificate}
# Put domain name
name = $${instance-parameter:configuration.domain}
[ca-custom-frontend]
< = jinja2-template-base
template = ${template-empty:target}
rendered = $${cadirectory:certs}/frontend.ca.crt
extra-context =
key content instance-parameter:configuration.apache-ca-certificate
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = ${dcron:location}/sbin/crond
cron-entries = $${directory:cron-entries}
crontabs = $${directory:crontabs}
cronstamps = $${directory:cronstamps}
catcher = $${cron-simplelogger:wrapper}
binary = $${directory:service}/crond
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = $${directory:bin}/cron_simplelogger
log = $${directory:log}/cron.log
[cron-entry-logrotate]
<= cron
recipe = slapos.cookbook:cron.d
name = logrotate
frequency = 0 0 * * *
command = $${logrotate:wrapper}
# Deploy Logrotate
[logrotate]
recipe = slapos.cookbook:logrotate
# Binaries
logrotate-binary = ${logrotate:location}/sbin/logrotate
gzip-binary = ${gzip:location}/bin/gzip
gunzip-binary = ${gzip:location}/bin/gunzip
# Directories
wrapper = $${directory:bin}/logrotate
conf = $${directory:etc}/logrotate.conf
logrotate-entries = $${directory:logrotate-entries}
backup = $${directory:logrotate-backup}
state-file = $${directory:srv}/logrotate.status
[logrotate-entry-caddy]
<= logrotate
recipe = slapos.cookbook:logrotate.d
name = caddy
log = $${caddy-configuration:error-log} $${caddy-configuration:access-log}
frequency = daily
rotatep-num = 30
post = $${frontend-caddy-lazy-graceful:rendered} &
sharedscripts = true
notifempty = true
create = true
[logrotate-entry-nginx]
<= logrotate
recipe = slapos.cookbook:logrotate.d
name = caddy-nginx
log = $${nginx-configuration:error_log} $${nginx-configuration:access_log}
frequency = daily
rotatep-num = 30
post = $${nginx-configuration:nginx-graceful-command}
sharedscripts = true
notifempty = true
create = true
#################
# Trafficserver
#################
[trafficserver-directory]
recipe = slapos.cookbook:mkdirectory
configuration = $${directory:etc}/trafficserver
local-state = $${directory:var}/trafficserver
bin_path = ${trafficserver:location}/bin
log = $${directory:log}/trafficserver
cache-path = $${directory:srv}/ats_cache
[trafficserver-variable]
wrapper-path = $${directory:service}/trafficserver
reload-path = $${directory:etc-run}/trafficserver-reload
local-ip = $${instance-parameter:ipv4-random}
input-port = 23432
hostname = $${instance-parameter:configuration.frontend-name}
remap = map /HTTPS/ http://$${instance-parameter:ipv4-random}:$${caddy-configuration:ssl-cache-through-port}
map / http://$${instance-parameter:ipv4-random}:$${caddy-configuration:cache-through-port}
plugin-config = ${trafficserver:location}/libexec/trafficserver/rfc5861.so
cache-path = $${trafficserver-directory:cache-path}
disk-cache-size = $${instance-parameter:configuration.disk-cache-size}
autoconf-port = $${instance-parameter:configuration.trafficserver-autoconf-port}
mgmt-port = $${instance-parameter:configuration.trafficserver-mgmt-port}
ram-cache-size = $${instance-parameter:configuration.ram-cache-size}
[trafficserver-configuration-directory]
recipe = plone.recipe.command
command = cp -rn ${trafficserver:location}/etc/trafficserver/* $${:target}
target = $${trafficserver-directory:configuration}
[trafficserver-launcher]
recipe = slapos.cookbook:wrapper
command-line = ${trafficserver:location}/bin/traffic_cop
wrapper-path = $${trafficserver-variable:wrapper-path}
environment = TS_ROOT=$${buildout:directory}
[trafficserver-reload]
recipe = slapos.cookbook:wrapper
command-line = ${trafficserver:location}/bin/traffic_line -x
wrapper-path = $${trafficserver-variable:reload-path}
environment = TS_ROOT=$${buildout:directory}
# XXX Dedicated Jinja Section without slapparameter
[trafficserver-jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = $${trafficserver-directory:configuration}/$${:filename}
extra-context =
mode = 600
context =
section ats_directory trafficserver-directory
section ats_configuration trafficserver-variable
$${:extra-context}
[trafficserver-records-config]
< = trafficserver-jinja2-template-base
template = ${template-trafficserver-records-config:location}/${template-trafficserver-records-config:filename}
filename = records.config
extra-context =
import os_module os
[trafficserver-storage-config]
< = trafficserver-jinja2-template-base
template = ${template-trafficserver-storage-config:location}/${template-trafficserver-storage-config:filename}
filename = storage.config
[trafficserver-remap-config]
< = trafficserver-jinja2-template-base
template = ${template-empty:target}
filename = remap.config
context =
key content trafficserver-variable:remap
[trafficserver-plugin-config]
< = trafficserver-jinja2-template-base
template = ${template-empty:target}
filename = plugin.config
context =
key content trafficserver-variable:plugin-config
[trafficserver-promise-listen-port]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/trafficserver-port-listening
hostname = $${trafficserver-variable:local-ip}
port = $${trafficserver-variable:input-port}
[trafficserver-line]
recipe = slapos.cookbook:wrapper
command-line = ${trafficserver:location}/bin/traffic_line
wrapper-path = $${directory:bin}/traffic_line
environment = TS_ROOT=$${buildout:directory}
[trafficserver-promise-cache-availability]
recipe = collective.recipe.template
input =
inline:#!${buildout:executable}
import subprocess
import sys
traffic_line = "$${trafficserver-line:wrapper-path}"
result = float(subprocess.check_output([traffic_line, '-r', 'proxy.node.cache.percent_free' ]))
if result != 0: sys.exit(0)
sys.stderr.write("Cache not available, availability: %s" % result)
sys.exit(127)
output = $${directory:promise}/trafficserver-cache-availability
mode = 700
### End of ATS sections
### Caddy Graceful and promises
[frontend-caddy-graceful-bin]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${directory:bin}/frontend-caddy-safe-graceful
mode = 0700
extra-context =
key content caddy-configuration:frontend-graceful-command
[frontend-caddy-graceful]
< = jinja2-template-base
template = ${template-caddy-graceful-script:target}
rendered = $${directory:etc-run}/frontend-caddy-safe-graceful
mode = 0700
extra-context =
key directory_run directory:run
key directory_etc directory:etc
key directory_bin directory:bin
key caddy_graceful_reload_command caddy-configuration:frontend-graceful-command
[frontend-caddy-lazy-graceful]
< = jinja2-template-base
template = ${template-caddy-lazy-script-call:target}
rendered = $${directory:bin}/frontend-caddy-lazy-graceful
mode = 0700
pid-file = $${directory:run}/lazy-graceful.pid
extra-context =
key pid_file :pid-file
raw wait_time 60
key lazy_command caddy-configuration:frontend-graceful-command
# Promises checking configuration:
[promise-frontend-caddy-configuration]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${directory:promise}/frontend-caddy-configuration-promise
mode = 0700
extra-context =
key content caddy-configuration:frontend-configuration-verification
[promise-caddy-frontend-v4-https]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/caddy_frontend_ipv4_https
hostname = $${instance-parameter:ipv4-random}
port = $${instance-parameter:configuration.port}
[promise-caddy-frontend-v4-http]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/caddy_frontend_ipv4_http
hostname = $${instance-parameter:ipv4-random}
port = $${instance-parameter:configuration.plain_http_port}
[promise-caddy-frontend-v6-https]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/caddy_frontend_ipv6_https
hostname = $${instance-parameter:ipv6-random}
port = $${instance-parameter:configuration.port}
[promise-caddy-frontend-v6-http]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/caddy_frontend_ipv6_http
hostname = $${instance-parameter:ipv6-random}
port = $${instance-parameter:configuration.plain_http_port}
[promise-caddy-frontend-cached]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/caddy_cached
hostname = $${instance-parameter:ipv4-random}
port = $${caddy-configuration:cache-through-port}
[promise-caddy-frontend-ssl-cached]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/caddy_ssl_cached
hostname = $${instance-parameter:ipv4-random}
port = $${caddy-configuration:ssl-cache-through-port}
[promise-caddy-is-process-older-than-dependency-set]
recipe = slapos.cookbook:wrapper
command-line = ${buildout:bin-directory}/is-process-older-than-dependency-set $${caddy-configuration:pid-file}
wrapper-path = $${directory:promise}/caddy-frontend-is-running-actual-software-release
[slap_connection]
# Kept for backward compatibility
computer_id = $${slap-connection:computer-id}
partition_id = $${slap-connection:partition-id}
server_url = $${slap-connection:server-url}
software_release_url = $${slap-connection:software-release-url}
key_file = $${slap-connection:key-file}
cert_file = $${slap-connection:cert-file}
[slap-parameter]
# Define default parameter(s) that will be used later, in case user didn't
# specify it
# All parameters are available through the configuration.XX syntax.
# All possible parameters should have a default.
domain = example.org
public-ipv4 =
port = 4443
plain_http_port = 8080
server-admin = admin@example.com
apache_custom_https = ""
apache_custom_http = ""
apache-key =
apache-certificate =
open-port = 80 443
extra_slave_instance_list =
frontend-name =
monitor-username = $${monitor-instance-parameter:username}
monitor-password = $${monitor-htpasswd:passwd}
#######
# Monitoring sections
#
[monitor-instance-parameter]
monitor-httpd-port = $${instance-parameter:configuration.monitor-httpd-port}
cors-domains = $${instance-parameter:configuration.monitor-cors-domains}
username = $${slap-parameter:monitor-username}
password = $${slap-parameter:monitor-password}
[monitor-conf-parameters]
private-path-list +=
$${directory:logrotate-backup}
[monitor-traffic-summary-last-stats-wrapper]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${monitor-directory:reports}/traffic-summary-last-stats_every_1_hour
mode = 0700
command = export TS_ROOT=$${buildout:directory} && echo "<pre>$(${trafficserver:location}/bin/traffic_logstats -f $${trafficserver-directory:log}/squid.blog)</pre>"
extra-context =
key content monitor-traffic-summary-last-stats-wrapper:command
# Produce ATS Cache stats
[monitor-ats-cache-stats-wrapper]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${monitor-directory:reports}/ats-cache-stats_every_1_hour
mode = 0700
command = export TS_ROOT=$${buildout:directory} && echo "<pre>$(${trafficserver:location}/bin/traffic_shell $${monitor-ats-cache-stats-config:rendered})</pre>"
extra-context =
key content monitor-ats-cache-stats-wrapper:command
[monitor-caddy-server-status-wrapper]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${monitor-directory:reports}/monitor-caddy-server-status-wrapper
mode = 0700
command = ${curl:location}/bin/curl -s http://$${instance-parameter:ipv4-random}:$${instance-parameter:configuration.plain_http_port}/server-status -u $${monitor-instance-parameter:username}:$${monitor-htpasswd:passwd} 2>&1
extra-context =
key content monitor-caddy-server-status-wrapper:command
[monitor-ats-cache-stats-config]
< = jinja2-template-base
template = ${template-empty:target}
rendered = $${trafficserver-configuration-directory:target}/cache-config.stats
mode = 644
context =
raw content show:cache-stats
[monitor-verify-re6st-connectivity]
recipe = slapos.cookbook:check_url_available
path = $${directory:promise}/re6st-connectivity
url = $${instance-parameter:configuration.re6st-verification-url}
dash_path = ${dash:location}/bin/dash
curl_path = ${curl:location}/bin/curl
#######################
# Nginx
#
[nginx-wrapper]
< = jinja2-template-base
template = ${template-caddy-wrapper:output}
rendered = $${directory:bin}/nginx-wrapper
mode = 0700
extra-context =
raw caddy ${caddy:output}
key conf dynamic-nginx-frontend-template:rendered
key log nginx-configuration:error_log
key grace instance-parameter:configuration.mpm-graceful-shutdown-timeout
[nginx-frontend]
recipe = slapos.cookbook:wrapper
command-line = $${nginx-wrapper:rendered} -pidfile $${nginx-configuration:pid-file}
wrapper-path = $${directory:service}/frontend_nginx
[dynamic-nginx-frontend-template]
< = jinja2-template-base
template = ${template-nginx-configuration:output}
rendered = $${directory:etc}/nginx.cfg
mode = 0600
extra-context =
key port nginx-configuration:port
key ssl_certificate nginx-configuration:ssl_certificate
key ssl_key nginx-configuration:ssl_key
key local_ip nginx-configuration:local_ip
key plain_port nginx-configuration:plain_port
key slave_configuration_directory nginx-configuration:slave-configuration-directory
key error_log nginx-configuration:error_log
key access_log nginx-configuration:access_log
key not_found_file caddy-configuration:not-found-file
[nginx-configuration]
access_log = $${directory:log}/nginx-access.log
error_log = $${directory:log}/nginx-error.log
ip = $${slap-network-information:global-ipv6}
local_ip = $${slap-network-information:local-ipv4}
port = $${instance-parameter:configuration.nginx_port}
plain_port = $${instance-parameter:configuration.plain_nginx_port}
worker_processes = 4
worker_connections = 1024
slave-configuration-directory = $${caddy-directory:nginx-slave-configuration}
pid-file = $${directory:run}/nginx.pid
nginx-graceful-command = $${:nginx-configuration-verification}; if [ $? -eq 0 ]; then kill -HUP $(cat $${:pid-file}); fi
nginx-configuration-verification = $${nginx-wrapper:rendered} -validate
ssl_certificate = $${ca-frontend:cert-file}
ssl_key = $${ca-frontend:key-file}
[frontend-nginx-graceful]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${directory:etc-run}/frontend-nginx-safe-graceful
mode = 0700
extra-context =
key content nginx-configuration:nginx-graceful-command
[promise-nginx-configuration]
< = jinja2-template-base
template = ${template-wrapper:output}
rendered = $${directory:promise}/nginx-configuration-promise
mode = 0700
extra-context =
key content nginx-configuration:nginx-configuration-verification
[promise-nginx-frontend-v4-https]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/nginx_frontend_ipv4_https
hostname = $${instance-parameter:ipv4-random}
port = $${instance-parameter:configuration.nginx_port}
[promise-nginx-frontend-v4-http]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/nginx_frontend_ipv4_http
hostname = $${instance-parameter:ipv4-random}
port = $${instance-parameter:configuration.plain_nginx_port}
[promise-nginx-frontend-v6-https]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/nginx_frontend_ipv6_https
hostname = $${instance-parameter:ipv6-random}
port = $${instance-parameter:configuration.nginx_port}
[promise-nginx-frontend-v6-http]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/nginx_frontend_ipv6_http
hostname = $${instance-parameter:ipv6-random}
port = $${instance-parameter:configuration.plain_nginx_port}
[promise-nginx-is-process-older-than-dependency-set]
recipe = slapos.cookbook:wrapper
command-line = ${buildout:bin-directory}/is-process-older-than-dependency-set $${nginx-configuration:pid-file}
wrapper-path = $${directory:promise}/promise-nginx-is-process-older-than-dependency-set
[port-redirection]
<= jinja2-template-base
template = inline:
[{"srcPort": 80, "destPort": {{ http_port }}}, {"srcPort": 443, "destPort": {{ https_port }}}]
rendered = $${buildout:directory}/.slapos-port-redirect
mode = 0644
extra-context =
key http_port instance-parameter:configuration.plain_http_port
key https_port instance-parameter:configuration.port
{% if slap_software_type in software_type %}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = ${buildout:directory}/${:filename}
extra-context =
context =
import json_module json
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type slap-parameter:slap_software_type
key slave_instance_list slap-parameter:slave_instance_list
${:extra-context}
{% set part_list = [] %}
{% set single_type_key = 'single-' %}
{% if slap_software_type == "replicate" %}
{% set frontend_type = slapparameter_dict.pop('-frontend-type', 'single-default') %}
{% elif slap_software_type in ['default', 'RootSoftwareInstance'] %}
{% set frontend_type = "%s%s" % (single_type_key, 'custom-personal') %}
{% else %}
{% set frontend_type = "%s%s" % (single_type_key, slap_software_type) %}
{% endif %}
{% set frontend_quantity = slapparameter_dict.pop('-frontend-quantity', '1') | int %}
{% set slave_list_name = 'extra_slave_instance_list' %}
{% set frontend_list = [] %}
{% set frontend_section_list = [] %}
{% set request_dict = {} %}
{% set namebase = 'caddy-frontend' %}
# XXX Dirty hack, not possible to define default value before
{% set sla_computer_caddy_1_key = '-sla-1-computer_guid' %}
{% if not sla_computer_caddy_1_key in slapparameter_dict %}
{% do slapparameter_dict.__setitem__(sla_computer_caddy_1_key, '${slap-connection:computer-id}') %}
{% endif %}
# Here we request individually each frontend.
# The presence of sla parameters is checked and added if found
{% for i in range(1, frontend_quantity + 1) %}
{% set frontend_name = "%s-%s" % (namebase, i) %}
{% set request_section_title = 'request-%s' % frontend_name %}
{% set sla_key = "-sla-%s-" % i %}
{% set sla_key_length = sla_key | length %}
{% set sla_dict = {} %}
{% set config_key = "-frontend-config-%s-" % i %}
{% set config_key_length = config_key | length %}
{% set config_dict = {} %}
{% for key in slapparameter_dict.keys() %}
{% if key.startswith(sla_key) %}
{% do sla_dict.__setitem__(key[sla_key_length:], slapparameter_dict.pop(key)) %}
# We check for specific configuration regarding the frontend
{% elif key.startswith(config_key) %}
{% do config_dict.__setitem__(key[config_key_length:], slapparameter_dict.pop(key)) %}
{% endif %}
{% endfor %}
{% do frontend_list.append(frontend_name) %}
{% do frontend_section_list.append(request_section_title) %}
{% do part_list.append(request_section_title) %}
# Filling request dict for slave
{% set state_key = "-frontend-%s-state" % i %}
{% do request_dict.__setitem__(request_section_title,
{
'config': config_dict,
'name': frontend_name,
'sla': sla_dict,
'state': slapparameter_dict.pop(state_key, None)
}) %}
{% endfor %}
{% set authorized_slave_string = slapparameter_dict.pop('-frontend-authorized-slave-string', '') %}
{% set authorized_slave_list = [] %}
{% set rejected_slave_list = [] %}
{% for slave in slave_instance_list %}
{% if not (slave.has_key('apache_custom_http') and not slave.get('slave_reference') in authorized_slave_string) %}
{% do authorized_slave_list.append(slave) %}
{% else %}
{% do rejected_slave_list.append(slave.get('slave_reference')) %}
{% endif %}
{% endfor %}
[monitor-instance-parameter]
monitor-httpd-port = {{ slapparameter_dict.get('monitor-httpd-port', '8196') }}
[replicate]
<= slap-connection
recipe = slapos.cookbook:requestoptional
config-monitor-cors-domains = {{ slapparameter_dict.get('monitor-cors-domains', 'monitor.app.officejs.com') }}
config-monitor-username = ${monitor-instance-parameter:username}
config-monitor-password = ${monitor-htpasswd:passwd}
config-monitor-httpd-port = {{ slapparameter_dict.get('monitor-httpd-port', '8196') }}
{% set frontend_software_url_key = "-frontend-software-release-url" %}
{% if slapparameter_dict.has_key(frontend_software_url_key) %}
software-url = {{ slapparameter_dict.pop(frontend_software_url_key) }}
{% else %}
software-url = ${slap-connection:software-release-url}
{% endif %}
software-type = {{frontend_type}}
return = private-ipv4 public-ipv4 slave-instance-information-list monitor-base-url
{% for section, frontend_request in request_dict.iteritems() %}
[{{section}}]
<= replicate
name = {{ frontend_request.get('name') }}
{% if frontend_request.get('state') %}
state = {{ frontend_request.get('state') }}
{% endif%}
{% set slave_configuration_dict = slapparameter_dict %}
{% do slave_configuration_dict.update(frontend_request.get('config')) %}
{% do slave_configuration_dict.__setitem__(slave_list_name, json_module.dumps(authorized_slave_list)) %}
{% do slave_configuration_dict.__setitem__("frontend-name", frontend_request.get('name')) %}
config-_ = {{ json_module.dumps(slave_configuration_dict) }}
{% if frontend_request.get('sla') %}
{% for parameter, value in frontend_request.get('sla').iteritems() %}
sla-{{ parameter }} = {{ value }}
{% endfor %}
{% endif %}
{% endfor %}
[publish-information]
<= monitor-publish
recipe = slapos.cookbook:publish
domain = {{ slapparameter_dict.get('domain') }}
slave-amount = {{ slave_instance_list | length }}
accepted-slave-amount = {{ authorized_slave_list | length }}
rejected-slave-amount = {{ rejected_slave_list | length }}
rejected-slave-list = {{ json_module.dumps(rejected_slave_list) }}
#----------------------------
#--
#-- Publish slave information
[publish-slave-information]
recipe = slapos.cookbook:softwaretype
default = ${dynamic-publish-slave-information:rendered}
RootSoftwareInstance = ${dynamic-publish-slave-information:rendered}
replicate = ${dynamic-publish-slave-information:rendered}
custom-personal = ${dynamic-publish-slave-information:rendered}
custom-group = ${dynamic-publish-slave-information:rendered}
[slave-information]
{% for frontend_section in frontend_section_list %}
{{ frontend_section }} = {{ "${%s:connection-slave-instance-information-list}" % frontend_section }}
{% endfor %}
[dynamic-publish-slave-information]
< = jinja2-template-base
template = {{ template_publish_slave_information }}
filename = dynamic-publish-slave-information.cfg
extensions = jinja2.ext.do
extra-context =
section slave_information slave-information
[monitor-conf-parameters]
monitor-url-list +=
{% for frontend in frontend_section_list %}
{{ ' ${' + frontend + ':connection-monitor-base-url}' }}
{% endfor %}
[buildout]
extends = {{ template_monitor }}
parts =
monitor-base
publish-slave-information
publish-information
{% for part in part_list %}
{{ ' %s' % part }}
{% endfor %}
# publish-information
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[slap_connection]
# Kept for backward compatibility
computer_id = ${slap-connection:computer-id}
partition_id = ${slap-connection:partition-id}
server_url = ${slap-connection:server-url}
software_release_url = ${slap-connection:software-release-url}
key_file = ${slap-connection:key-file}
cert_file = ${slap-connection:cert-file}
[slap-parameter]
slave_instance_list =
-frontend-quantity = 1
-frontend-type = single-default
{% endif %}
{
"$schema": "http://json-schema.org/draft-04/schema",
"properties": {
"-frontend-authorized-slave-string": {
"description": "List of SOFTINST-XXX of Slaves, separated by space which is allowed to use custom configuration.",
"title": "Authorized Slave String",
"type": "string"
},
"-frontend-quantity": {
"description": "Quantity of Frontends Replicate.",
"title": "Frontend Replication Quantity",
"type": "integer"
},
"apache-ca-certificate": {
"description": "[NOT IMPLEMENTED] SSL CA Certificate used by the server.",
"textarea": true,
"title": "[NOT IMPLEMENTED] SSL CA Certificate",
"type": "string"
},
"apache-certificate": {
"description": "SSL Certificate used by the server.",
"textarea": true,
"title": "SSL Certificate",
"type": "string"
},
"apache-key": {
"description": "SSL Key used by the server.",
"textarea": true,
"title": "SSL Key",
"type": "string"
},
"domain": {
"description": "Base Domain for create subdomains (ie.: example.com).",
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$",
"title": "Domain",
"type": "string"
},
"enable-http2-by-default": {
"default": "true",
"description": "Use HTTP2 as default Protocol",
"enum": [
"true",
"false"
],
"title": "Enable HTTP2 by Default",
"type": "string"
},
"mpm-graceful-shutdown-timeout": {
"default": 5,
"description": "Value passed to -grace parameter of Caddy, see https://caddyserver.com/docs/cli .",
"title": "Duration of the graceful shutdown period",
"type": "integer"
},
"nginx-domain": {
"description": "Base Domain for create subdomains (ie.: example2.com) for websocket, notebook and eventsource.",
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$",
"title": "Nginx Domain",
"type": "string"
},
"public-ipv4": {
"description": "Public ipv4 of the frontend (the one Caddy will be indirectly listening to).",
"title": "Public IPv4",
"type": "string"
},
"re6st-verification-url": {
"description": "Url to verify if the internet and/or re6stnet is working.",
"title": "Test Verification URL",
"type": "string"
}
},
"title": "Input Parameters",
"type": "object"
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Values returned by Caddy Frontend instanciation",
"properties": {
"accepted-slave-amount": {
"description": "Amount of Slaves allocated to the Instance which are deployed",
"type": "integer"
},
"domain": {
"description": "Base domain used by the instance",
"type": "string"
},
"monitor-base-url": {
"description": "Base url for monitor",
"type": "string"
},
"monitor-password": {
"description": "Password to access the monitor",
"type": "string"
},
"monitor-url": {
"description": "Url of Monitor (opml)",
"type": "string"
},
"monitor-user": {
"description": "User to access the monitor",
"type": "string"
},
"reject-slave-amount": {
"description": "Rejected Amount of Slaves allocated to the Instance which are not deployed",
"type": "integer"
},
"rejected-slave-list": {
"description": "List of slave instances references which are rejected",
"type": "array"
},
"slave-amount": {
"description": "Total amount of Slaves allocated to the Instance (include blocked ones)",
"type": "integer"
}
},
"type": "object"
}
{
"$schema": "http://json-schema.org/draft-04/schema",
"properties": {
"apache_custom_http": {
"default": "",
"description": "Raw http configuration in python template format. Your site will be rejected if you use it without notification and approval of frontend administrators",
"textarea": true,
"title": "HTTP configuration",
"type": "string"
},
"apache_custom_https": {
"default": "",
"description": "Raw https configuration in python template format. Your site will be rejected if you use it without notification and approval of frontend administrators",
"textarea": true,
"title": "HTTPS configuration",
"type": "string"
},
"custom_domain": {
"description": "Custom Domain to use for the website",
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$",
"title": "Custom Domain",
"type": "string"
},
"default-path": {
"default": "",
"description": "Provide default path to redirect user to when user access / (the site root)",
"title": "type:zope Default Path",
"type": "string"
},
"disable-no-cache-request": {
"default": "false",
"description": "If set to true, Cache-Control and Pragma requests headers will not be sent to cache and backend servers. This prevents clients from bypassing cache when enable_cache is true",
"enum": [
"false",
"true"
],
"title": "enable_cache: Disable 'no-cache' requests",
"type": "string"
},
"disable-via-header": {
"default": "false",
"description": "If set to true, Via response headers will not be sent to client",
"enum": [
"false",
"true"
],
"title": "enable_cache: Disable 'Via' headers from cache",
"type": "string"
},
"disabled-cookie-list": {
"default": "",
"description": "[NOT Implemented] List of Cookies separated by space that will not be sent to cache and backend servers. This is especially useful to discard analytics tracking cookies when using Vary: Cookie cache headers",
"title": "[NOT Implemented] Disabled Cookies",
"type": "string"
},
"enable-http2": {
"default": "true",
"description": "Use HTTP2 Protocol for the site",
"enum": [
"true",
"false"
],
"title": "Enable HTTP2 Protocol",
"type": "string"
},
"enable_cache": {
"default": "false",
"description": "If set to true, http caching server (Apache Traffic Server) will be used between frontend Caddy and backend",
"enum": [
"false",
"true"
],
"title": "Enable Cache",
"type": "string"
},
"https-only": {
"default": "false",
"description": "If set to true, http requests will be redirected to https",
"enum": [
"false",
"true"
],
"title": "HTTPS Only",
"type": "string"
},
"https-url": {
"description": "HTTPS Url of the backend if it is diferent from url parameter",
"pattern": "^(http|https|ftp)://",
"title": "HTTPS Backend URL",
"type": "string"
},
"monitor-ipv4-test": {
"default": "",
"description": "IPv4 Address for the frontend keep monitoring with ping",
"title": "IPv4 Address to Monitor Packet Lost",
"type": "string"
},
"monitor-ipv6-test": {
"default": "",
"description": "IPv6 Address for the frontend keep monitoring with ping6 (without brackets)",
"title": "IPv6 Address to Monitor Packet Lost",
"type": "string"
},
"path": {
"default": "",
"description": "Path to proxy to in the backend",
"title": "type:zope Backend Path",
"type": "string"
},
"prefer-gzip-encoding-to-backend": {
"default": "false",
"description": "[NOT Implemented] If set to true, frontend will rewrite Accept-Encoding request header to simply 'gzip' for all variants of Accept-Encoding containing 'gzip', in order to maximize cache hits for resources cached with Vary: Accept-Encoding when enable_cache is used",
"enum": [
"false",
"true"
],
"title": "[NOT Implemented] Prefer gzip Encoding for Backend",
"type": "string"
},
"re6st-optimal-test": {
"default": "",
"description": "IPv6 and IPv6 Address for the frontend test if re6st is on the optimal status (use ipv6,ipv4)",
"title": "IPv6 and IPv4 Address to test Re6st",
"type": "string"
},
"server-alias": {
"default": "",
"description": "Server Alias List separated by space",
"title": "Server Alias",
"type": "string"
},
"ssl-proxy-verify": {
"default": "false",
"description": "[NOT Implemented] If set to true, Backend SSL Certificates will be checked and frontend will refuse to proxy if certificate is invalid",
"enum": [
"false",
"true"
],
"title": "[NOT Implemented] Verify Backend Certificates",
"type": "string"
},
"ssl_ca_crt": {
"default": "",
"description": "[NOT Implemented] Content of the CA certificate file",
"textarea": true,
"title": "[NOT Implemented] SSL Certificate Authority's Certificate",
"type": "string"
},
"ssl_crt": {
"default": "",
"description": "Content of the SSL Certificate file",
"textarea": true,
"title": "SSL Certificate",
"type": "string"
},
"ssl_key": {
"default": "",
"description": "Content of the SSL Key file",
"textarea": true,
"title": "SSL Key",
"type": "string"
},
"ssl_proxy_ca_crt": {
"default": "",
"description": "[NOT Implemented] Content of the SSL Certificate Authority file of the backend (to be used with ssl-proxy-verify)",
"title": "[NOT Implemented] SSL Backend Authority's Certificate",
"type": "string"
},
"type": {
"default": "",
"description": "Type of slave. If redirect, the slave will redirect to the given url. If zope, the rewrite rules will be compatible with Virtual Host Monster. Implemented are default, zope and redirect, not implemneted are notebook and eventsource.",
"enum": [
"",
"zope",
"redirect",
"notebook",
"eventsource"
],
"title": "Backend Type",
"type": "string"
},
"url": {
"description": "Url of the backend",
"pattern": "^(http|https|ftp)://",
"title": "Backend URL",
"type": "string"
},
"virtualhostroot-http-port": {
"default": 80,
"description": "Port where http requests to frontend will be redirected.",
"title": "type:zope virtualhostroot-http-port",
"type": "integer"
},
"virtualhostroot-https-port": {
"default": 443,
"description": "Port where https requests to frontend will be redirected.",
"title": "type:zope virtualhostroot-https-port",
"type": "integer"
}
},
"title": "Input Parameters",
"type": "object"
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Values returned by Caddy Frontend instanciation",
"properties": {
"domain": {
"description": "Base domain used by the instance",
"type": "string"
},
"log-access-url": {
"description": "List of URLs to access logs",
"type": "array"
},
"public-ipv4": {
"description": "Public IPv4 to be included on DNS",
"type": "string"
},
"replication_number": {
"description": "Number of nodes the slave is replicated",
"type": "integer"
},
"secure_access": {
"description": "URL for HTTP access",
"type": "string"
},
"site_url": {
"description": "URL for HTTP access",
"type": "string"
},
"url": {
"description": "Default URL provided",
"type": "string"
}
},
"type": "object"
}
[buildout]
parts =
dynamic-template-caddy-replicate
switch-softwaretype
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[slap-parameters]
recipe = slapos.cookbook:slapconfiguration
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = $${buildout:directory}/$${:filename}
extra-context =
context =
import json_module json
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type slap-parameters:slap-software-type
key slapparameter_dict slap-parameters:configuration
key slave_instance_list slap-parameters:slave-instance-list
$${:extra-context}
[switch-softwaretype]
recipe = slapos.cookbook:softwaretype
default = $${dynamic-template-caddy-replicate:rendered}
RootSoftwareInstance = $${dynamic-template-caddy-replicate:rendered}
custom-personal = $${dynamic-template-caddy-replicate:rendered}
single-default = ${template-caddy-frontend:output}
single-custom-personal = ${template-caddy-frontend:output}
replicate = $${dynamic-template-caddy-replicate:rendered}
[dynamic-template-caddy-replicate]
< = jinja2-template-base
template = ${template-caddy-replicate:target}
filename = instance-caddy-replicate.cfg
extensions = jinja2.ext.do
extra-context =
raw template_publish_slave_information ${template-replicate-publish-slave-information:target}
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type RootSoftwareInstance-default-custom-personal-replicate
raw template_monitor ${monitor2-template:rendered}
[buildout]
extends = common.cfg
[versions]
PyRSS2Gen = 1.1
apache-libcloud = 0.19.0
cns.recipe.symlink = 0.2.3
ecdsa = 0.13
gitdb = 0.6.4
plone.recipe.command = 1.1
pycrypto = 2.6.1
rdiff-backup = 1.0.5+SlapOSPatched001
slapos.recipe.template = 4.3
slapos.toolbox = 0.76
smmap = 0.9.0
numpy = 1.11.2
pyasn1 = 0.2.3
websockify = 0.8.0
# Required by:
# slapos.toolbox==0.71
dnspython = 1.15.0
# Required by:
# slapos.toolbox==0.71
erp5.util = 0.4.49
# Required by:
# slapos.toolbox==0.71
passlib = 1.6.5
# Required by:
# slapos.toolbox==0.71
GitPython = 2.0.8
# Required by:
# slapos.toolbox==0.71
atomize = 0.2.0
# Required by:
# slapos.toolbox==0.71
feedparser = 5.2.1
# Required by:
# slapos.toolbox==0.71
lockfile = 0.12.2
# Required by:
# slapos.toolbox==0.71
paramiko = 2.0.1
# Required by:
# slapos.toolbox==0.71
pycurl = 7.43.0
# Required by:
# slapos.toolbox==0.71
rpdb = 0.1.5
{
"description": "Caddy Frontend",
"name": "Caddy Frontend",
"serialisation": "xml",
"software-type": {
"custom-personal": {
"description": "",
"index": 2,
"request": "instance-caddy-input-schema.json",
"response": "instance-output-schema.json",
"title": "Custom Personal"
},
"custom-personal-slave": {
"description": "Custom Personal",
"index": 1,
"request": "instance-slave-caddy-input-schema.json",
"response": "instance-output-schema.json",
"shared": true,
"software-type": "custom-personal",
"title": "Custom Personal (Slave)"
},
"default": {
"description": "Default",
"index": 3,
"request": "instance-caddy-input-schema.json",
"response": "instance-output-schema.json",
"software-type": "default",
"title": "Default"
},
"default-slave": {
"description": "Default",
"index": 4,
"request": "instance-slave-caddy-input-schema.json",
"response": "instance-output-schema.json",
"shared": true,
"software-type": "default",
"title": "Default (slave)"
}
}
}
# Main caddy configuration file
import {{frontend_configuration.get('log-access-configuration')}}
import {{ slave_configuration_directory }}/*.conf
import {{ slave_with_cache_configuration_directory }}/*.conf
# Catch-all and 404 for not configured instances
:{{ https_port }} {
tls {{ login_certificate }} {{ login_key }}
bind {{ local_ipv4 }}
# Compress the output
gzip
status 404 /
log / {{ access_log }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ error_log }} {
* {{ not_found_file }}
}
}
:{{ http_port }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
status 404 /
log / {{ access_log }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ error_log }} {
* {{ not_found_file }}
}
}
# Access to server-status Caddy-style
https://[{{ global_ipv6 }}]:{{ https_port }}/server-status, https://{{ local_ipv4 }}:{{ https_port }}/server-status {
tls {{ login_certificate }} {{ login_key }}
# Compress the output
gzip
bind {{ local_ipv4 }}
basicauth "{{ username }}" {{ password }} {
"Server Status"
/
}
expvar
pprof
log / {{ access_log }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ error_log }} {
* {{ not_found_file }}
}
}
{% if software_type == slap_software_type %}
{% set cached_server_dict = {} %}
{% set part_list = [] %}
{% set cache_port = caddy_configuration.get('cache-port') %}
{% set cached_port = caddy_configuration.get('cache-through-port') %}
{% set ssl_cached_port = caddy_configuration.get('ssl-cache-through-port') %}
{% set cache_access = "http://%s:%s" % (local_ipv4, cache_port) %}
{% set ssl_cache_access = "http://%s:%s/HTTPS" % (local_ipv4, cache_port) %}
{% set TRUE_VALUES = ['y', 'yes', '1', 'true'] %}
{% set NGINX_TYPE_LIST = ['eventsource', 'notebook'] %}
{% set generic_instance_parameter_dict = { 'cache_access': cache_access, 'local_ipv4': local_ipv4, 'http_port': http_port, 'https_port': https_port} %}
{% set slave_log_dict = {} %}
{% if extra_slave_instance_list %}
{% set slave_instance_information_list = [] %}
{% set slave_instance_list = slave_instance_list + json_module.loads(extra_slave_instance_list) %}
{% endif %}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
extra-context =
context =
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
${:extra-context}
{% do logrotate_dict.pop('recipe') %}
[logrotate]
{% for key, value in logrotate_dict.iteritems() %}
{{ key }} = {{ value }}
{% endfor %}
post = {{ frontend_lazy_graceful_reload }} &
frequency = daily
rotatep-num = 30
sharedscripts = true
notifempty = true
create = true
[cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = {{ custom_ssl_directory }}/requests/
private = {{ custom_ssl_directory }}/private/
certs = {{ custom_ssl_directory }}/certs/
newcerts = {{ custom_ssl_directory }}/newcerts/
crl = {{ custom_ssl_directory }}/crl/
{# Loop thought slave list to set up slaves #}
{% for slave_instance in slave_instance_list %}
{% set slave_reference = slave_instance.get('slave_reference') %}
{% set slave_type = slave_instance.get('type', '') %}
{% set slave_section_title = 'dynamic-template-slave-instance-%s' % slave_reference %}
{% set slave_parameter_dict = generic_instance_parameter_dict.copy() %}
{% set slave_publish_dict = {} %}
{% set slave_configuration_section_name = 'slave-instance-%s-configuration' % slave_reference %}
{% set slave_logrotate_section = slave_reference + "-logs" %}
{% set slave_password_section = slave_reference + "-password" %}
{% set slave_ln_section = slave_reference + "-ln" %}
{# extend parts #}
{% do part_list.extend([slave_ln_section]) %}
{% do part_list.extend([slave_logrotate_section, slave_section_title]) %}
{% set slave_log_folder = logrotate_dict.get('backup') + '/' + slave_reference + "-logs" %}
{# Set Up log files #}
{% do slave_parameter_dict.__setitem__('access_log', '/'.join([caddy_log_directory, '%s_access_log' % slave_reference])) %}
{% do slave_parameter_dict.__setitem__('error_log', '/'.join([caddy_log_directory, '%s_error_log' % slave_reference])) %}
{% do slave_instance.__setitem__('access_log', slave_parameter_dict.get('access_log')) %}
{% do slave_instance.__setitem__('error_log', slave_parameter_dict.get('error_log')) %}
{# Add slave log directory to the slave log access dict #}
{% do slave_log_dict.__setitem__(slave_reference, slave_log_folder) %}
{% set slave_log_access_url = 'https://' + slave_reference + ':${'+ slave_password_section +':passwd}@[' + frontend_configuration.get('caddy-ipv6') + ']:' + frontend_configuration.get('caddy-https-port') + '/' + slave_reference.lower() + '/' %}
{% do slave_publish_dict.__setitem__('log-access', slave_log_access_url) %}
{% do slave_publish_dict.__setitem__('slave-reference', slave_reference) %}
{% do slave_publish_dict.__setitem__('public-ipv4', public_ipv4) %}
{# Set slave domain if none was defined #}
{% if slave_instance.get('custom_domain', None) == None %}
{% set domain_prefix = slave_instance.get('slave_reference').replace("-", "").replace("_", "").lower() %}
{% if slave_type in NGINX_TYPE_LIST %}
{% do slave_instance.__setitem__('custom_domain', "%s.%s" % (domain_prefix, slapparameter_dict.get('nginx-domain', slapparameter_dict.get('domain')))) %}
{% else %}
{% do slave_instance.__setitem__('custom_domain', "%s.%s" % (domain_prefix, slapparameter_dict.get('domain'))) %}
{% endif %}
{% endif %}
{% set enable_cache = (('' ~ slave_instance.get('enable_cache', '')).lower() in TRUE_VALUES and slave_type != 'redirect') %}
{% if enable_cache and 'url' in slave_instance %}
{% if 'domain' in slave_instance %}
{% do slave_instance.__setitem__('custom_domain', slave_instance.get('domain')) %}
{% endif %}
{% do slave_instance.__setitem__('backend_url', slave_instance.get('url')) %}
{% do slave_instance.__setitem__('https_backend_url', slave_instance.get('https-url', slave_instance.get('url'))) %}
{% do slave_instance.__setitem__('url', cache_access) %}
{% do slave_instance.__setitem__('https-url', ssl_cache_access) %}
{% do cached_server_dict.__setitem__(slave_reference, slave_configuration_section_name) %}
{% endif %}
{% if not slave_instance.has_key('apache_custom_http') and not slave_instance.has_key('apache_custom_https') %}
{% do slave_publish_dict.__setitem__('domain', slave_instance.get('custom_domain')) %}
{% do slave_publish_dict.__setitem__('url', "http://%s" % slave_instance.get('custom_domain')) %}
{% do slave_publish_dict.__setitem__('site_url', "http://%s" % slave_instance.get('custom_domain')) %}
{% do slave_publish_dict.__setitem__('secure_access', 'https://%s' % slave_instance.get('custom_domain')) %}
{% endif %}
[slave-log-directory-dict]
{{slave_reference}} = {{ slave_log_folder }}
[slave-password]
{{ slave_reference }} = {{ '${' + slave_password_section + ':passwd}' }}
{# Set slave logrotate entry #}
[{{slave_logrotate_section}}]
<= logrotate
recipe = slapos.cookbook:logrotate.d
name = ${:_buildout_section_name_}
log = {{slave_parameter_dict.get('access_log')}} {{slave_parameter_dict.get('error_log')}}
backup = {{ slave_log_folder }}
{# integrate current logs inside #}
[{{slave_ln_section}}]
recipe = plone.recipe.command
stop-on-error = false
command = ln -s {{slave_parameter_dict.get('error_log')}} {{ slave_log_folder }}/error.log && ln -s {{slave_parameter_dict.get('access_log')}} {{ slave_log_folder }}/access.log
{# Set password for slave #}
[{{slave_password_section}}]
recipe = slapos.cookbook:generate.password
storage-path = {{caddy_configuration_directory}}/.{{slave_reference}}.passwd
bytes = 8
{# ################################################## #}
{# Set Slave Certificates if needed #}
{# Set ssl certificates for each slave #}
{% for cert_name in ('ssl_ca_crt', 'ssl_csr', 'ssl_proxy_ca_crt')%}
{% if cert_name in slave_instance %}
{% set cert_title = '%s-%s' % (slave_reference, cert_name.replace('ssl_', '')) %}
{% set cert_file = '/'.join([custom_ssl_directory, cert_title.replace('-','.')]) %}
{% do part_list.append(cert_title) %}
{% do slave_parameter_dict.__setitem__(cert_name, cert_file) %}
{% do slave_instance.__setitem__('path_to_' + cert_name, cert_file) %}
{# Store certificates on fs #}
[{{ cert_title }}]
< = jinja2-template-base
template = {{ empty_template }}
rendered = {{ cert_file }}
extra-context =
key content {{ cert_title + '-config:value' }}
# Store certificate in config
[{{ cert_title + '-config' }}]
value = {{ dumps(slave_instance.get(cert_name)) }}
{% endif %}
{% endfor %}
{#- Set Up Certs #}
{% do slave_instance.__setitem__('login_certificate', login_certificate) %}
{% do slave_instance.__setitem__('login_key', login_key) %}
{% do slave_instance.__setitem__('login_ca_crt', login_ca_crt) %}
{% do slave_instance.__setitem__('enable_http2_by_default', enable_http2_by_default) %}
{% do slave_parameter_dict.__setitem__('ssl_crt', login_certificate) %}
{% do slave_parameter_dict.__setitem__('ssl_key', login_key) %}
{% if 'ssl_key' in slave_instance and 'ssl_crt' in slave_instance %}
{% set cert_title = '%s-crt' % (slave_reference) %}
{% set key_title = '%s-key' % (slave_reference) %}
{% set cert_file = '/'.join([custom_ssl_directory, cert_title.replace('-','.')]) %}
{% set key_file = '/'.join([custom_ssl_directory, key_title.replace('-','.')]) %}
{% do part_list.append(cert_title) %}
{% do slave_parameter_dict.__setitem__("ssl_crt", cert_file) %}
{% do slave_parameter_dict.__setitem__("ssl_key", key_file) %}
{% do slave_instance.__setitem__('path_to_ssl_crt', cert_file) %}
{% do slave_instance.__setitem__('path_to_ssl_key', key_file) %}
[{{cert_title}}]
recipe = slapos.cookbook:certificate_authority.request
#openssl-binary = ${openssl:location}/bin/openssl
requests-directory = ${cadirectory:requests}
ca-private = ${cadirectory:private}
ca-certs = ${cadirectory:certs}
ca-newcerts = ${cadirectory:newcerts}
ca-crl = ${cadirectory:crl}
key-file = {{ key_file }}
cert-file = {{ cert_file }}
key-content = {{ dumps(slave_instance.get('ssl_key')) }}
cert-content = {{ dumps(slave_instance.get('ssl_crt')) }}
{% endif %}
{# ########################################## #}
{# Set Slave Configuration #}
[{{ slave_configuration_section_name }}]
{% set apache_custom_http = ((slave_instance.pop('apache_custom_http', '')) % slave_parameter_dict) %}
{% set apache_custom_https = ((slave_instance.pop('apache_custom_https', '')) % slave_parameter_dict) %}
apache_custom_http = {{ dumps(apache_custom_http) }}
apache_custom_https = {{ dumps(apache_custom_https) }}
{{ '\n' }}
{% for key, value in slave_instance.iteritems() %}
{{ key }} = {{ dumps(value) }}
{% endfor %}
[{{ slave_section_title }}]
< = jinja2-template-base
{% if slave_type in NGINX_TYPE_LIST %}
rendered = {{ nginx_configuration_directory }}/${:filename}
{% else %}
rendered = {{ caddy_configuration_directory }}/${:filename}
{% endif %}
{% if apache_custom_http %}
template = {{ template_custom_slave_configuration }}
{% elif slave_type == 'eventsource' %}
template = {{ template_eventsource_slave_configuration }}
{% elif slave_type == 'notebook' %}
template = {{ template_notebook_slave_configuration }}
{% else %}
template = {{ template_default_slave_configuration }}
{% endif %}
filename = {{ '%s.conf' % slave_reference }}
extra-context =
raw https_port {{ https_port }}
raw http_port {{ http_port }}
raw local_ipv4 {{ local_ipv4 }}
raw nginx_http_port {{ nginx_http_port }}
raw nginx_https_port {{ nginx_https_port }}
section slave_parameter {{ slave_configuration_section_name }}
{{ '\n' }}
{% set check_error_log_section_title = 'check-%s-error-log-last-hour' % slave_instance.get('slave_reference') %}
{% do part_list.append(check_error_log_section_title) %}
[{{ check_error_log_section_title }}]
recipe = slapos.cookbook:wrapper
command-line = {{ bin_directory }}/check-error-on-apache-log -l {{ slave_instance.get('error_log') }} -d 3600
filename = {{ check_error_log_section_title }}
wrapper-path = {{ promise_directory }}/${:filename}
{% set check_error_log_section_title = 'check-%s-error-log-last-day' % slave_instance.get('slave_reference') %}
{% do part_list.append(check_error_log_section_title) %}
[{{ check_error_log_section_title }}]
recipe = slapos.cookbook:wrapper
command-line = {{ bin_directory }}/check-error-on-apache-log -l {{ slave_instance.get('error_log') }} -d 86400
filename = {{ check_error_log_section_title }}
wrapper-path = {{ promise_directory }}/${:filename}
{% set monitor_ipv6_test = slave_instance.get('monitor-ipv6-test', '') %}
{% if monitor_ipv6_test %}
{% set monitor_ipv6_section_title = 'check-%s-ipv6-packet-list-test' % slave_instance.get('slave_reference') %}
{% do part_list.append(monitor_ipv6_section_title) %}
[{{ monitor_ipv6_section_title }}]
recipe = slapos.cookbook:wrapper
command-line = {{ bin_directory }}/is-icmp-packet-lost -a {{monitor_ipv6_test}}
filename = {{ monitor_ipv6_section_title }}
wrapper-path = {{ promise_directory }}/${:filename}
{% endif %}
{% set monitor_ipv4_test = slave_instance.get('monitor-ipv4-test', '') %}
{% if monitor_ipv4_test %}
{% set monitor_ipv4_section_title = 'check-%s-ipv4-packet-list-test' % slave_instance.get('slave_reference') %}
{% do part_list.append(monitor_ipv4_section_title) %}
[{{ monitor_ipv4_section_title }}]
recipe = slapos.cookbook:wrapper
command-line = {{ bin_directory }}/is-icmp-packet-lost -4 -a {{monitor_ipv4_test}}
filename = {{ monitor_ipv4_section_title }}
wrapper-path = {{ promise_directory }}/${:filename}
{% endif %}
{% set re6st_optimal_test = slave_instance.get('re6st-optimal-test', '') %}
{% if re6st_optimal_test %}
{% set re6st_ipv6, re6st_ipv4 = re6st_optimal_test.split(",") %}
{% set re6st_optimal_test_section_title = 'check-%s-re6st-optimal-test' % slave_instance.get('slave_reference') %}
{% do part_list.append(re6st_optimal_test_section_title) %}
[{{ re6st_optimal_test_section_title }}]
recipe = slapos.cookbook:wrapper
command-line = {{ bin_directory }}/check-re6st-optimal-status -4 {{re6st_ipv4}} -6 {{re6st_ipv6}}
filename = {{ re6st_optimal_test_section_title }}
wrapper-path = {{ promise_directory }}/${:filename}
{% endif %}
{# ############################### #}
{# Publish Slave Information #}
{% if not extra_slave_instance_list %}
{% set publish_section_title = 'publish-%s-connection-information' % slave_instance.get('slave_reference') %}
{% do part_list.append(publish_section_title) %}
[{{ publish_section_title }}]
recipe = slapos.cookbook:publish
{% for key, value in slave_publish_dict.iteritems() %}
{{ key }} = {{ value }}
{% endfor %}
{% else %}
{% do slave_instance_information_list.append(slave_publish_dict) %}
{% endif %}
{# End of the main for loop#}
{% endfor %}
###############################################
### Prepare virtualhost for slaves using cache
{% for slave_reference, slave_configuration_section_name in cached_server_dict.iteritems() %}
{% set cached_slave_configuration_section_title = '%s-cached-virtualhost' % slave_reference %}
{% do part_list.append(cached_slave_configuration_section_title) %}
[{{ cached_slave_configuration_section_title }}]
< = jinja2-template-base
template = {{ template_cached_slave_configuration }}
filename = {{ '%s.conf' % slave_reference }}
rendered = {{ caddy_cached_configuration_directory }}/${:filename}
extensions = jinja2.ext.do
extra-context =
section slave_parameter {{ slave_configuration_section_name }}
raw cached_port {{ cached_port }}
raw ssl_cached_port {{ ssl_cached_port }}
raw local_ipv4 {{ local_ipv4 }}
{{ '\n' }}
{% endfor %}
[slave-log-directories]
<= slave-log-directory-dict
recipe = slapos.cookbook:mkdirectory
{#- Define IPv6 to IPV4 tunneling #}
[tunnel-6to4-base]
recipe = slapos.cookbook:wrapper
ipv4 = ${slap-network-information:local-ipv4}
ipv6 = ${slap-network-information:global-ipv6}
wrapper-path = {{ service_directory}}/6tunnel-${:ipv6-port}
command-line = {{ sixtunnel_executable }} -6 -4 -d -l ${:ipv6} ${:ipv6-port} ${:ipv4} ${:ipv4-port}
[tunnel-6to4-base-http_port]
<= tunnel-6to4-base
ipv4-port = {{ http_port }}
ipv6-port = {{ http_port }}
[tunnel-6to4-base-https_port]
<= tunnel-6to4-base
ipv4-port = {{ https_port }}
ipv6-port = {{ https_port }}
[tunnel-6to4-base-cached_port]
<= tunnel-6to4-base
ipv4-port = {{ cached_port }}
ipv6-port = {{ cached_port }}
[tunnel-6to4-base-ssl_cached_port]
<= tunnel-6to4-base
ipv4-port = {{ ssl_cached_port }}
ipv6-port = {{ ssl_cached_port }}
[tunnel-6to4-base-nginx_http_port]
<= tunnel-6to4-base
ipv4-port = {{ nginx_http_port }}
ipv6-port = {{ nginx_http_port }}
[tunnel-6to4-base-nginx_https_port]
<= tunnel-6to4-base
ipv4-port = {{ nginx_https_port }}
ipv6-port = {{ nginx_https_port }}
{# Define log access #}
[caddy-log-access]
< = jinja2-template-base
template = {{frontend_configuration.get('template-log-access')}}
rendered = {{frontend_configuration.get('log-access-configuration')}}
extra-context =
section slave_log_directory slave-log-directory-dict
section slave_password slave-password
raw caddy_log_directory {{caddy_log_directory}}
raw caddy_configuration_directory {{caddy_configuration_directory}}
raw local_ipv4 {{ local_ipv4 }}
raw global_ipv6 {{ global_ipv6 }}
raw https_port {{ https_port }}
raw http_port {{ http_port }}
raw login_certificate {{ login_certificate }}
raw login_key {{ login_key }}
raw access_log {{ access_log }}
raw error_log {{ error_log }}
raw not_found_file {{ not_found_file }}
{# Publish information for the instance #}
[publish-caddy-information]
recipe = slapos.cookbook:publish
public-ipv4 = {{ public_ipv4 }}
private-ipv4 = {{ local_ipv4 }}
{% if extra_slave_instance_list %}
slave-instance-information-list = {{ json_module.dumps(slave_instance_information_list) }}
{% endif %}
monitor-base-url = {{ monitor_base_url }}
[buildout]
parts +=
slave-log-directories
{% for part in part_list %}
{{ ' %s' % part }}
{% endfor %}
publish-caddy-information
caddy-log-access
tunnel-6to4-base-http_port
tunnel-6to4-base-https_port
tunnel-6to4-base-cached_port
tunnel-6to4-base-ssl_cached_port
tunnel-6to4-base-nginx_http_port
tunnel-6to4-base-nginx_https_port
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
cache-access = {{ cache_access }}
{% endif %}
#!/bin/bash
PID=$$
PIDFILE={{ pid_file }}
sleep $((RANDOM % 10))
if [ ! -f $PIDFILE ]; then
echo $PID > $PIDFILE
sleep {{ wait_time }}
{{ lazy_command }}
else
ps --pid `cat $PIDFILE` &>/dev/null
if [ $? -eq 0 ]; then
echo "Skipped"
else
echo $PID > $PIDFILE
sleep {{ wait_time }}
{{ lazy_command }}
fi
fi
{%- set TRUE_VALUES = ['y', 'yes', '1', 'true'] %}
{%- set server_alias_list = slave_parameter.get('server-alias', '').split() %}
{%- set ssl_proxy_verify = ('' ~ slave_parameter.get('ssl-proxy-verify', '')).lower() in TRUE_VALUES %}
{%- set host_list = [slave_parameter.get('custom_domain')] + server_alias_list %}
{%- set http_backend_host_list = [] %}
{%- set https_backend_host_list = [] %}
{%- for host in host_list %}
{%- do http_backend_host_list.append('http://%s:%s' % (host, cached_port)) %}
{%- do https_backend_host_list.append('http://%s:%s' % (host, ssl_cached_port)) %}
{%- endfor %}
# SSL-disabled backends
{{ http_backend_host_list|join(', ') }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
{%- if ssl_proxy_verify and 'ssl_proxy_ca_crt' in slave_parameter %}
status 501 /
{%- endif %}
# Rewrite part
proxy / {{ slave_parameter.get('backend_url', '') }} {
# As backend is trusting REMOTE_USER header unset it always
header_upstream -REMOTE_USER
transparent
timeout 600s
{%- if ssl_proxy_verify %}
{%- if 'ssl_proxy_ca_crt' in slave_parameter %}
{%- endif %}
{%- else %}
insecure_skip_verify
{%- endif %}
}
}
# SSL-enabled backends
{{ https_backend_host_list|join(', ') }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
{%- if ssl_proxy_verify and 'ssl_proxy_ca_crt' in slave_parameter %}
status 501 /
{%- endif %}
proxy / {{ slave_parameter.get('https_backend_url', '') }} {
# As backend is trusting REMOTE_USER header unset it always
header_upstream -REMOTE_USER
transparent
timeout 600s
{%- if ssl_proxy_verify %}
{%- if 'ssl_proxy_ca_crt' in slave_parameter %}
{%- endif %}
{%- else %}
insecure_skip_verify
{%- endif %}
}
}
#!/bin/sh
RUN_DIR={{ directory_run }}
ETC_DIR={{ directory_etc }}
BIN_DIR={{ directory_bin }}
CADDY_SIGNATURE_FILE=$RUN_DIR/caddy_configuration.signature
NCADDY_SIGNATURE_FILE=$RUN_DIR/ncaddy_configuration.signature
touch $CADDY_SIGNATURE_FILE
sha256sum $ETC_DIR/Caddyfile $ETC_DIR/log-access.conf $ETC_DIR/caddy-*.d/*.conf $ETC_DIR/caddy-*.d/ssl/*.*key $ETC_DIR/caddy-*.d/ssl/*.*crt* | sort -k 66 > $NCADDY_SIGNATURE_FILE
# If no diff, no restart for now
if diff "$CADDY_SIGNATURE_FILE" "$NCADDY_SIGNATURE_FILE"; then
echo "Nothing Changed, so nothing to reload"
exit 0
fi
echo "Reloading caddy.."
{{ caddy_graceful_reload_command }}
mv "$NCADDY_SIGNATURE_FILE" "$CADDY_SIGNATURE_FILE"
#!${dash-output:dash}
exec {{ caddy }} \
-conf {{ conf }} \
-log {{ log }} \
-http2=true \
-grace {{ grace }}s \
-disable-http-challenge \
-disable-tls-sni-challenge \
"$@"
{{ slave_parameter.get('apache_custom_https', '') }}
{{ slave_parameter.get('apache_custom_http', '') }}
\ No newline at end of file
{%- set TRUE_VALUES = ['y', 'yes', '1', 'true'] %}
{%- set disable_no_cache_header = ('' ~ slave_parameter.get('disable-no-cache-request', '')).lower() in TRUE_VALUES %}
{%- set disable_via_header = ('' ~ slave_parameter.get('disable-via-header', '')).lower() in TRUE_VALUES %}
{%- set prefer_gzip = ('' ~ slave_parameter.get('prefer-gzip-encoding-to-backend', '')).lower() in TRUE_VALUES %}
{%- set server_alias_list = slave_parameter.get('server-alias', '').split() %}
{%- set enable_h2 = ('' ~ slave_parameter.get('enable-http2', slave_parameter['enable_http2_by_default'])).lower() in TRUE_VALUES %}
{%- set ssl_proxy_verify = ('' ~ slave_parameter.get('ssl-proxy-verify', '')).lower() in TRUE_VALUES %}
{%- set disabled_cookie_list = slave_parameter.get('disabled-cookie-list', '').split() %}
{%- set https_only = ('' ~ slave_parameter.get('https-only', '')).lower() in TRUE_VALUES %}
{%- set slave_type = slave_parameter.get('type', '') %}
{%- set host_list = [slave_parameter.get('custom_domain')] + server_alias_list %}
{%- set backend_url = slave_parameter.get('https-url', slave_parameter.get('url', '')) %}
{%- set http_host_list = [] %}
{%- set https_host_list = [] %}
{%- for host in host_list %}
{%- do http_host_list.append('http://%s:%s' % (host, http_port)) %}
{%- do https_host_list.append('https://%s:%s' % (host, https_port)) %}
{%- endfor %}
# SSL enabled hosts
{{ https_host_list|join(', ') }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
{%- if ssl_proxy_verify and 'ssl_proxy_ca_crt' in slave_parameter %}
status 501 /
{%- endif %}
tls {{ slave_parameter.get('path_to_ssl_crt', slave_parameter.get('login_certificate')) }} {{ slave_parameter.get('path_to_ssl_key', slave_parameter.get('login_key')) }} {
{%- if slave_parameter.get('path_to_ssl_ca_crt') %}
# Configuration of accepted clients
clients {{ slave_parameter.get('path_to_ssl_ca_crt') }}
{%- endif %}
{%- if enable_h2 %}
# Allow HTTP2
alpn h2 http/1.1
{%- else %}
# Disallow HTTP2
alpn http/1.1
{%- endif %}
}
log / {{ slave_parameter.get('access_log') }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ slave_parameter.get('error_log') }}
{%- for disabled_cookie in disabled_cookie_list %}
{%- endfor %}
{%- if prefer_gzip %}
{%- endif %}
{%- if slave_type == 'zope' and backend_url %}
# Zope configuration
proxy / {{ backend_url }} {
# As backend is trusting REMOTE_USER header unset it always
header_upstream -REMOTE_USER
{%- if disable_via_header %}
header_downstream -Via
{%- endif %}
{%- if disable_no_cache_header %}
header_upstream -Cache-Control
header_upstream -Pragma
{%- endif %}
transparent
timeout 600s
{%- if ssl_proxy_verify %}
{%- if 'ssl_proxy_ca_crt' in slave_parameter %}
{%- endif %}
{%- else %}
insecure_skip_verify
{%- endif %}
}
{%- if 'default-path' in slave_parameter %}
redir 301 {
if {path} is /
/ {scheme}://{host}/{{ slave_parameter.get('default-path') }}
}
{%- endif %}
rewrite {
regexp (.*)
to /VirtualHostBase/{scheme}%2F%2F{hostonly}:{{ slave_parameter.get('virtualhostroot-https-port', '443') }}%2F{{ slave_parameter.get('path', '') }}%2FVirtualHostRoot/{1}
}
{%- elif slave_type == 'redirect' and backend_url %}
# Redirect configuration
redir 302 {
/ {{ backend_url }}{uri}
}
{%- else %}
# Default configuration
{%- if 'default-path' in slave_parameter %}
redir 301 {
if {path} is /
/ {scheme}://{host}/{{ slave_parameter.get('default-path') }}
}
{%- endif %}
{%- if backend_url %}
proxy / {{ backend_url }} {
# As backend is trusting REMOTE_USER header unset it always
header_upstream -REMOTE_USER
{%- if disable_via_header %}
header_downstream -Via
{%- endif %}
{%- if disable_no_cache_header %}
header_upstream -Cache-Control
header_upstream -Pragma
{%- endif %}
transparent
timeout 600s
{%- if ssl_proxy_verify %}
{%- if 'ssl_proxy_ca_crt' in slave_parameter %}
{%- endif %}
{%- else %}
insecure_skip_verify
{%- endif %}
}
{%- endif %}
{%- endif %}
}
# SSL-disabled hosts
{{ http_host_list|join(', ') }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
{%- if ssl_proxy_verify and 'ssl_proxy_ca_crt' in slave_parameter %}
status 501 /
{%- endif %}
log / {{ slave_parameter.get('access_log') }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ slave_parameter.get('error_log') }}
{%- for disabled_cookie in disabled_cookie_list %}
{%- endfor %}
{%- if prefer_gzip %}
{%- endif %}
{%- if https_only %}
# Enforced redirection to SSL-enabled host
redir / https://{host}{uri}
{%- elif slave_type == 'redirect' and slave_parameter.get('url', '') %}
# Redirect configuration
redir 302 {
/ {{ slave_parameter.get('url', '') }}{uri}
}
{%- elif slave_type == 'zope' and backend_url %}
# Zope configuration
proxy / {{ backend_url }} {
# As backend is trusting REMOTE_USER header unset it always
header_upstream -REMOTE_USER
{%- if disable_via_header %}
header_downstream -Via
{%- endif %}
{%- if disable_no_cache_header %}
header_upstream -Cache-Control
header_upstream -Pragma
{%- endif %}
transparent
timeout 600s
{%- if ssl_proxy_verify %}
{%- if 'ssl_proxy_ca_crt' in slave_parameter %}
{%- endif %}
{%- else %}
insecure_skip_verify
{%- endif %}
}
{%- if 'default-path' in slave_parameter %}
redir 301 {
if {path} is /
/ {scheme}://{host}/{{ slave_parameter.get('default-path') }}
}
{%- endif %}
rewrite {
regexp (.*)
to /VirtualHostBase/{scheme}%2F%2F{hostonly}:{{ slave_parameter.get('virtualhostroot-http-port', '80') }}%2F{{ slave_parameter.get('path', '') }}%2FVirtualHostRoot/{1}
}
{%- else %}
# Default configuration
{%- if 'default-path' in slave_parameter %}
redir 301 {
if {path} is /
/ {scheme}://{host}/{{ slave_parameter.get('default-path') }}
}
{%- endif %}
{%- if slave_parameter.get('url', '') %}
proxy / {{ slave_parameter.get('url', '') }} {
# As backend is trusting REMOTE_USER header unset it always
header_upstream -REMOTE_USER
{%- if disable_via_header %}
header_downstream -Via
{%- endif %}
{%- if disable_no_cache_header %}
header_upstream -Cache-Control
header_upstream -Pragma
{%- endif %}
transparent
timeout 600s
{%- if ssl_proxy_verify %}
{%- if 'ssl_proxy_ca_crt' in slave_parameter %}
{%- endif %}
{%- else %}
insecure_skip_verify
{%- endif %}
}
{%- endif %}
{%- endif %}
}
{% set url = slave_parameter.get('url') %}
{% set https_url = slave_parameter.get('https-url', url) %}
{% if url.startswith("http://") or url.startswith("https://") %}
{% set upstream = url.split("/")[2] %}
{% set https_upstream = https_url.split("/")[2] %}
{% set protocol = url.split("/")[0] %}
{% set https_protocol = https_url.split("/")[0] %}
{% set proxy_pass = '%s//%s' % (protocol, slave_parameter.get('slave_reference')) %}
{% set https_proxy_pass = '%s//https_%s' % (protocol, slave_parameter.get('slave_reference')) %}
{% set ssl_configuration_list = [('ssl_certificate', 'path_to_ssl_crt'),
('ssl_certificate_key', 'path_to_ssl_key')] %}
# TODO-Caddy upstream {{ slave_parameter.get('slave_reference') }} {
# TODO-Caddy server {{ upstream }};
# TODO-Caddy
# TODO-Caddy pstream https_{{ slave_parameter.get('slave_reference') }} {
# TODO-Caddy server {{ https_upstream }};
# TODO-Caddy
# TODO-Caddy server {
# TODO-Caddy listen {{ local_ipv4 }}:{{ nginx_http_port }};
# TODO-Caddy
# TODO-Caddy server_name {{ slave_parameter.get('custom_domain') }};
# TODO-Caddy
# TODO-Caddy error_log {{ slave_parameter.get('error_log') }} error;
# TODO-Caddy access_log {{ slave_parameter.get('access_log') }} custom;
# TODO-Caddy
# TODO-Caddy location /pub {
# TODO-Caddy push_stream_publisher;
# TODO-Caddy push_stream_channels_path $arg_id;
# TODO-Caddy # store messages in memory
# TODO-Caddy push_stream_store_messages off;
# TODO-Caddy
# TODO-Caddy # Message size limit
# TODO-Caddy # client_max_body_size MUST be equal to client_body_buffer_size or
# TODO-Caddy # you will be sorry.
# TODO-Caddy client_max_body_size 16k;
# TODO-Caddy client_body_buffer_size 16k;
# TODO-Caddy
# TODO-Caddy }
# TODO-Caddy
# TODO-Caddy location ~ /sub/(.*) {
# TODO-Caddy # activate subscriber mode for this location
# TODO-Caddy add_header "Access-Control-Allow-Origin" "*";
# TODO-Caddy add_header 'Access-Control-Allow-Credentials' 'false';
# TODO-Caddy add_header 'Access-Control-Allow-Methods' 'GET, HEAD, OPTIONS';
# TODO-Caddy add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';
# TODO-Caddy
# TODO-Caddy push_stream_subscriber eventsource;
# TODO-Caddy # positional channel path
# TODO-Caddy push_stream_channels_path $1;
# TODO-Caddy
# TODO-Caddy # content-type
# TODO-Caddy default_type "text/event-stream; charset=utf-8";
# TODO-Caddy }
# TODO-Caddy
# TODO-Caddy
# TODO-Caddy server {
# TODO-Caddy listen {{ local_ipv4 }}:{{ nginx_https_port }} ssl;
# TODO-Caddy
# TODO-Caddy server_name {{ slave_parameter.get('custom_domain') }};
# TODO-Caddy
# TODO-Caddy error_log {{ slave_parameter.get('error_log') }} error;
# TODO-Caddy access_log {{ slave_parameter.get('access_log') }} custom;
# TODO-Caddy
# TODO-Caddy ssl on;
# TODO-Caddy
# TODO-Caddy ssl_session_timeout 5m;
# TODO-Caddy ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# TODO-Caddy ssl_ciphers 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5';
# TODO-Caddy ssl_prefer_server_ciphers on;
# TODO-Caddy ssl_session_cache shared:SSL:10m;
{% for key, value in ssl_configuration_list %}
{% if value in slave_parameter %}
# TODO-Caddy {{ ' %s' % key }} {{ slave_parameter.get(value) }};
{% endif %}
{% endfor %}
# TODO-Caddy location /pub {
# TODO-Caddy push_stream_publisher;
# TODO-Caddy push_stream_channels_path $arg_id;
# TODO-Caddy # store messages in memory
# TODO-Caddy push_stream_store_messages off;
# TODO-Caddy
# TODO-Caddy # Message size limit
# TODO-Caddy # client_max_body_size MUST be equal to client_body_buffer_size or
# TODO-Caddy # you will be sorry.
# TODO-Caddy client_max_body_size 16k;
# TODO-Caddy client_body_buffer_size 16k;
# TODO-Caddy
# TODO-Caddy }
# TODO-Caddy
# TODO-Caddy location ~ /sub/(.*) {
# TODO-Caddy # activate subscriber mode for this location
# TODO-Caddy add_header "Access-Control-Allow-Origin" "*";
# TODO-Caddy add_header 'Access-Control-Allow-Credentials' 'false';
# TODO-Caddy add_header 'Access-Control-Allow-Methods' 'GET, HEAD, OPTIONS';
# TODO-Caddy add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';
# TODO-Caddy
# TODO-Caddy push_stream_subscriber eventsource;
# TODO-Caddy # positional channel path
# TODO-Caddy push_stream_channels_path $1;
# TODO-Caddy
# TODO-Caddy # content-type
# TODO-Caddy default_type "text/event-stream; charset=utf-8";
# TODO-Caddy }
# TODO-Caddy}
{% endif %}
{%- set url = slave_parameter.get('url') %}
{%- set https_url = slave_parameter.get('https-url', url) %}
{%- if url.startswith("http://") or url.startswith("https://") %}
{%- set upstream = url.split("/")[2] %}
{%- set https_upstream = https_url.split("/")[2] %}
# SSL-enabled
https://{{ slave_parameter.get('custom_domain') }}:{{ nginx_https_port }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
log / {{ slave_parameter.get('access_log') }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ slave_parameter.get('error_log') }}
tls {{ slave_parameter.get('path_to_ssl_crt', slave_parameter.get('login_certificate')) }} {{ slave_parameter.get('path_to_ssl_key', slave_parameter.get('login_key')) }} {
{%- if slave_parameter.get('path_to_ssl_ca_crt') %}
clients {{ slave_parameter.get('path_to_ssl_ca_crt') }}
{%- endif %}
alpn http/1.1
}
proxy / {{ https_upstream }} {
transparent
insecure_skip_verify
}
rewrite {
regexp "/(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/?"
to /proxy/{1}
}
proxy /proxy/ {{ https_upstream }} {
header_upstream X-Real-IP {remote}
header_upstream Host {host}
websocket
without /proxy/
insecure_skip_verify
}
}
# SSL-disabled
http://{{ slave_parameter.get('custom_domain') }}:{{ nginx_http_port }} {
bind {{ local_ipv4 }}
# Compress the output
gzip
log / {{ slave_parameter.get('access_log') }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ slave_parameter.get('error_log') }}
proxy / {{ upstream }} {
transparent
insecure_skip_verify
}
rewrite {
regexp "/(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/?"
to /proxy/{1}
}
proxy /proxy/ {{ upstream }} {
header_upstream X-Real-IP {remote}
header_upstream Host {host}
websocket
without /proxy/
insecure_skip_verify
}
}
{%- endif %}
# TODO-Caddy worker_processes $${nginx-configuration:worker_processes};
# TODO-Caddy events {
# TODO-Caddy worker_connections $${nginx-configuration:worker_connections};
# TODO-Caddy # multi_accept on;
# TODO-Caddy }
# TODO-Caddy http {
##
# Basic Settings
##
# TODO-Caddy sendfile on;
# TODO-Caddy tcp_nopush on;
# TODO-Caddy tcp_nodelay on;
# TODO-Caddy keepalive_timeout 65;
# TODO-Caddy types_hash_max_size 2048;
# TODO-Caddy server_tokens off;
# TODO-Caddy log_format custom '$remote_addr - $remote_user $time_local $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';
# TODO-Caddy access_log $${nginx-configuration:access_log} custom;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
# TODO-Caddy default_type application/octet-stream;
# TODO-Caddy ssl_certificate $${ca-frontend:cert-file};
# TODO-Caddy ssl_certificate_key $${ca-frontend:key-file};
##
# Gzip Settings
##
# TODO-Caddy gzip on;
# TODO-Caddy gzip_disable "msie6";
# TODO-Caddy gzip_vary on;
# TODO-Caddy gzip_proxied any;
# TODO-Caddy gzip_comp_level 6;
# TODO-Caddy gzip_buffers 16 8k;
# TODO-Caddy gzip_http_version 1.1;
# TODO-Caddy gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
##
# Push stream Settings
##
# TODO-Caddy push_stream_shared_memory_size 32m;
# TODO-Caddy fastcgi_temp_path $${directory:varnginx} 1 2;
# TODO-Caddy uwsgi_temp_path $${directory:varnginx} 1 2;
# TODO-Caddy scgi_temp_path $${directory:varnginx} 1 2;
# TODO-Caddy client_body_temp_path $${directory:varnginx} 1 2;
# TODO-Caddy proxy_temp_path $${directory:varnginx} 1 2;
# TODO-Caddy }
import {{ slave_configuration_directory }}/*.conf
# Catch-all and 404 for not configured instances
:{{ port }} {
tls {{ ssl_certificate }} {{ ssl_key }}
bind {{ local_ip }}
# Serve an error 204 (No Content) for favicon.ico
status 204 /favicon.ico
status 404 /
log / {{ access_log }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ error_log }} {
* {{ not_found_file }}
}
}
:{{ plain_port }} {
bind {{ local_ip }}
# Serve an error 204 (No Content) for favicon.ico
status 204 /favicon.ico
status 404 /
log / {{ access_log }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ error_log }} {
* {{ not_found_file }}
}
}
<html>
<head>
<title>Instance not found</title>
</head>
<body>
<h1>This instance has not been found.</h1>
<p>If this error persists, please check your instance URL and status on SlapOS Master.</p>
</body>
</html>
{% set part_list = [] %}
{% set slave_information_dict = {} %}
# regroup slave information from all frontends
{% for frontend, slave_list_raw in slave_information.iteritems() %}
{% if slave_list_raw %}
{% set slave_list = json_module.loads(slave_list_raw) %}
{% else %}
{% set slave_list = [] %}
{% endif %}
{% for slave_dict in slave_list %}
{% set slave_reference = slave_dict.pop('slave-reference') %}
{% set log_access_url = slave_dict.pop('log-access', '') %}
{% set current_slave_dict = slave_information_dict.get(slave_reference, {}) %}
{% do current_slave_dict.update(slave_dict) %}
{% set log_access_list = current_slave_dict.get('log-access-urls', []) %}
{% do log_access_list.append( frontend + ': ' + log_access_url) %}
{% do current_slave_dict.__setitem__(
'log-access-urls',
log_access_list
) %}
{% do current_slave_dict.__setitem__(
'replication_number',
current_slave_dict.get('replication_number', 0) + 1
) %}
{% do slave_information_dict.__setitem__(slave_reference, current_slave_dict) %}
{% endfor %}
{% endfor %}
# Publish information for each slave
{% for slave_reference, slave_information in slave_information_dict.iteritems() %}
{% set publish_section_title = 'publish-%s' % slave_reference %}
{% do part_list.append(publish_section_title) %}
[{{ publish_section_title }}]
recipe = slapos.cookbook:publish
-slave-reference = {{ slave_reference }}
log-access-url = {{ json_module.dumps(slave_information.pop('log-access-urls', 1000)) }}
{% for key, value in slave_information.iteritems() %}
{{ key }} = {{ value }}
{% endfor %}
{% endfor %}
[buildout]
parts =
{% for part in part_list %}
{{ ' %s' % part }}
{% endfor %}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
\ No newline at end of file
{% for slave, directory in slave_log_directory.iteritems() %}
https://[{{ global_ipv6 }}]:{{ https_port }}/{{ slave }}, https://{{ local_ipv4 }}:{{ https_port }}/{{ slave }} {
bind {{ local_ipv4 }}
root {{directory}}/
browse
tls {{ login_certificate }} {{ login_key }}
basicauth "{{ slave }}" {{ slave_password[slave] }} {
"Log Access {{ slave }}"
/
}
log / {{ access_log }} "{remote} {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}"
errors {{ error_log }} {
* {{ not_found_file }}
}
}
{% endfor %}
#
#
# Process Records Config File
#
# <RECORD-TYPE> <NAME> <TYPE> <VALUE (till end of line)>
#
# RECORD-TYPE: CONFIG, LOCAL
# NAME: name of variable
# TYPE: INT, STRING, FLOAT
# VALUE: Initial value for record
#
#
# *NOTE*: All options covered in this file should be documented in the
# administration guide or the addendum:
#
#
##############################################################################
#
# System Variables
#
##############################################################################
CONFIG proxy.config.proxy_name STRING {{ ats_configuration['hostname'] }}
CONFIG proxy.config.local_state_dir {{ ats_directory['local-state'] }}
CONFIG proxy.config.config_dir STRING {{ ats_directory['configuration'] }}
CONFIG proxy.config.bin_path STRING {{ ats_directory['bin_path'] }}
CONFIG proxy.config.proxy_binary_opts STRING -M
CONFIG proxy.config.env_prep STRING example_prep.sh
CONFIG proxy.config.alarm_email STRING nobody
CONFIG proxy.config.syslog_facility STRING LOG_DAEMON
CONFIG proxy.config.output.logfile STRING traffic.out
CONFIG proxy.config.snapshot_dir STRING snapshots
CONFIG proxy.config.system.mmap_max INT 2097152
##############################################################################
#
# Main threads configuration (worker threads). Also see configurations for
# SSL threads, disk I/O threads and task threads in their respective areas.
#
##############################################################################
CONFIG proxy.config.exec_thread.autoconfig INT 1
CONFIG proxy.config.exec_thread.autoconfig.scale FLOAT 1.5
CONFIG proxy.config.exec_thread.limit INT 2
CONFIG proxy.config.accept_threads INT 1
##############################################################################
#
# Local Manager
#
##############################################################################
CONFIG proxy.config.admin.admin_user STRING admin
CONFIG proxy.config.admin.number_config_bak INT 3
CONFIG proxy.config.admin.user_id STRING {{ '#%s' % os_module.geteuid() }}
##############################################################################
#
# Process Manager
#
##############################################################################
CONFIG proxy.config.admin.autoconf_port INT {{ ats_configuration.get('autoconf-port', '8083') }}
CONFIG proxy.config.process_manager.mgmt_port INT {{ ats_configuration.get('mgmt-port', '8084') }}
##############################################################################
#
# In order to only bind a specific IP, use the following config, as in
# the example below. Note - this can contain two addresses, one for IPv4
# sockets and one for IPv6 sockets.
#
##############################################################################
LOCAL proxy.local.incoming_ip_to_bind STRING {{ ats_configuration['local-ip'] }}
#LOCAL proxy.local.outgoing_ip_to_bind STRING 10.0.143.32
#LOCAL proxy.local.incoming_ip_to_bind STRING 192.168.101.17 fc07:192:168:101::17
##############################################################################
#
# Alarm Configuration
#
##############################################################################
# execute alarm as "<abs_path>/<bin> "<MSG_STRING_FROM_PROXY>""
CONFIG proxy.config.alarm.bin STRING example_alarm_bin.sh
CONFIG proxy.config.alarm.abs_path STRING NULL
##############################################################################
#
# HTTP Engine
#
##############################################################################
##########
# basics #
##########
# The server ports are listed here. These are separated by spaces or commas.
# Each port is a colon separated list of values, which must include a
# port number. The order is irrelevant. Other options are
# ipv4 - Use IPv4 (default)
# ipv6 - Use IPv6
# tr-in - Transparent inbound.
# tr-out - Transparent outbound.
# tr-full - Fully transparent (inbound and outbound).
# tr-pass - Transparently Pass-through non-HTTP traffic (in conjuction with tr-in).
# ssl - SSL terminated port.
# blind - Blind tunnel port (CONNECT only)
# ip-in=[addr] - Bind inbound IP address (listen for client).
# ip-out=[addr] - Bind outbound IP address (connect to origin server).
# ip-resolve=[style] - Set the IP resolution style.
#
# Note - address types must agree with each other and the ipv4/ipv6
# option if specified. IPv6 addresses must be enclosed in brackets.
# ip-out can be repeated as long as each address is a different
# family. If ip-in is specified as an IPv6 address, the port is
# forced to IPv6. Transparent ports cannot be bound to an IP
# address on the transparent side.
#
# The '=' is optional for any option with a value.
#
# Example 1: Port 8080 IPv6 inbound transparent, and port 80 IPv4
# "8080:ipv6:tr-in 80"
#
# Example 2: Listen on standard http and https ports for IPv4 and IPv6,
# fully transparent on the http ports. Also provide an non-transparent
# port at address 192.168.1.56 on port 8080.
# "80:ipv4:tr-full tr-full:80:ipv6 443:ipv4:ssl 443:ssl:ipv6 ip-in=192.168.1.56:8080"
#
CONFIG proxy.config.http.server_ports STRING {{ ats_configuration['local-ip'] + ':' + ats_configuration['input-port'] }}
# Ports on the origin server to which a blind tunnel may connect.
CONFIG proxy.config.http.connect_ports STRING 443 563
# The via settings have four values
# 0 - Do not modify / set this via header
# 1 - Update the via, with normal verbosity
# 2 - Update the via, with higher verbosity
# 3 - Update the via, with highest verbosity
CONFIG proxy.config.http.insert_request_via_str INT 2
CONFIG proxy.config.http.insert_response_via_str INT 2
# Insert a Server: header, this has three values
# 0 - Don't add or modify the Server: header
# 1 - Add a Server: header
# 2 - Only add a Server: header if one doesn't exist already
CONFIG proxy.config.http.response_server_enabled INT 1
CONFIG proxy.config.http.insert_age_in_response INT 1
CONFIG proxy.config.http.enable_url_expandomatic INT 0
CONFIG proxy.config.http.no_dns_just_forward_to_parent INT 0
CONFIG proxy.config.http.uncacheable_requests_bypass_parent INT 1
CONFIG proxy.config.http.keep_alive_enabled_in INT 1
CONFIG proxy.config.http.keep_alive_enabled_out INT 1
CONFIG proxy.config.http.chunking_enabled INT 1
# send http11 requests:
# 0 - Never
# 1 - Always
# 2 - if the server has returned http1.1 before
# 3 - if the client request is 1.1 & the server has returned 1.1 before
# If use_client_addr is set to 1, options 2 and 3 cause the proxy to use
# the client HTTP version for upstream requests.
CONFIG proxy.config.http.send_http11_requests INT 1
# Share server connections
# 0 - Never
# 1 - Share, with a single global connection pool
# 2 - Share, with a connection pool per worker thread
CONFIG proxy.config.http.share_server_sessions INT 2
##########################
# HTTP referer filtering #
##########################
CONFIG proxy.config.http.referer_filter INT 0
CONFIG proxy.config.http.referer_format_redirect INT 0
CONFIG proxy.config.http.referer_default_redirect STRING http://www.example.com/
##############################
# parent proxy configuration #
##############################
CONFIG proxy.config.http.parent_proxy_routing_enable INT 0
CONFIG proxy.config.http.parent_proxy.retry_time INT 300
# Parent fail threshold is the number of request that must
# fail within the retry window for the parent to be marked
# down
CONFIG proxy.config.http.parent_proxy.fail_threshold INT 10
CONFIG proxy.config.http.parent_proxy.total_connect_attempts INT 4
CONFIG proxy.config.http.parent_proxy.per_parent_connect_attempts INT 2
CONFIG proxy.config.http.parent_proxy.connect_attempts_timeout INT 30
CONFIG proxy.config.http.forward.proxy_auth_to_parent INT 0
###################################
# HTTP connection timeouts (secs) #
###################################
# out: proxy -> origin server connection
# in : ua -> proxy connection
CONFIG proxy.config.http.keep_alive_no_activity_timeout_in INT 115
CONFIG proxy.config.http.keep_alive_no_activity_timeout_out INT 120
CONFIG proxy.config.http.transaction_no_activity_timeout_in INT 300
CONFIG proxy.config.http.transaction_no_activity_timeout_out INT 300
CONFIG proxy.config.http.transaction_active_timeout_in INT 900
CONFIG proxy.config.http.transaction_active_timeout_out INT 0
CONFIG proxy.config.http.accept_no_activity_timeout INT 120
CONFIG proxy.config.http.background_fill_active_timeout INT 60
CONFIG proxy.config.http.background_fill_completed_threshold FLOAT 0.5
##################################
# origin server connect attempts #
##################################
CONFIG proxy.config.http.connect_attempts_max_retries INT 1
CONFIG proxy.config.http.connect_attempts_max_retries_dead_server INT 3
CONFIG proxy.config.http.connect_attempts_rr_retries INT 3
CONFIG proxy.config.http.connect_attempts_timeout INT 160
CONFIG proxy.config.http.post_connect_attempts_timeout INT 1800
CONFIG proxy.config.http.down_server.cache_time INT 300
CONFIG proxy.config.http.down_server.abort_threshold INT 10
##################################
# congestion control #
##################################
CONFIG proxy.config.http.congestion_control.enabled INT 0
#############################
# negative response caching #
#############################
CONFIG proxy.config.http.negative_caching_enabled INT 0
CONFIG proxy.config.http.negative_caching_lifetime INT 1800
#########################
# proxy users variables #
#########################
CONFIG proxy.config.http.anonymize_remove_from INT 0
CONFIG proxy.config.http.anonymize_remove_referer INT 0
CONFIG proxy.config.http.anonymize_remove_user_agent INT 0
CONFIG proxy.config.http.anonymize_remove_cookie INT 0
CONFIG proxy.config.http.anonymize_remove_client_ip INT 0
CONFIG proxy.config.http.anonymize_insert_client_ip INT 1
CONFIG proxy.config.http.anonymize_other_header_list STRING NULL
CONFIG proxy.config.http.insert_squid_x_forwarded_for INT 1
############
# security #
############
CONFIG proxy.config.http.push_method_enabled INT 0
# ###################################
# # HTTP Quick filtering (security) #
# ###################################
# this functionality is moved to ip_allow.config
#################
# cache control #
#################
CONFIG proxy.config.http.cache.http INT 1
# Enabling this setting allows the proxy to cache empty documents. This currently
# requires that the response has a Content-Length: header, with a value of "0".
CONFIG proxy.config.http.cache.allow_empty_doc INT 0
CONFIG proxy.config.http.cache.ignore_client_no_cache INT 0
CONFIG proxy.config.http.cache.ims_on_client_no_cache INT 0
CONFIG proxy.config.http.cache.ignore_server_no_cache INT 0
CONFIG proxy.config.http.cache.ignore_client_cc_max_age INT 0
CONFIG proxy.config.http.normalize_ae_gzip INT 0
# cache responses to cookies has 5 options:
# 0 - do not cache any responses to cookies
# 1 - cache for any content-type
# 2 - cache only for image types
# 3 - cache for all but text content-types
# 4 - cache for all but text content-types except OS response
# without "Set-Cookie" or with "Cache-Control: public"
# See also cache-responses-to-cookies in cache.config.
CONFIG proxy.config.http.cache.cache_responses_to_cookies INT 1
CONFIG proxy.config.http.cache.ignore_authentication INT 0
CONFIG proxy.config.http.cache.cache_urls_that_look_dynamic INT 1
CONFIG proxy.config.http.cache.enable_default_vary_headers INT 0
# when_to_revalidate has 5 options:
# 0 - default. use cache directives or heuristic
# 1 - stale if heuristic
# 2 - always stale (always revalidate)
# 3 - never stale
# 4 - always revalidate if request is conditional, else default is used
CONFIG proxy.config.http.cache.when_to_revalidate INT 0
# Some old MSIE browsers don't send no-cache headers to
# reverse proxies or transparent caches, this variable controls
# when to add no-cache headers to MSIE requests:
# -1 - no-cache is never added, stats are not updated
# 0 - default; no-cache not added to MSIE requests
# 1 - no-cache added to IMS MSIE requests
# 2 - no-cache added to all MSIE requests
CONFIG proxy.config.http.cache.when_to_add_no_cache_to_msie_requests INT -1
# required headers: three options:
# 0 - No required headers to make document cachable
# 1 - "Last-Modified:", "Expires:", or "Cache-Control: max-age" required
# 2 - explicit lifetime required, "Expires:" or "Cache-Control: max-age"
CONFIG proxy.config.http.cache.required_headers INT 2
CONFIG proxy.config.http.cache.max_stale_age INT 604800
CONFIG proxy.config.http.cache.range.lookup INT 1
########################
# heuristic expiration #
########################
CONFIG proxy.config.http.cache.heuristic_min_lifetime INT 3600
CONFIG proxy.config.http.cache.heuristic_max_lifetime INT 86400
CONFIG proxy.config.http.cache.heuristic_lm_factor FLOAT 0.10
CONFIG proxy.config.http.cache.fuzz.time INT 240
CONFIG proxy.config.http.cache.fuzz.probability FLOAT 0.005
#########################################
# dynamic content & content negotiation #
#########################################
CONFIG proxy.config.http.cache.vary_default_text STRING NULL
CONFIG proxy.config.http.cache.vary_default_images STRING NULL
CONFIG proxy.config.http.cache.vary_default_other STRING NULL
##############################################################
# The HTTP stats are expensive, turn off you don't need them #
##############################################################
CONFIG proxy.config.http.enable_http_stats INT 1
##############################################################################
#
# Customizable User Response Pages
#
##############################################################################
# 1 - enable customizable user response pages in only the "default" directory
# 2 - enable language-targeted user response pages
CONFIG proxy.config.body_factory.enable_customizations INT 1
CONFIG proxy.config.body_factory.enable_logging INT 0
# 0 - never suppress generated responses
# 1 - always suppress generated responses
# 2 - suppress responses for intercepted traffic
CONFIG proxy.config.body_factory.response_suppression_mode INT 0
##############################################################################
#
# Net Subsystem
#
##############################################################################
CONFIG proxy.config.net.connections_throttle INT 30000
# Enable defer accept / accept filtering. On Linux, this is a timeout, sec.
CONFIG proxy.config.net.defer_accept INT 45
##############################################################################
#
# Cluster Subsystem
#
##############################################################################
# cluster type requires restart to change
# 1 is full clustering, 2 is mgmt only, 3 is no clustering
LOCAL proxy.local.cluster.type INT 3
CONFIG proxy.config.cluster.cluster_port INT 8086
CONFIG proxy.config.cluster.rsport INT 8088
CONFIG proxy.config.cluster.mcport INT 8089
CONFIG proxy.config.cluster.mc_group_addr STRING 224.0.1.37
CONFIG proxy.config.cluster.mc_ttl INT 1
CONFIG proxy.config.cluster.log_bogus_mc_msgs INT 1
CONFIG proxy.config.cluster.ethernet_interface STRING lo
##############################################################################
#
# Cache
#
##############################################################################
CONFIG proxy.config.cache.permit.pinning INT 0
# default the ram cache size to AUTO_SIZE (-1) based on cache size
# (approximately 10 MB of RAM cache per GB of disk cache)
# alternatively, set to a fixed value such as 21474836480 (20GB)
CONFIG proxy.config.cache.ram_cache.size INT {{ ats_configuration.get('ram-cache-size', '1G') }}
# Replacement algorithm
# 0 : Clocked Least Frequently Used by Size (CLFUS) w/optional compression
# 1 : LRU w/o optional compression - trivially simple
CONFIG proxy.config.cache.ram_cache.algorithm INT 0
# Filter inserts into the RAM cache to ensure that they have been seen at
# least once. For LRU, this provides scan resistance. Note that CLFUS
# already requires that a document have history before it is inserted, so
# for CLFUS, setting this option means that a document must be seen three
# times before it is added to the RAM cache.
CONFIG proxy.config.cache.ram_cache.use_seen_filter INT 0
# Compress the content of the ram cache:
# 0 : no compression
# 1 : fastlz (extremely fast, relatively low compression)
# 2 : libz (moderate speed, reasonable compression)
# 3 : liblzma (very slow, high compression)
# NOTE: compression runs on task threads. To use more cores for
# compression, increase proxy.config.task_threads.
CONFIG proxy.config.cache.ram_cache.compress INT 0
# The maximum number of alternates that are allowed for any given URL.
# It is not possible to strictly enforce this if the variable
# 'proxy.config.cache.vary_on_user_agent' is set to 1.
# The default value for 'proxy.config.cache.vary_on_user_agent' is 0.
# (0 disables the maximum number of alts check)
CONFIG proxy.config.cache.limits.http.max_alts INT 5
# The target size of a contiguous fragment on disk.
# Acceptable values are powers of 2, e.g. 65536, 131072, 262144, 524288, 1048576, 2097152.
# Larger could waste memory on slow connections, smaller could waste seeks.
CONFIG proxy.config.cache.target_fragment_size INT 1048576
# The maximum size of a document that will be stored in the cache.
# (0 disables the maximum document size check)
CONFIG proxy.config.cache.max_doc_size INT 0
# enable the cache to read from an object while it is being added to the cache
CONFIG proxy.config.cache.enable_read_while_writer INT 0
# How many I/O threads to allocate per disk (spindle). Be aware that RAID
# disks would show up to TS as a single spindle.
CONFIG proxy.config.cache.threads_per_disk INT 8
# Time (in ms) to delay until retrying to acquire a cache lock. Setting
# this low can reduce latencies in some cases, but can consume more CPU.
# If you experience CPU spinning, try increasing this setting.
CONFIG proxy.config.cache.mutex_retry_delay INT 2
# The interim storage disks. Must use raw disks.
# Only support at most 8 interim disks now. e.g.
# proxy.config.cache.interim.storage STRING /dev/sda /dev/sdb/
LOCAL proxy.config.cache.interim.storage STRING NULL
##############################################################################
#
# DNS
#
##############################################################################
CONFIG proxy.config.dns.search_default_domains INT 0
CONFIG proxy.config.dns.splitDNS.enabled INT 0
CONFIG proxy.config.dns.max_dns_in_flight INT 2048
# Additional URL expansions for http DNS lookup
CONFIG proxy.config.dns.url_expansions STRING NULL
CONFIG proxy.config.dns.round_robin_nameservers INT 0
CONFIG proxy.config.dns.nameservers STRING NULL
CONFIG proxy.config.dns.resolv_conf STRING /etc/resolv.conf
# This provides additional resilience against DNS forgery, particularly in
# forward or transparent proxies, but requires that the resolver populates
# the queries section of the response properly.
CONFIG proxy.config.dns.validate_query_name INT 0
##############################################################################
#
# HostDB
#
##############################################################################
# in entries, may not be changed while running
# note that in order to increase hostdb.size, hostdb.storage_size should
# also be increase. These are best guesses, you will have to monitor this.
CONFIG proxy.config.hostdb.size INT 120000
CONFIG proxy.config.hostdb.storage_size INT 32M
# ttl modes:
# 0 = obey
# 1 = ignore
# 2 = min(X,ttl)
# 3 = max(X,ttl)
CONFIG proxy.config.hostdb.ttl_mode INT 0
# in minutes...
CONFIG proxy.config.hostdb.timeout INT 1440
# round-robin addresses for single clients
# (can cause authentication problems)
CONFIG proxy.config.hostdb.strict_round_robin INT 0
##############################################################################
#
# Logging Config
#
##############################################################################
# possible values for logging_enabled:
# 0: no logging at all
# 1: log errors only
# 2: log transactions only
# 3: full logging (errors + transactions)
CONFIG proxy.config.log.logging_enabled INT 3
CONFIG proxy.config.log.max_secs_per_buffer INT 5
CONFIG proxy.config.log.max_space_mb_for_logs INT 25000
CONFIG proxy.config.log.max_space_mb_for_orphan_logs INT 25
CONFIG proxy.config.log.max_space_mb_headroom INT 1000
CONFIG proxy.config.log.hostname STRING localhost
CONFIG proxy.config.log.logfile_dir STRING {{ ats_directory['log'] }}
CONFIG proxy.config.log.logfile_perm STRING rw-r--r--
CONFIG proxy.config.log.custom_logs_enabled INT 0
CONFIG proxy.config.log.squid_log_enabled INT 1
CONFIG proxy.config.log.squid_log_is_ascii INT 0
CONFIG proxy.config.log.squid_log_name STRING squid
CONFIG proxy.config.log.squid_log_header STRING NULL
CONFIG proxy.config.log.common_log_enabled INT 0
CONFIG proxy.config.log.common_log_is_ascii INT 1
CONFIG proxy.config.log.common_log_name STRING common
CONFIG proxy.config.log.common_log_header STRING NULL
CONFIG proxy.config.log.extended_log_enabled INT 0
CONFIG proxy.config.log.extended_log_is_ascii INT 0
CONFIG proxy.config.log.extended_log_name STRING extended
CONFIG proxy.config.log.extended_log_header STRING NULL
CONFIG proxy.config.log.extended2_log_enabled INT 0
CONFIG proxy.config.log.extended2_log_is_ascii INT 1
CONFIG proxy.config.log.extended2_log_name STRING extended2
CONFIG proxy.config.log.extended2_log_header STRING NULL
CONFIG proxy.config.log.separate_icp_logs INT 0
CONFIG proxy.config.log.separate_host_logs INT 0
# Log collation allows you to do "remote logging"
LOCAL proxy.local.log.collation_mode INT 0
CONFIG proxy.config.log.collation_host STRING NULL
CONFIG proxy.config.log.collation_port INT 8085
CONFIG proxy.config.log.collation_secret STRING foobar
CONFIG proxy.config.log.collation_host_tagged INT 0
CONFIG proxy.config.log.collation_retry_sec INT 5
CONFIG proxy.config.log.rolling_enabled INT 1
CONFIG proxy.config.log.rolling_interval_sec INT 86400
CONFIG proxy.config.log.rolling_offset_hr INT 0
CONFIG proxy.config.log.rolling_size_mb INT 10
CONFIG proxy.config.log.auto_delete_rolled_files INT 1
CONFIG proxy.config.log.sampling_frequency INT 1
##############################################################################
#
# Reverse Proxy
#
##############################################################################
CONFIG proxy.config.reverse_proxy.enabled INT 1
CONFIG proxy.config.header.parse.no_host_url_redirect STRING NULL
##############################################################################
#
# URL Remap Rules
#
##############################################################################
CONFIG proxy.config.url_remap.default_to_server_pac INT 0
CONFIG proxy.config.url_remap.default_to_server_pac_port INT -1
# To enable forward proxy, you must turn off remap_required
CONFIG proxy.config.url_remap.remap_required INT 1
# Pristine host header is the "original" (request) header. Make sure your
# origin expects them in reverse proxy.
CONFIG proxy.config.url_remap.pristine_host_hdr INT 1
##############################################################################
#
# SSL Termination
#
##############################################################################
# The number of SSL threads is a multiplier of number of CPUs and
# proxy.config.exec_thread.autoconfig.scale by default. You can
# override that here (set it to a non-zero value).
CONFIG proxy.config.ssl.number.threads INT 0
# The following variables control SSL protocols.
CONFIG proxy.config.ssl.SSLv2 INT 0
CONFIG proxy.config.ssl.SSLv3 INT 0
CONFIG proxy.config.ssl.TLSv1 INT 1
CONFIG proxy.config.ssl.TLSv1_1 INT 1
CONFIG proxy.config.ssl.TLSv1_2 INT 1
# The following two variables control the Cipher Suite traffic Server
# uses for HTTPS connnections and whether to prefer the client
# selected (default) or the server selected
# Our default SSL Cipher Suite tries to be reasonably fast and strong.
CONFIG proxy.config.ssl.server.cipher_suite STRING ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5
CONFIG proxy.config.ssl.server.honor_cipher_order INT 1
# Control if SSL should perform content compression or not
CONFIG proxy.config.ssl.compression INT 0
# Client certification level should be:
# 0 no client certificates
# 1 client certificates optional
# 2 client certificates required
CONFIG proxy.config.ssl.client.certification_level INT 0
# Server cert chain filename is the name of the global cert chain file
# that is added to every cert in ssl_multicert.config. This file is only
# loaded if there are configurations in ssl_multicert.config.
CONFIG proxy.config.ssl.server.cert_chain.filename STRING NULL
# This is the path that SSL certificates files are relative to. Certificate
# names specified in ssl_multicert.config will be located relative to this path.
CONFIG proxy.config.ssl.server.cert.path STRING etc/trafficserver
# If any private key is not contained in the certificate file, you must
# fill in the private key path. Private key names specified in
# ssl_multicert.config will be located relative to this path.
CONFIG proxy.config.ssl.server.private_key.path STRING etc/trafficserver
# The CA file name and path are the
# certificate authority certificate that
# client certificates will be verified against.
CONFIG proxy.config.ssl.CA.cert.filename STRING NULL
CONFIG proxy.config.ssl.CA.cert.path STRING etc/trafficserver
################################
# client related configuration #
################################
CONFIG proxy.config.ssl.client.verify.server INT 0
CONFIG proxy.config.ssl.client.cert.filename STRING NULL
CONFIG proxy.config.ssl.client.cert.path STRING etc/trafficserver
# Fill in private key file and path only if the client's
# private key is not contained in the client certificate file.
CONFIG proxy.config.ssl.client.private_key.filename STRING NULL
CONFIG proxy.config.ssl.client.private_key.path STRING etc/trafficserver
# The CA file name and path are the
# certificate authority certificate that
# server certificates will be verified against.
CONFIG proxy.config.ssl.client.CA.cert.filename STRING NULL
CONFIG proxy.config.ssl.client.CA.cert.path STRING etc/trafficserver
##############################################################################
#
# ICP Configuration. NOTE! ICP is currently broken NOTE!
#
##############################################################################
# icp modes
# enabled=0 ICP disabled
# enabled=1 Allow receive of ICP queries
# enabled=2 Allow send/receive of ICP queries
CONFIG proxy.config.icp.enabled INT 0
CONFIG proxy.config.icp.icp_interface STRING NULL
CONFIG proxy.config.icp.icp_port INT 3130
CONFIG proxy.config.icp.multicast_enabled INT 0
CONFIG proxy.config.icp.query_timeout INT 2
##############################################################################
#
# Scheduled Update Configuration
#
##############################################################################
CONFIG proxy.config.update.enabled INT 0
CONFIG proxy.config.update.force INT 0
CONFIG proxy.config.update.retry_count INT 10
CONFIG proxy.config.update.retry_interval INT 2
CONFIG proxy.config.update.concurrent_updates INT 100
##############################################################################
#
# Socket send/recv buffer sizes (0 == don't call setsockopt() )
#
##############################################################################
# out: proxy -> os connection
# in : ua -> proxy connection
CONFIG proxy.config.net.sock_send_buffer_size_in INT 262144
CONFIG proxy.config.net.sock_recv_buffer_size_in INT 0
CONFIG proxy.config.net.sock_send_buffer_size_out INT 0
CONFIG proxy.config.net.sock_recv_buffer_size_out INT 0
##############################################################################
#
# User Overridden Configurations Below
#
##############################################################################
CONFIG proxy.config.core_limit INT -1
##############################################################################
#
# Debugging
#
##############################################################################
# Uses a regular expression to match the debugging topic name, performance
# will be affected!
CONFIG proxy.config.diags.debug.enabled INT 0
CONFIG proxy.config.diags.debug.tags STRING http.*|dns.*
# Great for tracking down memory leaks, but you need to use the
# ink allocators
CONFIG proxy.config.dump_mem_info_frequency INT 0
# Log the source code location of diagnostic messages.
CONFIG proxy.config.diags.show_location INT 0
##############################################################################
#
# Configuration for Reclaimable InkFreeList memory pool
#
# NOTE: The following options are meaningfull only when Traffic Server is
# compiled with the following option to configure:
#
# --enable-reclaimable-freelist
#
##############################################################################
CONFIG proxy.config.allocator.enable_reclaim INT 1
# The value of reclaim_factor should be in the 0.0 to 1.0 range. Allocators
# use it to calculate size of unused memory, which is used to determine when
# to reclaim memory. The larger the value, the more aggressive reclaims.
CONFIG proxy.config.allocator.reclaim_factor FLOAT 0.300000
# Allocator will reclaim memory only when it continuously satisfy the reclaim
# condition for max_overage continuous checks.
CONFIG proxy.config.allocator.max_overage INT 3
# For debugging, enable debug_filter, which is a bit-map with these fields:
# bit 0: reclaim memory in ink_freelist_new
# bit 1: allocate memory from partial-free Chunks(if exist) or OS
CONFIG proxy.config.allocator.debug_filter INT 0
##############################################################################
#
# Slow Log
#
##############################################################################
# Log any request that takes more then x number of milliseconds, needs
# to be > 0 to be enabled
CONFIG proxy.config.http.slow.log.threshold INT 0
##############################################################################
#
# Thread pool for "misc" tasks, plugins etc. 2 is a good minimum.
#
##############################################################################
CONFIG proxy.config.task_threads INT 2
{{ ats_configuration.get("cache-path") }} {{ ats_configuration.get("disk-cache-size") }} volume={{ ats_configuration.get("hostname") }}
\ No newline at end of file
#!${dash-output:dash}
{{ content }}
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIDuzCCAqOgAwIBAgIJAOzw6rzXAd+jMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxLTArBgNVBAMMJGN1c3RvbWRvbWFpbnNzbGNydHNzbGtl
eS5leGFtcGxlLmNvbTAeFw0xODA1MTgxMzA2NThaFw0yODA1MTUxMzA2NThaMHQx
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQxLTArBgNVBAMMJGN1c3RvbWRvbWFpbnNzbGNy
dHNzbGtleS5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAOQe3WLRuVBPPufClmlOk6Euc3nmycvCkzcwMUD6+zdyAGH0qhHoIHJmiXi6
GcKYgqqa3eaIxvvke2EEphDwYkj6neOVyuX3KukL8ggEUakJ17TEQkS7hIk4dmDT
wjFAMgLz8uN11jqLooo9w/ptD+LUWmm6K9zk49iqqdKuG9Z5v3dm0KMUvsmYGWqN
g31tQWU1Cm2kNu+2iP2FPnx2PWkDq4KTn64U7iJP9DdDEvzNfYcvz8upjR15B+dI
K0ihwDXV5BtfZXDvck+ctCdfS1QxM+x+PboEJKUNoefz/+Q/9T3mlc+KchFG9asL
Q/kbHtdgZzsDGTDEtdDtIrLLQ3MCAwEAAaNQME4wHQYDVR0OBBYEFG6I5Y0feayi
UPznSzRJIMS1blcNMB8GA1UdIwQYMBaAFG6I5Y0feayiUPznSzRJIMS1blcNMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKmK75LcaROfjdxQLBFqiP/I
6WB8pBNbAN6nL+dgxeQJNEx7VQXSU/3KF0nIMC35pzf93ZySMq6ujCjxksNA0Pa0
XEH0pmTqOO7Af5wsjIniLqGTRvFCqGbWKEcYDBwKq0svTGfYyPOaBj8z7lt9LURs
WRC1tCrn8T8NkAY/jdGRQZRtLlgk+x2SaeDfQ8F1MtMT8jYSLo4R+c4f+iuDgMWi
JPM5SvYeDEXndWctKGxmP4p2HIp8gJuqYHmP4oxO7Rn/QPti1p68WfNQsRquHYJ4
dR9krkpVeteQ7w8cQA9OkG/m3neiIfFKkosJSGEHctRvRQ0GtbQO6A6nZqk0n6I=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkHt1i0blQTz7n
wpZpTpOhLnN55snLwpM3MDFA+vs3cgBh9KoR6CByZol4uhnCmIKqmt3miMb75Hth
BKYQ8GJI+p3jlcrl9yrpC/IIBFGpCde0xEJEu4SJOHZg08IxQDIC8/LjddY6i6KK
PcP6bQ/i1Fppuivc5OPYqqnSrhvWeb93ZtCjFL7JmBlqjYN9bUFlNQptpDbvtoj9
hT58dj1pA6uCk5+uFO4iT/Q3QxL8zX2HL8/LqY0deQfnSCtIocA11eQbX2Vw73JP
nLQnX0tUMTPsfj26BCSlDaHn8//kP/U95pXPinIRRvWrC0P5Gx7XYGc7AxkwxLXQ
7SKyy0NzAgMBAAECggEBAOLv5ZPCSdWgEFdlWFbIycrmOBDETGo9VlDny4f2ZuZg
rgrE6E/KGkVUxlvo32mcaRkp2ajW1wWN5kO86Swex9gMIfhfcyrVecW/kXbyPP6q
AQIe4EIaPh54oiNvZleyok4Xu8EW4Bj8AqX+DjHaP5yLXqqhf7NPrW9FUI57kMwK
DqeHBilgWUxzcjc4LLiEu6UTuB8c2Slj3Ps0K/mVzvPbQ7Xx+RYXzfX+SqjyvDEe
GpaRLoiRJ0KZSoGUgBQSIqgfzR7g6ipKNDvlzsawMpG641vsQ8tSI+l4U5f6MbYZ
pFT+mxL4+N+PQbWN5w3qYWK6Ilh77+0rKfGVrLH7s7kCgYEA/2SXFnUgJUnKpuE0
4buUtPCMw8j+qZsJZ8nmf2BbwIGgp+CFGlO6aG4sfzYulpQuZOsnKRIu5qoE3xQp
MzuqWPZ8eygAubBdddaym3kPRiMAxTXPr+vBFyvti+oFflxaTsTXAfCXD2wM8yKm
Od16xg9co3NED2zt62mtSM6NOiUCgYEA5Kmt1JqL4ymMe9gBZ07Ar7GCfmmqepSb
w9XqgkHDk0ZYizNeQupPQrypfdeLFlKVnlp4DycEA4XzGdFgp1+PkAMSIVDUZZp5
KxWJdQkdScENe1eYAz0vALCWSnUahyMGuNW9Xe/z2mtNLKRYcNDQ2LROJTQjShvw
XSfVQXS597cCgYEAgXG5hn9tAJlLJpQk2njZ4W++2QkJ0msrNDjIJC1xs7u/8vbA
X9yqMX4N/Zg3ush2T15EpfN6ZB0uhObSDw6hw5+C7mUTIQq8BBsCwfx0+maJYGtq
zc6fOqBgMTc2+5nRh/UKyQfpeL6aPa2FNPUF4lcs7AdjKrJaUKRqWOmf+SUCgYAd
ksRkpshIzOraaYlk7w6EqpSR/OCLkgTDQztdNVwyA/sXpcEfLmap3vScze+zJ2Mq
Y9D7RLSEMCLMyAOUIgvTOFJz9JxDt8LMC7EHbfJXw5wWw7FpWdRmZnBJmPOhXqpT
5XDkYVBMg2wrxeWaUadxH4Cr1x5pS0u/AJPYL1yN6QKBgApwfVmCWXS0S1++6KiM
WN+jyvqmF4FS6Ib5TII1/diChY0PCO/UnmVPYg1AIqsdT5ghVreZs7wuHi1LsXQ4
41nBmUnhdaiKCz9qVybXJwvicn/2MlsIi5C4Ox97OHJyCR1iKxf5A2ypfYEuh25V
NZZ4n9p5PhcLev6x3QhuWosT
-----END PRIVATE KEY-----
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from setuptools import setup, find_packages
version = '0.0.1.dev0'
name = 'slapos.test.caddy-frontend'
setup(name=name,
version=version,
description="Test for SlapOS' Caddy Frontend",
maintainer="Nexedi",
maintainer_email="info@nexedi.com",
url="https://lab.nexedi.com/nexedi/slapos",
packages=find_packages(),
install_requires=[
'slapos.core',
'erp5.util',
'requests',
'forcediphttpsadapter',
'requests-toolbelt',
'supervisor',
],
zip_safe=True,
test_suite='test',
)
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
# Note for SSL
# This test comes with certificates and keys. There is even root Certificate
# Authority, for the backends
# Please follow https://datacenteroverlords.com/2012/03/01/\
# creating-your-own-ssl-certificate-authority/
# in order to add more certificates for backend.
# Frontend still uses self-signed certificates.
import glob
import os
import requests
from requests_toolbelt.adapters import source
import json
import multiprocessing
import subprocess
from unittest import skipIf, skip
import ssl
from BaseHTTPServer import HTTPServer
from forcediphttpsadapter.adapters import ForcedIPHTTPSAdapter
import time
import utils
# ports chosen to not collide with test systems
HTTP_PORT = '11080'
HTTPS_PORT = '11443'
NGINX_HTTP_PORT = '12080'
NGINX_HTTPS_PORT = '12443'
MONITOR_HTTPD_PORT = '13000'
MONITOR_F1_HTTPD_PORT = '13001'
MONITOR_F2_HTTPD_PORT = '13002'
if os.environ['TEST_SR'].endswith('caddy-frontend/software.cfg'):
IS_CADDY = True
else:
IS_CADDY = False
# response_code difference
if IS_CADDY:
no_backend_response_code = 404
else:
no_backend_response_code = 502
# apache_custom_http[s] difference
if IS_CADDY:
LOG_REGEXP = '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} SOME_REMOTE_USER ' \
'\[\d{2}\/.{3}\/\d{4}\:\d{2}\:\d{2}\:\d{2} \+\d{4}\] ' \
'"GET \/test-path HTTP\/1.1" 404 \d+ "-" "python-requests.*" \d+'
apache_custom_https = '''# apache_custom_https_filled_in_accepted
https://apachecustomhttpsaccepted.example.com:%%(https_port)s {
bind %%(local_ipv4)s
tls %%(ssl_crt)s %%(ssl_key)s
log / %%(access_log)s {combined}
errors %%(error_log)s
proxy / %(url)s {
transparent
timeout 600s
insecure_skip_verify
}
}
'''
apache_custom_http = '''# apache_custom_http_filled_in_accepted
http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
bind %%(local_ipv4)s
log / %%(access_log)s {combined}
errors %%(error_log)s
proxy / %(url)s {
transparent
timeout 600s
insecure_skip_verify
}
}
'''
else:
LOG_REGEXP = '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} - - ' \
'\[\d{2}\/.{3}\/\d{4}\:\d{2}\:\d{2}\:\d{2} \+\d{4}\] ' \
'"GET \/test-path HTTP\/1.1" 502 \d+ "-" "python-requests.*" \d+'
apache_custom_https = '''# apache_custom_https_filled_in_accepted
ServerName apachecustomhttpsaccepted.example.com
ServerAlias apachecustomhttpsaccepted.example.com
SSLEngine on
SSLProxyEngine on
ErrorLog %%(error_log)s
LogLevel notice
CustomLog %%(access_log)s combined
# Rewrite part
ProxyPreserveHost On
ProxyTimeout 600
RewriteEngine On
RewriteRule ^/(.*)$ %(url)s/$1 [L,P]
'''
apache_custom_http = '''# apache_custom_http_filled_in_accpeted
ServerName apachecustomhttpsaccepted.example.com
ServerAlias apachecustomhttpsaccepted.example.com
ErrorLog %%(error_log)s
LogLevel notice
CustomLog %%(access_log)s combined
# Rewrite part
ProxyPreserveHost On
ProxyTimeout 600
RewriteEngine On
RewriteRule ^/(.*)$ %(url)s/$1 [L,P]
'''
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
def isHTTP2(domain, ip):
curl_command = '%(curl)s --http2 -v -k -H "Host: %(domain)s" ' \
'https://%(domain)s:%(https_port)s/ '\
'--resolve %(domain)s:%(https_port)s:%(ip)s' % dict(
ip=ip, domain=domain, curl=os.environ['CURL'], https_port=HTTPS_PORT)
prc = subprocess.Popen(
curl_command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
out, err = prc.communicate()
assert prc.returncode == 0, "Problem running %r. Output:\n%s\nError:\n%s" % (
curl_command, out, err)
return 'Using HTTP2, server supports multi-use' in err
class TestDataMixin(object):
def getTrimmedProcessInfo(self):
return '\n'.join(sorted([
'%(group)s:%(name)s %(statename)s' % q for q
in self.getSupervisorRPCServer().supervisor.getAllProcessInfo()]))
def assertTestData(self, runtime_data):
filename = '%s-%s.txt' % (self.id(), self.frontend_type)
test_data_file = os.path.join(
os.path.dirname(os.path.realpath(__file__)), 'test_data', filename)
try:
test_data = open(test_data_file).read().strip()
except IOError:
test_data = ''
maxDiff = self.maxDiff
self.maxDiff = None
try:
self.assertMultiLineEqual(
test_data,
runtime_data
)
except AssertionError:
if os.environ.get('SAVE_TEST_DATA', '0') == '1':
open(test_data_file, 'w').write(runtime_data.strip())
raise
finally:
self.maxDiff = maxDiff
def test_promise_list(self):
runtime_data = '\n'.join(sorted([
q[len(self.instance_path) + 1:]
for q in glob.glob(os.path.join(
self.instance_path, '*', 'etc', 'promise', '*'))]))
self.assertTestData(runtime_data)
def test_monitor_promise_list(self):
runtime_data = '\n'.join(sorted([
q[len(self.instance_path) + 1:]
for q in glob.glob(os.path.join(
self.instance_path, '*', 'etc', 'monitor-promise', '*'))]))
self.assertTestData(runtime_data)
def _test_file_list(self, slave_dir, IGNORE_PATH_LIST):
runtime_data = []
for slave_var in glob.glob(os.path.join(self.instance_path, '*', 'var')):
for entry in os.walk(os.path.join(slave_var, slave_dir)):
for filename in entry[2]:
path = os.path.join(
entry[0][len(self.instance_path) + 1:], filename)
if not any([path.endswith(q) for q in IGNORE_PATH_LIST]):
runtime_data.append(path)
runtime_data = '\n'.join(sorted(runtime_data))
self.assertTestData(runtime_data)
def test_file_list_log(self):
self._test_file_list('log', [
# appears late, not needed for assertion
'trafficserver/diags.log',
'trafficserver/squid.blog',
'trafficserver/.squid.blog.meta',
])
def test_file_list_run(self):
self._test_file_list('run', [
# run by cron from time to time
'monitor/monitor-collect.pid',
])
@skipIf(not IS_CADDY, 'Feature not needed for Apache')
def test_supervisor_state(self):
# give a chance for etc/run scripts to finish
time.sleep(1)
runtime_data = self.getTrimmedProcessInfo()
self.assertTestData(runtime_data)
class HttpFrontendTestCase(utils.SlapOSInstanceTestCase):
frontend_type = 'CADDY' if IS_CADDY else 'APACHE'
def assertLogAccessUrlWithPop(self, parameter_dict, reference):
log_access_url = parameter_dict.pop('log-access-url')
try:
log_access_url_json = json.loads(log_access_url)
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (log_access_url,))
self.assertTrue(len(log_access_url_json) >= 1)
# check only the first one, as second frontend will be stopped
log_access = log_access_url_json[0]
entry = log_access.split(': ')
if len(entry) != 2:
self.fail('Cannot parse %r' % (log_access,))
frontend, url = entry
result = requests.get(url, verify=False)
self.assertEqual(
result.status_code,
200,
'While accessing %r of %r the status code was %r' % (
url, frontend, result.status_code))
def assertKeyWithPop(self, key, d):
self.assertTrue(key in d, 'Key %r is missing in %r' % (key, d))
d.pop(key)
def assertEqualResultJson(self, result, key, value):
try:
j = result.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertTrue(key in j, 'No key %r in %s' % (key, j))
self.assertEqual(j[key], value)
class TestMasterRequest(HttpFrontendTestCase, TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
}
def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
self.assertKeyWithPop('monitor-setup-url', parameter_dict)
self.assertEqual(
{
'monitor-base-url': None,
'domain': 'None',
'accepted-slave-amount': '0',
'rejected-slave-amount': '0',
'slave-amount': '0',
'rejected-slave-list': '[]'},
parameter_dict
)
@skip('Feature postponed')
def test_caddy_key_caddy_certificate(self):
# Caddy: Need to use caddy_key and caddy_certificate with backward
# compatilibty to apache_key and apache_certificate
raise NotImplementedError
class TestMasterRequestDomain(HttpFrontendTestCase, TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'domain': 'example.com',
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
}
def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
self.assertKeyWithPop('monitor-setup-url', parameter_dict)
self.assertEqual(
{
'monitor-base-url': None,
'domain': 'example.com',
'accepted-slave-amount': '0',
'rejected-slave-amount': '0',
'slave-amount': '0',
'rejected-slave-list': '[]'
},
parameter_dict
)
class SlaveHttpFrontendTestCase(HttpFrontendTestCase):
@classmethod
def startServerProcess(cls):
server = HTTPServer(
(utils.LOCAL_IPV4, utils.findFreeTCPPort(utils.LOCAL_IPV4)),
utils.TestHandler)
server_https = HTTPServer(
(utils.LOCAL_IPV4, utils.findFreeTCPPort(utils.LOCAL_IPV4)),
utils.TestHandler)
server_https.socket = ssl.wrap_socket(
server_https.socket,
certfile=os.path.join(
os.path.dirname(os.path.realpath(__file__)),
'testserver.example.com.pem'),
server_side=True)
cls.backend_url = 'http://%s:%s' % server.server_address
cls.server_process = multiprocessing.Process(target=server.serve_forever)
cls.server_process.start()
cls.backend_https_url = 'https://%s:%s' % server_https.server_address
cls.server_https_process = multiprocessing.Process(
target=server_https.serve_forever)
cls.server_https_process.start()
@classmethod
def stopServerProcess(cls):
cls.server_process.terminate()
cls.server_https_process.terminate()
@classmethod
def setUpSlaves(cls):
cls.slave_connection_parameter_dict_dict = {}
request = cls.slapos_controler.slap.registerOpenOrder().request
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
slave_instance = request(
software_release=cls.software_url_list[0],
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
)
cls.runComputerPartition()
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
slave_instance = request(
software_release=cls.software_url_list[0],
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
)
cls.slave_connection_parameter_dict_dict[slave_reference] = \
slave_instance.getConnectionParameterDict()
@classmethod
def setUpClass(cls):
try:
cls.startServerProcess()
super(SlaveHttpFrontendTestCase, cls).setUpClass()
cls.setUpSlaves()
except Exception:
cls.tearDownClass()
raise
@classmethod
def tearDownClass(cls):
super(SlaveHttpFrontendTestCase, cls).tearDownClass()
cls.stopServerProcess()
def fakeHTTPSResult(self, domain, real_ip, path, port=HTTPS_PORT,
headers=None, cookies=None, source_ip=None):
if headers is None:
headers = {}
headers.setdefault('REMOTE_USER', 'SOME_REMOTE_USER')
session = requests.Session()
session.mount(
'https://%s:%s' % (domain, port),
ForcedIPHTTPSAdapter(
dest_ip=real_ip))
if source_ip is not None:
new_source = source.SourceAddressAdapter(source_ip)
session.mount('http://', new_source)
session.mount('https://', new_source)
return session.get(
'https://%s:%s/%s' % (domain, port, path),
verify=False,
allow_redirects=False,
headers=headers,
cookies=cookies
)
def fakeHTTPResult(self, domain, real_ip, path, port=HTTP_PORT,
headers=None):
if headers is None:
headers = {}
headers.setdefault('REMOTE_USER', 'SOME_REMOTE_USER')
headers['Host'] = domain
return requests.get(
'http://%s:%s/%s' % (real_ip, port, path),
headers=headers,
allow_redirects=False,
)
def patchRequests(self):
HTTPResponse = requests.packages.urllib3.response.HTTPResponse
HTTPResponse.orig__init__ = HTTPResponse.__init__
def new_HTTPResponse__init__(self, *args, **kwargs):
self.orig__init__(*args, **kwargs)
try:
self.peercert = self._connection.sock.getpeercert(binary_form=True)
except AttributeError:
pass
HTTPResponse.__init__ = new_HTTPResponse__init__
HTTPAdapter = requests.adapters.HTTPAdapter
HTTPAdapter.orig_build_response = HTTPAdapter.build_response
def new_HTTPAdapter_build_response(self, request, resp):
response = self.orig_build_response(request, resp)
try:
response.peercert = resp.peercert
except AttributeError:
pass
return response
HTTPAdapter.build_response = new_HTTPAdapter_build_response
def unpatchRequests(self):
HTTPResponse = requests.packages.urllib3.response.HTTPResponse
if getattr(HTTPResponse, 'orig__init__', None) is not None:
HTTPResponse.__init__ = HTTPResponse.orig__init__
del(HTTPResponse.orig__init__)
HTTPAdapter = requests.adapters.HTTPAdapter
if getattr(HTTPAdapter, 'orig_build_response', None) is not None:
HTTPAdapter.build_response = HTTPAdapter.orig_build_response
del(HTTPAdapter.orig_build_response)
def setUp(self):
# patch requests in order to being able to extract SSL certs
self.patchRequests()
def tearDown(self):
self.unpatchRequests()
class TestSlave(SlaveHttpFrontendTestCase, TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'domain': 'example.com',
'nginx-domain': 'nginx.example.com',
'public-ipv4': utils.LOCAL_IPV4,
'apache-certificate': open('wildcard.example.com.crt').read(),
'apache-key': open('wildcard.example.com.key').read(),
'-frontend-authorized-slave-string': '_apache_custom_http_s-accepted',
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
'-frontend-config-1-monitor-httpd-port': MONITOR_F1_HTTPD_PORT,
}
@classmethod
def getSlaveParameterDictDict(cls):
return {
'empty': {
},
'url': {
'url': cls.backend_url,
},
'url_https-url': {
'url': cls.backend_url + '/http',
'https-url': cls.backend_url + '/https',
},
'server-alias': {
'url': cls.backend_url,
'server-alias': 'alias1.example.com alias2.example.com',
},
'ssl-proxy-verify_ssl_proxy_ca_crt': {
'url': cls.backend_https_url,
'ssl-proxy-verify': True,
'ssl_proxy_ca_crt': open('testserver.root.ca.crt').read(),
},
'ssl-proxy-verify-unverified': {
'url': cls.backend_https_url,
'ssl-proxy-verify': True,
},
'https-only': {
'url': cls.backend_url,
'https-only': True,
},
'custom_domain': {
'url': cls.backend_url,
'custom_domain': 'customdomain.example.com',
},
'custom_domain_ssl_crt_ssl_key': {
'url': cls.backend_url,
'custom_domain': 'customdomainsslcrtsslkey.example.com',
'ssl_crt': open('customdomainsslcrtsslkey.example.com.crt').read(),
'ssl_key': open('customdomainsslcrtsslkey.example.com.key').read(),
},
'type-zope': {
'url': cls.backend_url,
'type': 'zope',
},
'type-zope-ssl-proxy-verify_ssl_proxy_ca_crt': {
'url': cls.backend_https_url,
'type': 'zope',
'ssl-proxy-verify': True,
'ssl_proxy_ca_crt': open('testserver.root.ca.crt').read(),
},
'type-zope-ssl-proxy-verify-unverified': {
'url': cls.backend_https_url,
'type': 'zope',
'ssl-proxy-verify': True,
},
'type-zope-virtualhostroot-http-port': {
'url': cls.backend_url,
'type': 'zope',
'virtualhostroot-http-port': '12345'
},
'type-zope-virtualhostroot-https-port': {
'url': cls.backend_url,
'type': 'zope',
'virtualhostroot-https-port': '12345'
},
'type-zope-path': {
'url': cls.backend_url,
'type': 'zope',
'path': 'path',
},
'type-zope-default-path': {
'url': cls.backend_url,
'type': 'zope',
'default-path': 'default-path',
},
'type-notebook': {
'url': cls.backend_url,
'type': 'notebook',
},
'type-eventsource': {
'url': cls.backend_url,
'type': 'eventsource',
},
'type-redirect': {
'url': cls.backend_url,
'type': 'redirect',
},
'enable_cache': {
'url': cls.backend_url,
'enable_cache': True,
},
'enable_cache-disable-no-cache-request': {
'url': cls.backend_url,
'enable_cache': True,
'disable-no-cache-request': True,
},
'enable_cache-disable-via-header': {
'url': cls.backend_url,
'enable_cache': True,
'disable-via-header': True,
},
'enable-http2-false': {
'url': cls.backend_url,
'enable-http2': False,
},
'enable_cache-ssl-proxy-verify-unverified': {
'url': cls.backend_https_url,
'enable_cache': True,
'ssl-proxy-verify': True,
},
'enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt': {
'url': cls.backend_https_url,
'enable_cache': True,
'ssl_proxy_ca_crt': open('testserver.root.ca.crt').read(),
'ssl-proxy-verify': True,
},
'enable-http2-default': {
'url': cls.backend_url,
},
'apache_custom_http_s-rejected': {
'url': cls.backend_url,
'apache_custom_https': '# apache_custom_https_filled_in_rejected',
'apache_custom_http': '# apache_custom_http_filled_in_rejected',
},
'apache_custom_http_s-accepted': {
'url': cls.backend_url,
'apache_custom_https': apache_custom_https % dict(url=cls.backend_url),
'apache_custom_http': apache_custom_http % dict(url=cls.backend_url),
},
'prefer-gzip-encoding-to-backend': {
'url': cls.backend_url,
'prefer-gzip-encoding-to-backend': 'true',
},
'disabled-cookie-list': {
'url': cls.backend_url,
'disabled-cookie-list': 'Chocolate Vanilia',
},
'monitor-ipv4-test': {
'monitor-ipv4-test': 'monitor-ipv4-test',
},
'monitor-ipv6-test': {
'monitor-ipv6-test': 'monitor-ipv6-test',
},
're6st-optimal-test': {
're6st-optimal-test': 'ipv6,ipv4',
}
}
def getMasterPartitionPath(self):
# partition w/o etc/trafficserver, but with buildout.cfg
return [
q for q in glob.glob(os.path.join(self.instance_path, '*',))
if not os.path.exists(os.path.join(q, 'etc', 'trafficserver')) and
os.path.exists(os.path.join(q, 'buildout.cfg'))][0]
def getSlavePartitionPath(self):
# partition w/ etc/trafficserver
return [
q for q in glob.glob(os.path.join(self.instance_path, '*',))
if os.path.exists(os.path.join(q, 'etc', 'trafficserver'))][0]
def test_master_partition_state(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
self.assertKeyWithPop('monitor-setup-url', parameter_dict)
self.assertEqual(
{
'monitor-base-url': None,
'domain': 'example.com',
'accepted-slave-amount': '32',
'rejected-slave-amount': '1',
'slave-amount': '33',
'rejected-slave-list': '["_apache_custom_http_s-rejected"]'},
parameter_dict
)
partition_path = self.getMasterPartitionPath()
self.assertEqual(
set([
'check-free-disk-space',
'monitor-http-frontend',
'monitor-httpd-listening-on-tcp',
'promise-monitor-httpd-is-process-older-than-dependency-set',
]),
set(os.listdir(os.path.join(partition_path, 'etc', 'promise'))))
self.assertEqual(
set(),
set(os.listdir(os.path.join(partition_path, 'etc', 'monitor-promise'))))
def test_empty(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'empty']
self.assertLogAccessUrlWithPop(parameter_dict, 'empty')
self.assertEqual(
parameter_dict,
{
'domain': 'empty.example.com',
'replication_number': '1',
'url': 'http://empty.example.com',
'site_url': 'http://empty.example.com',
'secure_access': 'https://empty.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(result.status_code, no_backend_response_code)
# check that log file contains verbose log
log_file = glob.glob(
os.path.join(
self.instance_path, '*', 'var', 'log', 'httpd', '_empty_access_log'
))[0]
self.assertRegexpMatches(
open(log_file, 'r').read(),
LOG_REGEXP)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(result_http.status_code, no_backend_response_code)
# check that 404 is as configured
result_missing = self.fakeHTTPSResult(
'forsuredoesnotexists.example.com', parameter_dict['public-ipv4'], '')
self.assertEqual(404, result_missing.status_code)
self.assertEqual(
"""<html>
<head>
<title>Instance not found</title>
</head>
<body>
<h1>This instance has not been found.</h1>
<p>If this error persists, please check your instance URL and status on S"""
"""lapOS Master.</p>
</body>
</html>
""",
result_missing.text
)
def test_url(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'url'].copy()
self.assertLogAccessUrlWithPop(parameter_dict, 'url')
self.assertEqual(
parameter_dict,
{
'domain': 'url.example.com',
'replication_number': '1',
'url': 'http://url.example.com',
'site_url': 'http://url.example.com',
'secure_access': 'https://url.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
try:
j = result.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqual(
result.headers['Content-Encoding'],
'gzip'
)
self.assertEqual(
result.headers['Set-Cookie'],
'secured=value;secure, nonsecured=value'
)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(result_http, 'Path', '/test-path')
try:
j = result_http.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqual(
result_http.headers['Content-Encoding'],
'gzip'
)
self.assertEqual(
result_http.headers['Set-Cookie'],
'secured=value;secure, nonsecured=value'
)
@skipIf(IS_CADDY, 'Feature postponed')
def test_url_ipv6_access(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'url'].copy()
self.assertLogAccessUrlWithPop(parameter_dict, 'url')
self.assertEqual(
parameter_dict,
{
'domain': 'url.example.com',
'replication_number': '1',
'url': 'http://url.example.com',
'site_url': 'http://url.example.com',
'secure_access': 'https://url.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result_ipv6 = self.fakeHTTPSResult(
parameter_dict['domain'], utils.GLOBAL_IPV6, 'test-path',
source_ip=utils.GLOBAL_IPV6)
self.assertEqual(
result_ipv6.json()['Incoming Headers']['x-forwarded-for'],
utils.GLOBAL_IPV6
)
self.assertEqual(
utils.der2pem(result_ipv6.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result_ipv6, 'Path', '/test-path')
def test_type_zope_path(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope-path']
self.assertLogAccessUrlWithPop(parameter_dict, 'type-zope-path')
self.assertEqual(
parameter_dict,
{
'domain': 'typezopepath.example.com',
'replication_number': '1',
'url': 'http://typezopepath.example.com',
'site_url': 'http://typezopepath.example.com',
'secure_access': 'https://typezopepath.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/https//'
'typezopepath.example.com:443/path/VirtualHostRoot/test-path'
)
def test_type_zope_default_path(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope-default-path']
self.assertLogAccessUrlWithPop(parameter_dict, 'type-zope-default-path')
self.assertEqual(
parameter_dict,
{
'domain': 'typezopedefaultpath.example.com',
'replication_number': '1',
'url': 'http://typezopedefaultpath.example.com',
'site_url': 'http://typezopedefaultpath.example.com',
'secure_access': 'https://typezopedefaultpath.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], '')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(
result.headers['Location'],
'https://typezopedefaultpath.example.com:%s/default-path' % (HTTPS_PORT,)
)
def test_server_alias(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'server-alias']
self.assertLogAccessUrlWithPop(parameter_dict, 'server-alias')
self.assertEqual(
parameter_dict,
{
'domain': 'serveralias.example.com',
'replication_number': '1',
'url': 'http://serveralias.example.com',
'site_url': 'http://serveralias.example.com',
'secure_access': 'https://serveralias.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
result = self.fakeHTTPSResult(
'alias1.example.com', parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
result = self.fakeHTTPSResult(
'alias2.example.com', parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
@skip('Feature postponed')
def test_check_error_log(self):
# Caddy: Need to implement similar thing like check-error-on-apache-log
raise NotImplementedError(self.id())
@skip('Feature postponed')
def test_ssl_ca_crt(self):
raise NotImplementedError(self.id())
@skip('Feature postponed')
def test_path_to_ssl_ca_crt(self):
raise NotImplementedError(self.id())
def test_https_only(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'https-only']
self.assertLogAccessUrlWithPop(parameter_dict, 'https-only')
self.assertEqual(
parameter_dict,
{
'domain': 'httpsonly.example.com',
'replication_number': '1',
'url': 'http://httpsonly.example.com',
'site_url': 'http://httpsonly.example.com',
'secure_access': 'https://httpsonly.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
result_http.headers['Location'],
'https://httpsonly.example.com/test-path'
)
def test_custom_domain(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'custom_domain']
self.assertLogAccessUrlWithPop(parameter_dict, 'custom_domain')
self.assertEqual(
parameter_dict,
{
'domain': 'customdomain.example.com',
'replication_number': '1',
'url': 'http://customdomain.example.com',
'site_url': 'http://customdomain.example.com',
'secure_access': 'https://customdomain.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
def test_custom_domain_ssl_crt_ssl_key(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'custom_domain_ssl_crt_ssl_key']
self.assertLogAccessUrlWithPop(parameter_dict, 'custom_domain_ssl_crt_key')
self.assertEqual(
parameter_dict,
{
'domain': 'customdomainsslcrtsslkey.example.com',
'replication_number': '1',
'url': 'http://customdomainsslcrtsslkey.example.com',
'site_url': 'http://customdomainsslcrtsslkey.example.com',
'secure_access': 'https://customdomainsslcrtsslkey.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('customdomainsslcrtsslkey.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
def test_type_zope(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope']
self.assertLogAccessUrlWithPop(parameter_dict, 'type-zope')
self.assertEqual(
parameter_dict,
{
'domain': 'typezope.example.com',
'replication_number': '1',
'url': 'http://typezope.example.com',
'site_url': 'http://typezope.example.com',
'secure_access': 'https://typezope.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
try:
j = result.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/https//typezope.example.com:443/'
'/VirtualHostRoot/test-path'
)
result = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/http//typezope.example.com:80/'
'/VirtualHostRoot/test-path'
)
def test_type_zope_virtualhostroot_http_port(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope-virtualhostroot-http-port']
self.assertLogAccessUrlWithPop(
parameter_dict, 'type-zope-virtualhostroot-http-port')
self.assertEqual(
parameter_dict,
{
'domain': 'typezopevirtualhostroothttpport.example.com',
'replication_number': '1',
'url': 'http://typezopevirtualhostroothttpport.example.com',
'site_url': 'http://typezopevirtualhostroothttpport.example.com',
'secure_access':
'https://typezopevirtualhostroothttpport.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/http//typezopevirtualhostroothttpport'
'.example.com:12345//VirtualHostRoot/test-path'
)
def test_type_zope_virtualhostroot_https_port(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope-virtualhostroot-https-port']
self.assertLogAccessUrlWithPop(
parameter_dict, 'type-zope-virtualhostroot-https-port')
self.assertEqual(
parameter_dict,
{
'domain': 'typezopevirtualhostroothttpsport.example.com',
'replication_number': '1',
'url': 'http://typezopevirtualhostroothttpsport.example.com',
'site_url': 'http://typezopevirtualhostroothttpsport.example.com',
'secure_access':
'https://typezopevirtualhostroothttpsport.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/https//typezopevirtualhostroothttpsport'
'.example.com:12345//VirtualHostRoot/test-path'
)
def test_type_notebook(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-notebook']
self.assertLogAccessUrlWithPop(parameter_dict, 'type-notebook')
self.assertEqual(
parameter_dict,
{
'domain': 'typenotebook.nginx.example.com',
'replication_number': '1',
'url': 'http://typenotebook.nginx.example.com',
'site_url': 'http://typenotebook.nginx.example.com',
'secure_access': 'https://typenotebook.nginx.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
NGINX_HTTPS_PORT)
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
@skip('Feature postponed')
def test_type_websocket(self):
# Pure websocket configurable frontend
raise NotImplementedError
@skip('Feature postponed')
def test_apache_ca_certificate(self):
# merge with apache-certificate
raise NotImplementedError
@skipIf(IS_CADDY, 'Feature postponed')
def test_type_eventsource(self):
# Caddy: For event source, if I understand
# https://github.com/mholt/caddy/issues/1355 correctly, we could use
# Caddy as a proxy in front of nginx-push-stream . If we have a
# "central shared" caddy instance, can it handle keeping connections
# opens for many clients ?
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-eventsource']
self.assertLogAccessUrlWithPop(parameter_dict, 'type-eventsource')
self.assertEqual(
parameter_dict,
{
'domain': 'typeeventsource.nginx.example.com',
'replication_number': '1',
'url': 'http://typeeventsource.nginx.example.com',
'site_url': 'http://typeeventsource.nginx.example.com',
'secure_access': 'https://typeeventsource.nginx.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'pub',
NGINX_HTTPS_PORT)
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(
result.content,
''
)
headers = result.headers.copy()
self.assertKeyWithPop('Expires', headers)
self.assertKeyWithPop('Date', headers)
self.assertEqual(
headers,
{
'X-Nginx-PushStream-Explain': 'No channel id provided.',
'Content-Length': '0',
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Connection': 'keep-alive',
'Server': 'nginx'
}
)
def test_type_redirect(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-redirect']
self.assertLogAccessUrlWithPop(parameter_dict, 'type-redirect')
self.assertEqual(
parameter_dict,
{
'domain': 'typeredirect.example.com',
'replication_number': '1',
'url': 'http://typeredirect.example.com',
'site_url': 'http://typeredirect.example.com',
'secure_access': 'https://typeredirect.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(
result.headers['Location'],
'%s/test-path' % (self.backend_url,)
)
def test_ssl_proxy_verify_ssl_proxy_ca_crt(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'ssl-proxy-verify_ssl_proxy_ca_crt']
self.assertLogAccessUrlWithPop(
parameter_dict, 'ssl-proxy-verify_ssl_proxy_ca_crt')
self.assertEqual(
parameter_dict,
{
'domain': 'sslproxyverifysslproxycacrt.example.com',
'replication_number': '1',
'url': 'http://sslproxyverifysslproxycacrt.example.com',
'site_url': 'http://sslproxyverifysslproxycacrt.example.com',
'secure_access': 'https://sslproxyverifysslproxycacrt.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
if IS_CADDY:
self.assertEqual(
result.status_code,
501
)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
result_http.status_code,
501
)
else:
self.assertEqualResultJson(result, 'Path', '/test-path')
try:
j = result.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqual(
result.headers['Content-Encoding'],
'gzip'
)
self.assertEqual(
result.headers['Set-Cookie'],
'secured=value;secure, nonsecured=value'
)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(result_http, 'Path', '/test-path')
try:
j = result_http.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqual(
result_http.headers['Content-Encoding'],
'gzip'
)
self.assertEqual(
result_http.headers['Set-Cookie'],
'secured=value;secure, nonsecured=value'
)
def test_ssl_proxy_verify_unverified(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'ssl-proxy-verify-unverified']
self.assertLogAccessUrlWithPop(
parameter_dict, 'ssl-proxy-verify-unverified')
self.assertEqual(
parameter_dict,
{
'domain': 'sslproxyverifyunverified.example.com',
'replication_number': '1',
'url': 'http://sslproxyverifyunverified.example.com',
'site_url': 'http://sslproxyverifyunverified.example.com',
'secure_access': 'https://sslproxyverifyunverified.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(
result.status_code,
502
)
def test_enable_cache_ssl_proxy_verify_ssl_proxy_ca_crt(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt']
self.assertLogAccessUrlWithPop(
parameter_dict, 'enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt')
self.assertEqual(
parameter_dict,
{
'domain': 'enablecachesslproxyverifysslproxycacrt.example.com',
'replication_number': '1',
'url': 'http://enablecachesslproxyverifysslproxycacrt.example.com',
'site_url':
'http://enablecachesslproxyverifysslproxycacrt.example.com',
'secure_access':
'https://enablecachesslproxyverifysslproxycacrt.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
if IS_CADDY:
self.assertEqual(
result.status_code,
501
)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
result_http.status_code,
501
)
else:
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Via', headers)
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop keys appearing randomly in headers
headers.pop('Transfer-Encoding', None)
headers.pop('Content-Length', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{'Age': '0', 'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value'}
)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(result_http, 'Path', '/test-path')
headers = result_http.headers.copy()
self.assertKeyWithPop('Via', headers)
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop keys appearing randomly in headers
headers.pop('Transfer-Encoding', None)
headers.pop('Content-Length', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{'Age': '0', 'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value'}
)
def test_enable_cache_ssl_proxy_verify_unverified(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable_cache-ssl-proxy-verify-unverified']
self.assertLogAccessUrlWithPop(
parameter_dict, 'enable_cache-ssl-proxy-verify-unverified')
self.assertEqual(
parameter_dict,
{
'domain': 'enablecachesslproxyverifyunverified.example.com',
'replication_number': '1',
'url': 'http://enablecachesslproxyverifyunverified.example.com',
'site_url': 'http://enablecachesslproxyverifyunverified.example.com',
'secure_access':
'https://enablecachesslproxyverifyunverified.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(
result.status_code,
502
)
def test_type_zope_ssl_proxy_verify_ssl_proxy_ca_crt(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope-ssl-proxy-verify_ssl_proxy_ca_crt']
self.assertLogAccessUrlWithPop(
parameter_dict, 'type-zope-ssl-proxy-verify_ssl_proxy_ca_crt')
self.assertEqual(
parameter_dict,
{
'domain': 'typezopesslproxyverifysslproxycacrt.example.com',
'replication_number': '1',
'url': 'http://typezopesslproxyverifysslproxycacrt.example.com',
'site_url': 'http://typezopesslproxyverifysslproxycacrt.example.com',
'secure_access':
'https://typezopesslproxyverifysslproxycacrt.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
if IS_CADDY:
self.assertEqual(
result.status_code,
501
)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
result_http.status_code,
501
)
else:
try:
j = result.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/https//typezopesslproxyverifysslproxycacrt.example'
'.com:443//VirtualHostRoot/test-path'
)
result = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(
result,
'Path',
'/VirtualHostBase/http//typezopesslproxyverifysslproxycacrt.example'
'.com:80//VirtualHostRoot/test-path'
)
def test_type_zope_ssl_proxy_verify_unverified(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'type-zope-ssl-proxy-verify-unverified']
self.assertLogAccessUrlWithPop(
parameter_dict, 'type-zope-ssl-proxy-verify-unverified')
self.assertEqual(
parameter_dict,
{
'domain': 'typezopesslproxyverifyunverified.example.com',
'replication_number': '1',
'url': 'http://typezopesslproxyverifyunverified.example.com',
'site_url': 'http://typezopesslproxyverifyunverified.example.com',
'secure_access':
'https://typezopesslproxyverifyunverified.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(
result.status_code,
502
)
def test_monitor_ipv6_test(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'monitor-ipv6-test']
self.assertLogAccessUrlWithPop(parameter_dict, 'monitor-ipv6-test')
self.assertEqual(
parameter_dict,
{
'domain': 'monitoripv6test.example.com',
'replication_number': '1',
'url': 'http://monitoripv6test.example.com',
'site_url': 'http://monitoripv6test.example.com',
'secure_access': 'https://monitoripv6test.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(result.status_code, no_backend_response_code)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(result_http.status_code, no_backend_response_code)
# rewrite SR/bin/is-icmp-packet-lost
open(
os.path.join(self.software_path, 'bin', 'is-icmp-packet-lost'), 'w'
).write('echo "$@"')
# call the monitor for this partition
monitor_file = glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'monitor-promise',
'check-_monitor-ipv6-test-ipv6-packet-list-test'))[0]
self.assertEqual(
'-a monitor-ipv6-test',
subprocess.check_output(monitor_file).strip()
)
def test_monitor_ipv4_test(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'monitor-ipv4-test']
self.assertLogAccessUrlWithPop(parameter_dict, 'monitor-ipv4-test')
self.assertEqual(
parameter_dict,
{
'domain': 'monitoripv4test.example.com',
'replication_number': '1',
'url': 'http://monitoripv4test.example.com',
'site_url': 'http://monitoripv4test.example.com',
'secure_access': 'https://monitoripv4test.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(result.status_code, no_backend_response_code)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(result_http.status_code, no_backend_response_code)
# rewrite SR/bin/is-icmp-packet-lost
open(
os.path.join(self.software_path, 'bin', 'is-icmp-packet-lost'), 'w'
).write('echo "$@"')
# call the monitor for this partition
monitor_file = glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'monitor-promise',
'check-_monitor-ipv4-test-ipv4-packet-list-test'))[0]
self.assertEqual(
'-4 -a monitor-ipv4-test',
subprocess.check_output(monitor_file).strip()
)
def test_re6st_optimal_test(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
're6st-optimal-test']
self.assertLogAccessUrlWithPop(parameter_dict, 're6st-optimal-test')
self.assertEqual(
parameter_dict,
{
'domain': 're6stoptimaltest.example.com',
'replication_number': '1',
'url': 'http://re6stoptimaltest.example.com',
'site_url': 'http://re6stoptimaltest.example.com',
'secure_access': 'https://re6stoptimaltest.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqual(result.status_code, no_backend_response_code)
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(result_http.status_code, no_backend_response_code)
# rewrite SR/bin/is-icmp-packet-lost
open(
os.path.join(
self.software_path, 'bin', 'check-re6st-optimal-status'), 'w'
).write('echo "$@"')
# call the monitor for this partition
monitor_file = glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'monitor-promise',
'check-_re6st-optimal-test-re6st-optimal-test'))[0]
self.assertEqual(
'-4 ipv4 -6 ipv6',
subprocess.check_output(monitor_file).strip()
)
def test_enable_cache(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable_cache']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable_cache')
self.assertEqual(
parameter_dict,
{
'domain': 'enablecache.example.com',
'replication_number': '1',
'url': 'http://enablecache.example.com',
'site_url': 'http://enablecache.example.com',
'secure_access': 'https://enablecache.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Via', headers)
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop keys appearing randomly in headers
headers.pop('Transfer-Encoding', None)
headers.pop('Content-Length', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{'Age': '0', 'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value',
'Content-Encoding': 'gzip', 'Vary': 'Accept-Encoding'}
)
result_direct = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
port=26011)
self.assertEqualResultJson(result_direct, 'Path', '/test-path')
try:
j = result_direct.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result_direct.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqual(
result_direct.headers['Content-Encoding'],
'gzip'
)
self.assertEqual(
result_direct.headers['Set-Cookie'],
'secured=value;secure, nonsecured=value'
)
result_direct_https_backend = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
port=26012)
self.assertEqualResultJson(
result_direct_https_backend, 'Path', '/test-path')
try:
j = result_direct_https_backend.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (
result_direct_https_backend.text,))
self.assertFalse('remote_user' in j['Incoming Headers'].keys())
self.assertEqual(
result_direct_https_backend.headers['Content-Encoding'],
'gzip'
)
self.assertEqual(
result_direct_https_backend.headers['Set-Cookie'],
'secured=value;secure, nonsecured=value'
)
def test_enable_cache_disable_no_cache_request(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable_cache-disable-no-cache-request']
self.assertLogAccessUrlWithPop(
parameter_dict, 'enable_cache-disable-no-cache-request')
self.assertEqual(
parameter_dict,
{
'domain': 'enablecachedisablenocacherequest.example.com',
'replication_number': '1',
'url': 'http://enablecachedisablenocacherequest.example.com',
'site_url': 'http://enablecachedisablenocacherequest.example.com',
'secure_access':
'https://enablecachedisablenocacherequest.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
headers={'Pragma': 'no-cache', 'Cache-Control': 'something'})
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Via', headers)
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop keys appearing randomly in headers
headers.pop('Transfer-Encoding', None)
headers.pop('Content-Length', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{'Age': '0', 'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value',
'Content-Encoding': 'gzip', 'Vary': 'Accept-Encoding'}
)
try:
j = result.json()
except Exception:
raise ValueError('JSON decode problem in:\n%s' % (result.text,))
self.assertFalse('pragma' in j['Incoming Headers'].keys())
def test_enable_cache_disable_via_header(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable_cache-disable-via-header']
self.assertLogAccessUrlWithPop(
parameter_dict, 'enable_cache-disable-via-header')
self.assertEqual(
parameter_dict,
{
'domain': 'enablecachedisableviaheader.example.com',
'replication_number': '1',
'url': 'http://enablecachedisableviaheader.example.com',
'site_url': 'http://enablecachedisableviaheader.example.com',
'secure_access':
'https://enablecachedisableviaheader.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop keys appearing randomly in headers
headers.pop('Transfer-Encoding', None)
headers.pop('Content-Length', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{'Age': '0', 'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value',
'Content-Encoding': 'gzip', 'Vary': 'Accept-Encoding'}
)
def test_enable_http2_false(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-false']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-false')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2false.example.com',
'replication_number': '1',
'url': 'http://enablehttp2false.example.com',
'site_url': 'http://enablehttp2false.example.com',
'secure_access':
'https://enablehttp2false.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop vary-keys
headers.pop('Content-Length', None)
headers.pop('Transfer-Encoding', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{
'Vary': 'Accept-Encoding',
'Content-Type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value',
'Content-Encoding': 'gzip',
}
)
self.assertFalse(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
def test_enable_http2_default(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-default']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-default')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2default.example.com',
'replication_number': '1',
'url': 'http://enablehttp2default.example.com',
'site_url': 'http://enablehttp2default.example.com',
'secure_access':
'https://enablehttp2default.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop vary-keys
headers.pop('Content-Length', None)
headers.pop('Transfer-Encoding', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{
'Vary': 'Accept-Encoding',
'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value',
'Content-Encoding': 'gzip',
}
)
self.assertTrue(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
@skipIf(IS_CADDY, 'Feature postponed')
def test_prefer_gzip_encoding_to_backend(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'prefer-gzip-encoding-to-backend']
self.assertLogAccessUrlWithPop(
parameter_dict, 'prefer-gzip-encoding-to-backend')
self.assertEqual(
parameter_dict,
{
'domain': 'prefergzipencodingtobackend.example.com',
'replication_number': '1',
'url': 'http://prefergzipencodingtobackend.example.com',
'site_url': 'http://prefergzipencodingtobackend.example.com',
'secure_access':
'https://prefergzipencodingtobackend.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
headers={'Accept-Encoding': 'gzip, deflate'})
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
self.assertEqual(
result.json()['Incoming Headers']['accept-encoding'], 'gzip')
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
headers={'Accept-Encoding': 'deflate'})
self.assertEqualResultJson(result, 'Path', '/test-path')
self.assertEqual(
result.json()['Incoming Headers']['accept-encoding'], 'deflate')
@skipIf(IS_CADDY, 'Feature postponed')
def test_disabled_cookie_list(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'disabled-cookie-list']
self.assertLogAccessUrlWithPop(parameter_dict, 'disabled-cookie-list')
self.assertEqual(
parameter_dict,
{
'domain': 'disabledcookielist.example.com',
'replication_number': '1',
'url': 'http://disabledcookielist.example.com',
'site_url': 'http://disabledcookielist.example.com',
'secure_access': 'https://disabledcookielist.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path',
cookies=dict(
Chocolate='absent',
Vanilia='absent',
Coffee='present'
))
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
self.assertEqual(
result.json()['Incoming Headers']['cookie'], 'Coffee=present')
@skip('Feature postponed')
def test_caddy_custom_http_s_rejected(self):
raise NotImplementedError
def test_apache_custom_http_s_rejected(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'apache_custom_http_s-rejected']
self.assertEqual({}, parameter_dict)
slave_configuration_file_list = glob.glob(os.path.join(
self.instance_path, '*', 'etc', '*slave-conf.d', '*.conf'))
# no configuration file contains provided custom http
configuration_file_with_custom_https_list = [
q for q in slave_configuration_file_list
if 'apache_custom_https_filled_in_rejected' in open(q).read()]
self.assertEqual([], configuration_file_with_custom_https_list)
configuration_file_with_custom_http_list = [
q for q in slave_configuration_file_list
if 'apache_custom_http_filled_in_rejected' in open(q).read()]
self.assertEqual([], configuration_file_with_custom_http_list)
def test_apache_custom_http_s_accepted(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'apache_custom_http_s-accepted']
self.assertLogAccessUrlWithPop(
parameter_dict, 'apache_custom_http_s-accepted')
self.assertEqual(
parameter_dict,
{'replication_number': '1', 'public-ipv4': utils.LOCAL_IPV4}
)
result = self.fakeHTTPSResult(
'apachecustomhttpsaccepted.example.com',
parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
headers = result.headers.copy()
self.assertKeyWithPop('Server', headers)
self.assertKeyWithPop('Date', headers)
# drop vary-keys
headers.pop('Content-Length', None)
headers.pop('Transfer-Encoding', None)
headers.pop('Connection', None)
headers.pop('Keep-Alive', None)
self.assertEqual(
headers,
{
'Content-type': 'text/json',
'Set-Cookie': 'secured=value;secure, nonsecured=value'
}
)
result_http = self.fakeHTTPResult(
'apachecustomhttpsaccepted.example.com',
parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(result_http, 'Path', '/test-path')
slave_configuration_file_list = glob.glob(os.path.join(
self.instance_path, '*', 'etc', '*slave-conf.d', '*.conf'))
# no configuration file contains provided custom http
configuration_file_with_custom_https_list = [
q for q in slave_configuration_file_list
if 'apache_custom_https_filled_in_accepted' in open(q).read()]
self.assertEqual(1, len(configuration_file_with_custom_https_list))
configuration_file_with_custom_http_list = [
q for q in slave_configuration_file_list
if 'apache_custom_https_filled_in_accepted' in open(q).read()]
self.assertEqual(1, len(configuration_file_with_custom_http_list))
def test_https_url(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'url_https-url']
self.assertLogAccessUrlWithPop(parameter_dict, 'url_https-url')
self.assertEqual(
parameter_dict,
{
'domain': 'urlhttpsurl.example.com',
'replication_number': '1',
'url': 'http://urlhttpsurl.example.com',
'site_url': 'http://urlhttpsurl.example.com',
'secure_access': 'https://urlhttpsurl.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/https/test-path')
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(result_http, 'Path', '/http/test-path')
class TestReplicateSlave(SlaveHttpFrontendTestCase, TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'domain': 'example.com',
'nginx-domain': 'nginx.example.com',
'public-ipv4': utils.LOCAL_IPV4,
'apache-certificate': open('wildcard.example.com.crt').read(),
'apache-key': open('wildcard.example.com.key').read(),
'-frontend-quantity': 2,
'-sla-2-computer_guid': 'slapos.test',
'-frontend-2-state': 'stopped',
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
'-frontend-config-1-monitor-httpd-port': MONITOR_F1_HTTPD_PORT,
'-frontend-config-2-monitor-httpd-port': MONITOR_F2_HTTPD_PORT,
}
@classmethod
def getSlaveParameterDictDict(cls):
return {
'replicate': {
'url': cls.backend_url,
},
}
def test(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'replicate']
self.assertLogAccessUrlWithPop(parameter_dict, 'replicate')
self.assertEqual(
parameter_dict,
{
'domain': 'replicate.example.com',
'replication_number': '2',
'url': 'http://replicate.example.com',
'site_url': 'http://replicate.example.com',
'secure_access': 'https://replicate.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
result = self.fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqual(
utils.der2pem(result.peercert),
open('wildcard.example.com.crt').read())
self.assertEqualResultJson(result, 'Path', '/test-path')
result_http = self.fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
self.assertEqualResultJson(result_http, 'Path', '/test-path')
# prove 2nd frontend by inspection of the instance
slave_configuration_name = '_replicate.conf'
slave_configuration_file_list = [
'/'.join([f[0], slave_configuration_name]) for f in [
q for q in os.walk(self.instance_path)
if slave_configuration_name in q[2]
]
]
self.assertEqual(
2, len(slave_configuration_file_list), slave_configuration_file_list)
class TestEnableHttp2ByDefaultFalseSlave(SlaveHttpFrontendTestCase,
TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'domain': 'example.com',
'nginx-domain': 'nginx.example.com',
'public-ipv4': utils.LOCAL_IPV4,
'apache-certificate': open('wildcard.example.com.crt').read(),
'apache-key': open('wildcard.example.com.key').read(),
'enable-http2-by-default': 'false',
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
'-frontend-config-1-monitor-httpd-port': MONITOR_F1_HTTPD_PORT,
}
@classmethod
def getSlaveParameterDictDict(cls):
return {
'enable-http2-default': {
},
'enable-http2-false': {
'enable-http2': 'false',
},
'enable-http2-true': {
'enable-http2': 'true',
},
}
def test_enable_http2_default(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-default']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-default')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2default.example.com',
'replication_number': '1',
'url': 'http://enablehttp2default.example.com',
'site_url': 'http://enablehttp2default.example.com',
'secure_access':
'https://enablehttp2default.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
self.assertFalse(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
def test_enable_http2_false(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-false']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-false')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2false.example.com',
'replication_number': '1',
'url': 'http://enablehttp2false.example.com',
'site_url': 'http://enablehttp2false.example.com',
'secure_access':
'https://enablehttp2false.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
self.assertFalse(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
def test_enable_http2_true(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-true']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-true')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2true.example.com',
'replication_number': '1',
'url': 'http://enablehttp2true.example.com',
'site_url': 'http://enablehttp2true.example.com',
'secure_access':
'https://enablehttp2true.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
self.assertTrue(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
class TestEnableHttp2ByDefaultDefaultSlave(SlaveHttpFrontendTestCase,
TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'domain': 'example.com',
'nginx-domain': 'nginx.example.com',
'public-ipv4': utils.LOCAL_IPV4,
'apache-certificate': open('wildcard.example.com.crt').read(),
'apache-key': open('wildcard.example.com.key').read(),
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
'-frontend-config-1-monitor-httpd-port': MONITOR_F1_HTTPD_PORT,
}
@classmethod
def getSlaveParameterDictDict(cls):
return {
'enable-http2-default': {
},
'enable-http2-false': {
'enable-http2': 'false',
},
'enable-http2-true': {
'enable-http2': 'true',
},
}
def test_enable_http2_default(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-default']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-default')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2default.example.com',
'replication_number': '1',
'url': 'http://enablehttp2default.example.com',
'site_url': 'http://enablehttp2default.example.com',
'secure_access':
'https://enablehttp2default.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
self.assertTrue(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
def test_enable_http2_false(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-false']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-false')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2false.example.com',
'replication_number': '1',
'url': 'http://enablehttp2false.example.com',
'site_url': 'http://enablehttp2false.example.com',
'secure_access':
'https://enablehttp2false.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
self.assertFalse(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
def test_enable_http2_true(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'enable-http2-true']
self.assertLogAccessUrlWithPop(parameter_dict, 'enable-http2-true')
self.assertEqual(
parameter_dict,
{
'domain': 'enablehttp2true.example.com',
'replication_number': '1',
'url': 'http://enablehttp2true.example.com',
'site_url': 'http://enablehttp2true.example.com',
'secure_access':
'https://enablehttp2true.example.com',
'public-ipv4': utils.LOCAL_IPV4,
}
)
self.assertTrue(
isHTTP2(parameter_dict['domain'], parameter_dict['public-ipv4']))
class TestRe6stVerificationUrlDefaultSlave(SlaveHttpFrontendTestCase,
TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
'-frontend-config-1-monitor-httpd-port': MONITOR_F1_HTTPD_PORT,
}
@classmethod
def getSlaveParameterDictDict(cls):
return {
'default': {
},
}
def test_default(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'default']
self.assertLogAccessUrlWithPop(parameter_dict, 'default')
self.assertEqual(
parameter_dict,
{
'domain': 'default.None',
'replication_number': '1',
'url': 'http://default.None',
'site_url': 'http://default.None',
'secure_access': 'https://default.None',
'public-ipv4': None,
}
)
re6st_connectivity_promise_list = glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'promise',
're6st-connectivity'))
self.assertEqual(1, len(re6st_connectivity_promise_list))
self.assertTrue(
'URL="http://[2001:67c:1254:4::1]/index.html"' in
open(re6st_connectivity_promise_list[0]).read()
)
class TestRe6stVerificationUrlSlave(SlaveHttpFrontendTestCase,
TestDataMixin):
@classmethod
def getInstanceParameterDict(cls):
return {
'port': HTTPS_PORT,
'plain_http_port': HTTP_PORT,
'nginx_port': NGINX_HTTPS_PORT,
'plain_nginx_port': NGINX_HTTP_PORT,
'monitor-httpd-port': MONITOR_HTTPD_PORT,
'-frontend-config-1-monitor-httpd-port': MONITOR_F1_HTTPD_PORT,
're6st-verification-url': 'some-re6st-verification-url',
}
@classmethod
def getSlaveParameterDictDict(cls):
return {
'default': {
},
}
def test_default(self):
parameter_dict = self.slave_connection_parameter_dict_dict[
'default']
self.assertLogAccessUrlWithPop(parameter_dict, 'default')
self.assertEqual(
parameter_dict,
{
'domain': 'default.None',
'replication_number': '1',
'url': 'http://default.None',
'site_url': 'http://default.None',
'secure_access': 'https://default.None',
'public-ipv4': None,
}
)
re6st_connectivity_promise_list = glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'promise',
're6st-connectivity'))
self.assertEqual(1, len(re6st_connectivity_promise_list))
self.assertTrue(
'URL="some-re6st-verification-url"' in
open(re6st_connectivity_promise_list[0]).read()
)
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/frontend-apache-access.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/frontend-apache-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-default_access_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-default_error_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-false_access_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-false_error_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-true_access_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-true_error_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/monitor-httpd-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/nginx-access.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/nginx-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/trafficserver/manager.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0/var/log/monitor-httpd-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/frontend-access.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/frontend-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-default_access_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-default_error_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-false_access_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-false_error_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-true_access_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/httpd/_enable-http2-true_error_log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/monitor-httpd-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/nginx-access.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/nginx-error.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/trafficserver/manager.log
TestEnableHttp2ByDefaultDefaultSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/apache_configuration.signature
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/httpd.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/monitor-httpd.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/napache_configuration.signature
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/nginx.pid
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0/var/run/monitor-httpd.pid
TestEnableHttp2ByDefaultDefaultSlave-0/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/caddy_configuration.signature
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/httpd.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/monitor-httpd.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/ncaddy_configuration.signature
TestEnableHttp2ByDefaultDefaultSlave-1/var/run/nginx.pid
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-day
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-hour
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-day
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-hour
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-day
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-hour
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-day
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-hour
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-day
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-hour
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-day
TestEnableHttp2ByDefaultDefaultSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-hour
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache-frontend-is-running-actual-software-release
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache-mpm-watchdog
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache_cached
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache_frontend_ipv4_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache_frontend_ipv4_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache_frontend_ipv6_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache_frontend_ipv6_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/apache_ssl_cached
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/frontend-apache-configuration-promise
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx-configuration-promise
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv4_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv4_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv6_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv6_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/re6st-connectivity
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/trafficserver-cache-availability
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultDefaultSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy-frontend-is-running-actual-software-release
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy_cached
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy_frontend_ipv4_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy_frontend_ipv4_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy_frontend_ipv6_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy_frontend_ipv6_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/caddy_ssl_cached
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/frontend-caddy-configuration-promise
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx-configuration-promise
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv4_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv4_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv6_http
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/nginx_frontend_ipv6_https
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/re6st-connectivity
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/trafficserver-cache-availability
TestEnableHttp2ByDefaultDefaultSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultDefaultSlave-0:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-0:crond RUNNING
TestEnableHttp2ByDefaultDefaultSlave-0:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-0:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:crond-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:frontend-apache-safe-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:frontend-nginx-safe-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:frontend_apache-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:frontend_nginx-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:trafficserver-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestEnableHttp2ByDefaultDefaultSlave-0:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultDefaultSlave-0:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-0:crond RUNNING
TestEnableHttp2ByDefaultDefaultSlave-0:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-0:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:6tunnel-11080-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:6tunnel-11443-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:6tunnel-12080-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:6tunnel-12443-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:6tunnel-26011-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:6tunnel-26012-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:crond-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:frontend-caddy-safe-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:frontend-nginx-safe-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:frontend_caddy-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:frontend_nginx-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultDefaultSlave-1:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:trafficserver-on-watch RUNNING
TestEnableHttp2ByDefaultDefaultSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-1/var/log/frontend-apache-access.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/frontend-apache-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-default_access_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-default_error_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-false_access_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-false_error_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-true_access_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-true_error_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/monitor-httpd-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/nginx-access.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/nginx-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/trafficserver/manager.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0/var/log/monitor-httpd-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/frontend-access.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/frontend-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-default_access_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-default_error_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-false_access_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-false_error_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-true_access_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/httpd/_enable-http2-true_error_log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/monitor-httpd-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/nginx-access.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/nginx-error.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/trafficserver/manager.log
TestEnableHttp2ByDefaultFalseSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/apache_configuration.signature
TestEnableHttp2ByDefaultFalseSlave-1/var/run/httpd.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/monitor-httpd.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/napache_configuration.signature
TestEnableHttp2ByDefaultFalseSlave-1/var/run/nginx.pid
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0/var/run/monitor-httpd.pid
TestEnableHttp2ByDefaultFalseSlave-0/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/caddy_configuration.signature
TestEnableHttp2ByDefaultFalseSlave-1/var/run/httpd.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/monitor-httpd.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/monitor/monitor-bootstrap.pid
TestEnableHttp2ByDefaultFalseSlave-1/var/run/ncaddy_configuration.signature
TestEnableHttp2ByDefaultFalseSlave-1/var/run/nginx.pid
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-day
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-hour
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-day
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-hour
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-day
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-hour
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-day
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-hour
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-day
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-hour
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-day
TestEnableHttp2ByDefaultFalseSlave-1/etc/monitor-promise/check-_enable-http2-true-error-log-last-hour
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache-frontend-is-running-actual-software-release
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache-mpm-watchdog
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache_cached
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache_frontend_ipv4_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache_frontend_ipv4_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache_frontend_ipv6_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache_frontend_ipv6_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/apache_ssl_cached
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/frontend-apache-configuration-promise
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx-configuration-promise
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv4_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv4_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv6_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv6_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/re6st-connectivity
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/trafficserver-cache-availability
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultFalseSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy-frontend-is-running-actual-software-release
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy_cached
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy_frontend_ipv4_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy_frontend_ipv4_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy_frontend_ipv6_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy_frontend_ipv6_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/caddy_ssl_cached
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/check-free-disk-space
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/frontend-caddy-configuration-promise
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/monitor-http-frontend
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx-configuration-promise
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv4_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv4_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv6_http
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/nginx_frontend_ipv6_https
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/re6st-connectivity
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/trafficserver-cache-availability
TestEnableHttp2ByDefaultFalseSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultFalseSlave-0:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-0:crond RUNNING
TestEnableHttp2ByDefaultFalseSlave-0:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-0:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultFalseSlave-1:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:crond-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:frontend-apache-safe-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-1:frontend-nginx-safe-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-1:frontend_apache-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:frontend_nginx-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-1:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:trafficserver-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestEnableHttp2ByDefaultFalseSlave-0:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultFalseSlave-0:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-0:crond RUNNING
TestEnableHttp2ByDefaultFalseSlave-0:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-0:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:6tunnel-11080-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:6tunnel-11443-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:6tunnel-12080-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:6tunnel-12443-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:6tunnel-26011-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:6tunnel-26012-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:bootstrap-monitor EXITED
TestEnableHttp2ByDefaultFalseSlave-1:certificate_authority-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:crond-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:frontend-caddy-safe-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-1:frontend-nginx-safe-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-1:frontend_caddy-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:frontend_nginx-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:monitor-httpd-graceful EXITED
TestEnableHttp2ByDefaultFalseSlave-1:monitor-httpd-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:trafficserver-on-watch RUNNING
TestEnableHttp2ByDefaultFalseSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestMasterRequest-1/var/log/frontend-apache-access.log
TestMasterRequest-1/var/log/frontend-apache-error.log
TestMasterRequest-1/var/log/monitor-httpd-error.log
TestMasterRequest-1/var/log/nginx-access.log
TestMasterRequest-1/var/log/nginx-error.log
TestMasterRequest-1/var/log/trafficserver/manager.log
TestMasterRequest-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestMasterRequest-0/var/log/monitor-httpd-error.log
\ No newline at end of file
TestMasterRequest-0/var/run/monitor/monitor-bootstrap.pid
TestMasterRequest-1/var/run/apache_configuration.signature
TestMasterRequest-1/var/run/httpd.pid
TestMasterRequest-1/var/run/monitor-httpd.pid
TestMasterRequest-1/var/run/monitor/monitor-bootstrap.pid
TestMasterRequest-1/var/run/napache_configuration.signature
TestMasterRequest-1/var/run/nginx.pid
\ No newline at end of file
TestMasterRequest-0/var/run/monitor-httpd.pid
TestMasterRequest-0/var/run/monitor/monitor-bootstrap.pid
\ No newline at end of file
TestMasterRequest-0/etc/promise/check-free-disk-space
TestMasterRequest-0/etc/promise/monitor-http-frontend
TestMasterRequest-0/etc/promise/monitor-httpd-listening-on-tcp
TestMasterRequest-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestMasterRequest-1/etc/promise/apache-frontend-is-running-actual-software-release
TestMasterRequest-1/etc/promise/apache-mpm-watchdog
TestMasterRequest-1/etc/promise/apache_cached
TestMasterRequest-1/etc/promise/apache_frontend_ipv4_http
TestMasterRequest-1/etc/promise/apache_frontend_ipv4_https
TestMasterRequest-1/etc/promise/apache_frontend_ipv6_http
TestMasterRequest-1/etc/promise/apache_frontend_ipv6_https
TestMasterRequest-1/etc/promise/apache_ssl_cached
TestMasterRequest-1/etc/promise/check-free-disk-space
TestMasterRequest-1/etc/promise/frontend-apache-configuration-promise
TestMasterRequest-1/etc/promise/monitor-http-frontend
TestMasterRequest-1/etc/promise/monitor-httpd-listening-on-tcp
TestMasterRequest-1/etc/promise/nginx-configuration-promise
TestMasterRequest-1/etc/promise/nginx_frontend_ipv4_http
TestMasterRequest-1/etc/promise/nginx_frontend_ipv4_https
TestMasterRequest-1/etc/promise/nginx_frontend_ipv6_http
TestMasterRequest-1/etc/promise/nginx_frontend_ipv6_https
TestMasterRequest-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestMasterRequest-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestMasterRequest-1/etc/promise/re6st-connectivity
TestMasterRequest-1/etc/promise/trafficserver-cache-availability
TestMasterRequest-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestMasterRequest-0/etc/promise/check-free-disk-space
TestMasterRequest-0/etc/promise/monitor-http-frontend
TestMasterRequest-0/etc/promise/monitor-httpd-listening-on-tcp
TestMasterRequest-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestMasterRequest-1/etc/promise/monitor-http-frontend
\ No newline at end of file
TestMasterRequest-0:bootstrap-monitor EXITED
TestMasterRequest-0:certificate_authority-on-watch RUNNING
TestMasterRequest-0:crond RUNNING
TestMasterRequest-0:monitor-httpd-graceful EXITED
TestMasterRequest-0:monitor-httpd-on-watch RUNNING
TestMasterRequest-1:bootstrap-monitor EXITED
TestMasterRequest-1:certificate_authority-on-watch RUNNING
TestMasterRequest-1:crond-on-watch RUNNING
TestMasterRequest-1:frontend-apache-safe-graceful EXITED
TestMasterRequest-1:frontend-nginx-safe-graceful EXITED
TestMasterRequest-1:frontend_apache-on-watch RUNNING
TestMasterRequest-1:frontend_nginx-on-watch RUNNING
TestMasterRequest-1:monitor-httpd-graceful EXITED
TestMasterRequest-1:monitor-httpd-on-watch RUNNING
TestMasterRequest-1:trafficserver-on-watch RUNNING
TestMasterRequest-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestMasterRequest-0:bootstrap-monitor EXITED
TestMasterRequest-0:certificate_authority-on-watch RUNNING
TestMasterRequest-0:crond RUNNING
TestMasterRequest-0:monitor-httpd-graceful EXITED
TestMasterRequest-0:monitor-httpd-on-watch RUNNING
watchdog:watchdog RUNNING
\ No newline at end of file
TestMasterRequestDomain-1/var/log/frontend-apache-access.log
TestMasterRequestDomain-1/var/log/frontend-apache-error.log
TestMasterRequestDomain-1/var/log/monitor-httpd-error.log
TestMasterRequestDomain-1/var/log/nginx-access.log
TestMasterRequestDomain-1/var/log/nginx-error.log
TestMasterRequestDomain-1/var/log/trafficserver/manager.log
TestMasterRequestDomain-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestMasterRequestDomain-0/var/log/monitor-httpd-error.log
\ No newline at end of file
TestMasterRequestDomain-0/var/run/monitor/monitor-bootstrap.pid
TestMasterRequestDomain-1/var/run/apache_configuration.signature
TestMasterRequestDomain-1/var/run/httpd.pid
TestMasterRequestDomain-1/var/run/monitor-httpd.pid
TestMasterRequestDomain-1/var/run/monitor/monitor-bootstrap.pid
TestMasterRequestDomain-1/var/run/napache_configuration.signature
TestMasterRequestDomain-1/var/run/nginx.pid
\ No newline at end of file
TestMasterRequestDomain-0/var/run/monitor-httpd.pid
TestMasterRequestDomain-0/var/run/monitor/monitor-bootstrap.pid
\ No newline at end of file
TestMasterRequestDomain-0/etc/promise/check-free-disk-space
TestMasterRequestDomain-0/etc/promise/monitor-http-frontend
TestMasterRequestDomain-0/etc/promise/monitor-httpd-listening-on-tcp
TestMasterRequestDomain-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestMasterRequestDomain-1/etc/promise/apache-frontend-is-running-actual-software-release
TestMasterRequestDomain-1/etc/promise/apache-mpm-watchdog
TestMasterRequestDomain-1/etc/promise/apache_cached
TestMasterRequestDomain-1/etc/promise/apache_frontend_ipv4_http
TestMasterRequestDomain-1/etc/promise/apache_frontend_ipv4_https
TestMasterRequestDomain-1/etc/promise/apache_frontend_ipv6_http
TestMasterRequestDomain-1/etc/promise/apache_frontend_ipv6_https
TestMasterRequestDomain-1/etc/promise/apache_ssl_cached
TestMasterRequestDomain-1/etc/promise/check-free-disk-space
TestMasterRequestDomain-1/etc/promise/frontend-apache-configuration-promise
TestMasterRequestDomain-1/etc/promise/monitor-http-frontend
TestMasterRequestDomain-1/etc/promise/monitor-httpd-listening-on-tcp
TestMasterRequestDomain-1/etc/promise/nginx-configuration-promise
TestMasterRequestDomain-1/etc/promise/nginx_frontend_ipv4_http
TestMasterRequestDomain-1/etc/promise/nginx_frontend_ipv4_https
TestMasterRequestDomain-1/etc/promise/nginx_frontend_ipv6_http
TestMasterRequestDomain-1/etc/promise/nginx_frontend_ipv6_https
TestMasterRequestDomain-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestMasterRequestDomain-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestMasterRequestDomain-1/etc/promise/re6st-connectivity
TestMasterRequestDomain-1/etc/promise/trafficserver-cache-availability
TestMasterRequestDomain-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestMasterRequestDomain-0/etc/promise/check-free-disk-space
TestMasterRequestDomain-0/etc/promise/monitor-http-frontend
TestMasterRequestDomain-0/etc/promise/monitor-httpd-listening-on-tcp
TestMasterRequestDomain-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestMasterRequestDomain-1/etc/promise/monitor-http-frontend
\ No newline at end of file
TestMasterRequestDomain-0:bootstrap-monitor EXITED
TestMasterRequestDomain-0:certificate_authority-on-watch RUNNING
TestMasterRequestDomain-0:crond RUNNING
TestMasterRequestDomain-0:monitor-httpd-graceful EXITED
TestMasterRequestDomain-0:monitor-httpd-on-watch RUNNING
TestMasterRequestDomain-1:bootstrap-monitor EXITED
TestMasterRequestDomain-1:certificate_authority-on-watch RUNNING
TestMasterRequestDomain-1:crond-on-watch RUNNING
TestMasterRequestDomain-1:frontend-apache-safe-graceful EXITED
TestMasterRequestDomain-1:frontend-nginx-safe-graceful EXITED
TestMasterRequestDomain-1:frontend_apache-on-watch RUNNING
TestMasterRequestDomain-1:frontend_nginx-on-watch RUNNING
TestMasterRequestDomain-1:monitor-httpd-graceful EXITED
TestMasterRequestDomain-1:monitor-httpd-on-watch RUNNING
TestMasterRequestDomain-1:trafficserver-on-watch RUNNING
TestMasterRequestDomain-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestMasterRequestDomain-0:bootstrap-monitor EXITED
TestMasterRequestDomain-0:certificate_authority-on-watch RUNNING
TestMasterRequestDomain-0:crond RUNNING
TestMasterRequestDomain-0:monitor-httpd-graceful EXITED
TestMasterRequestDomain-0:monitor-httpd-on-watch RUNNING
watchdog:watchdog RUNNING
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-1/var/log/frontend-apache-access.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/frontend-apache-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/httpd/_default_access_log
TestRe6stVerificationUrlDefaultSlave-1/var/log/httpd/_default_error_log
TestRe6stVerificationUrlDefaultSlave-1/var/log/monitor-httpd-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/nginx-access.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/nginx-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/trafficserver/manager.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0/var/log/monitor-httpd-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/frontend-access.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/frontend-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/httpd/_default_access_log
TestRe6stVerificationUrlDefaultSlave-1/var/log/httpd/_default_error_log
TestRe6stVerificationUrlDefaultSlave-1/var/log/monitor-httpd-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/nginx-access.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/nginx-error.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/trafficserver/manager.log
TestRe6stVerificationUrlDefaultSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/apache_configuration.signature
TestRe6stVerificationUrlDefaultSlave-1/var/run/httpd.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/monitor-httpd.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/napache_configuration.signature
TestRe6stVerificationUrlDefaultSlave-1/var/run/nginx.pid
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0/var/run/monitor-httpd.pid
TestRe6stVerificationUrlDefaultSlave-0/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/caddy_configuration.signature
TestRe6stVerificationUrlDefaultSlave-1/var/run/httpd.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/monitor-httpd.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlDefaultSlave-1/var/run/ncaddy_configuration.signature
TestRe6stVerificationUrlDefaultSlave-1/var/run/nginx.pid
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-1/etc/monitor-promise/check-_default-error-log-last-day
TestRe6stVerificationUrlDefaultSlave-1/etc/monitor-promise/check-_default-error-log-last-hour
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-1/etc/monitor-promise/check-_default-error-log-last-day
TestRe6stVerificationUrlDefaultSlave-1/etc/monitor-promise/check-_default-error-log-last-hour
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/check-free-disk-space
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache-frontend-is-running-actual-software-release
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache-mpm-watchdog
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache_cached
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache_frontend_ipv4_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache_frontend_ipv4_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache_frontend_ipv6_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache_frontend_ipv6_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/apache_ssl_cached
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/check-free-disk-space
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/frontend-apache-configuration-promise
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx-configuration-promise
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv4_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv4_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv6_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv6_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/re6st-connectivity
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/trafficserver-cache-availability
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/check-free-disk-space
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlDefaultSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy-frontend-is-running-actual-software-release
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy_cached
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy_frontend_ipv4_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy_frontend_ipv4_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy_frontend_ipv6_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy_frontend_ipv6_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/caddy_ssl_cached
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/check-free-disk-space
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/frontend-caddy-configuration-promise
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx-configuration-promise
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv4_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv4_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv6_http
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/nginx_frontend_ipv6_https
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/re6st-connectivity
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/trafficserver-cache-availability
TestRe6stVerificationUrlDefaultSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0:bootstrap-monitor EXITED
TestRe6stVerificationUrlDefaultSlave-0:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-0:crond RUNNING
TestRe6stVerificationUrlDefaultSlave-0:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-0:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:bootstrap-monitor EXITED
TestRe6stVerificationUrlDefaultSlave-1:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:crond-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:frontend-apache-safe-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-1:frontend-nginx-safe-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-1:frontend_apache-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:frontend_nginx-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-1:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:trafficserver-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestRe6stVerificationUrlDefaultSlave-0:bootstrap-monitor EXITED
TestRe6stVerificationUrlDefaultSlave-0:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-0:crond RUNNING
TestRe6stVerificationUrlDefaultSlave-0:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-0:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:6tunnel-11080-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:6tunnel-11443-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:6tunnel-12080-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:6tunnel-12443-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:6tunnel-26011-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:6tunnel-26012-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:bootstrap-monitor EXITED
TestRe6stVerificationUrlDefaultSlave-1:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:crond-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:frontend-caddy-safe-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-1:frontend-nginx-safe-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-1:frontend_caddy-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:frontend_nginx-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlDefaultSlave-1:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:trafficserver-on-watch RUNNING
TestRe6stVerificationUrlDefaultSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestRe6stVerificationUrlSlave-1/var/log/frontend-apache-access.log
TestRe6stVerificationUrlSlave-1/var/log/frontend-apache-error.log
TestRe6stVerificationUrlSlave-1/var/log/httpd/_default_access_log
TestRe6stVerificationUrlSlave-1/var/log/httpd/_default_error_log
TestRe6stVerificationUrlSlave-1/var/log/monitor-httpd-error.log
TestRe6stVerificationUrlSlave-1/var/log/nginx-access.log
TestRe6stVerificationUrlSlave-1/var/log/nginx-error.log
TestRe6stVerificationUrlSlave-1/var/log/trafficserver/manager.log
TestRe6stVerificationUrlSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestRe6stVerificationUrlSlave-0/var/log/monitor-httpd-error.log
TestRe6stVerificationUrlSlave-1/var/log/frontend-access.log
TestRe6stVerificationUrlSlave-1/var/log/frontend-error.log
TestRe6stVerificationUrlSlave-1/var/log/httpd/_default_access_log
TestRe6stVerificationUrlSlave-1/var/log/httpd/_default_error_log
TestRe6stVerificationUrlSlave-1/var/log/monitor-httpd-error.log
TestRe6stVerificationUrlSlave-1/var/log/nginx-access.log
TestRe6stVerificationUrlSlave-1/var/log/nginx-error.log
TestRe6stVerificationUrlSlave-1/var/log/trafficserver/manager.log
TestRe6stVerificationUrlSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestRe6stVerificationUrlSlave-0/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlSlave-1/var/run/apache_configuration.signature
TestRe6stVerificationUrlSlave-1/var/run/httpd.pid
TestRe6stVerificationUrlSlave-1/var/run/monitor-httpd.pid
TestRe6stVerificationUrlSlave-1/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlSlave-1/var/run/napache_configuration.signature
TestRe6stVerificationUrlSlave-1/var/run/nginx.pid
\ No newline at end of file
TestRe6stVerificationUrlSlave-0/var/run/monitor-httpd.pid
TestRe6stVerificationUrlSlave-0/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlSlave-1/var/run/caddy_configuration.signature
TestRe6stVerificationUrlSlave-1/var/run/httpd.pid
TestRe6stVerificationUrlSlave-1/var/run/monitor-httpd.pid
TestRe6stVerificationUrlSlave-1/var/run/monitor/monitor-bootstrap.pid
TestRe6stVerificationUrlSlave-1/var/run/ncaddy_configuration.signature
TestRe6stVerificationUrlSlave-1/var/run/nginx.pid
\ No newline at end of file
TestRe6stVerificationUrlSlave-1/etc/monitor-promise/check-_default-error-log-last-day
TestRe6stVerificationUrlSlave-1/etc/monitor-promise/check-_default-error-log-last-hour
\ No newline at end of file
TestRe6stVerificationUrlSlave-1/etc/monitor-promise/check-_default-error-log-last-day
TestRe6stVerificationUrlSlave-1/etc/monitor-promise/check-_default-error-log-last-hour
\ No newline at end of file
TestRe6stVerificationUrlSlave-0/etc/promise/check-free-disk-space
TestRe6stVerificationUrlSlave-0/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlSlave-1/etc/promise/apache-frontend-is-running-actual-software-release
TestRe6stVerificationUrlSlave-1/etc/promise/apache-mpm-watchdog
TestRe6stVerificationUrlSlave-1/etc/promise/apache_cached
TestRe6stVerificationUrlSlave-1/etc/promise/apache_frontend_ipv4_http
TestRe6stVerificationUrlSlave-1/etc/promise/apache_frontend_ipv4_https
TestRe6stVerificationUrlSlave-1/etc/promise/apache_frontend_ipv6_http
TestRe6stVerificationUrlSlave-1/etc/promise/apache_frontend_ipv6_https
TestRe6stVerificationUrlSlave-1/etc/promise/apache_ssl_cached
TestRe6stVerificationUrlSlave-1/etc/promise/check-free-disk-space
TestRe6stVerificationUrlSlave-1/etc/promise/frontend-apache-configuration-promise
TestRe6stVerificationUrlSlave-1/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlSlave-1/etc/promise/nginx-configuration-promise
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv4_http
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv4_https
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv6_http
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv6_https
TestRe6stVerificationUrlSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestRe6stVerificationUrlSlave-1/etc/promise/re6st-connectivity
TestRe6stVerificationUrlSlave-1/etc/promise/trafficserver-cache-availability
TestRe6stVerificationUrlSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestRe6stVerificationUrlSlave-0/etc/promise/check-free-disk-space
TestRe6stVerificationUrlSlave-0/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlSlave-1/etc/promise/caddy-frontend-is-running-actual-software-release
TestRe6stVerificationUrlSlave-1/etc/promise/caddy_cached
TestRe6stVerificationUrlSlave-1/etc/promise/caddy_frontend_ipv4_http
TestRe6stVerificationUrlSlave-1/etc/promise/caddy_frontend_ipv4_https
TestRe6stVerificationUrlSlave-1/etc/promise/caddy_frontend_ipv6_http
TestRe6stVerificationUrlSlave-1/etc/promise/caddy_frontend_ipv6_https
TestRe6stVerificationUrlSlave-1/etc/promise/caddy_ssl_cached
TestRe6stVerificationUrlSlave-1/etc/promise/check-free-disk-space
TestRe6stVerificationUrlSlave-1/etc/promise/frontend-caddy-configuration-promise
TestRe6stVerificationUrlSlave-1/etc/promise/monitor-http-frontend
TestRe6stVerificationUrlSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestRe6stVerificationUrlSlave-1/etc/promise/nginx-configuration-promise
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv4_http
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv4_https
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv6_http
TestRe6stVerificationUrlSlave-1/etc/promise/nginx_frontend_ipv6_https
TestRe6stVerificationUrlSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestRe6stVerificationUrlSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestRe6stVerificationUrlSlave-1/etc/promise/re6st-connectivity
TestRe6stVerificationUrlSlave-1/etc/promise/trafficserver-cache-availability
TestRe6stVerificationUrlSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestRe6stVerificationUrlSlave-0:bootstrap-monitor EXITED
TestRe6stVerificationUrlSlave-0:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlSlave-0:crond RUNNING
TestRe6stVerificationUrlSlave-0:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlSlave-0:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:bootstrap-monitor EXITED
TestRe6stVerificationUrlSlave-1:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:crond-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:frontend-apache-safe-graceful EXITED
TestRe6stVerificationUrlSlave-1:frontend-nginx-safe-graceful EXITED
TestRe6stVerificationUrlSlave-1:frontend_apache-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:frontend_nginx-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlSlave-1:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:trafficserver-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestRe6stVerificationUrlSlave-0:bootstrap-monitor EXITED
TestRe6stVerificationUrlSlave-0:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlSlave-0:crond RUNNING
TestRe6stVerificationUrlSlave-0:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlSlave-0:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:6tunnel-11080-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:6tunnel-11443-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:6tunnel-12080-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:6tunnel-12443-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:6tunnel-26011-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:6tunnel-26012-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:bootstrap-monitor EXITED
TestRe6stVerificationUrlSlave-1:certificate_authority-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:crond-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:frontend-caddy-safe-graceful EXITED
TestRe6stVerificationUrlSlave-1:frontend-nginx-safe-graceful EXITED
TestRe6stVerificationUrlSlave-1:frontend_caddy-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:frontend_nginx-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:monitor-httpd-graceful EXITED
TestRe6stVerificationUrlSlave-1:monitor-httpd-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:trafficserver-on-watch RUNNING
TestRe6stVerificationUrlSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestReplicateSlave-1/var/log/frontend-apache-access.log
TestReplicateSlave-1/var/log/frontend-apache-error.log
TestReplicateSlave-1/var/log/httpd/_replicate_access_log
TestReplicateSlave-1/var/log/httpd/_replicate_error_log
TestReplicateSlave-1/var/log/monitor-httpd-error.log
TestReplicateSlave-1/var/log/nginx-access.log
TestReplicateSlave-1/var/log/nginx-error.log
TestReplicateSlave-1/var/log/trafficserver/manager.log
TestReplicateSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestReplicateSlave-0/var/log/monitor-httpd-error.log
TestReplicateSlave-1/var/log/frontend-access.log
TestReplicateSlave-1/var/log/frontend-error.log
TestReplicateSlave-1/var/log/httpd/_replicate_access_log
TestReplicateSlave-1/var/log/httpd/_replicate_error_log
TestReplicateSlave-1/var/log/monitor-httpd-error.log
TestReplicateSlave-1/var/log/nginx-access.log
TestReplicateSlave-1/var/log/nginx-error.log
TestReplicateSlave-1/var/log/trafficserver/manager.log
TestReplicateSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestReplicateSlave-0/var/run/monitor/monitor-bootstrap.pid
TestReplicateSlave-1/var/run/apache_configuration.signature
TestReplicateSlave-1/var/run/httpd.pid
TestReplicateSlave-1/var/run/monitor-httpd.pid
TestReplicateSlave-1/var/run/monitor/monitor-bootstrap.pid
TestReplicateSlave-1/var/run/napache_configuration.signature
TestReplicateSlave-1/var/run/nginx.pid
\ No newline at end of file
TestReplicateSlave-0/var/run/monitor-httpd.pid
TestReplicateSlave-0/var/run/monitor/monitor-bootstrap.pid
TestReplicateSlave-1/var/run/caddy_configuration.signature
TestReplicateSlave-1/var/run/httpd.pid
TestReplicateSlave-1/var/run/monitor-httpd.pid
TestReplicateSlave-1/var/run/monitor/monitor-bootstrap.pid
TestReplicateSlave-1/var/run/ncaddy_configuration.signature
TestReplicateSlave-1/var/run/nginx.pid
\ No newline at end of file
TestReplicateSlave-1/etc/monitor-promise/check-_replicate-error-log-last-day
TestReplicateSlave-1/etc/monitor-promise/check-_replicate-error-log-last-hour
TestReplicateSlave-2/etc/monitor-promise/check-_replicate-error-log-last-day
TestReplicateSlave-2/etc/monitor-promise/check-_replicate-error-log-last-hour
\ No newline at end of file
TestReplicateSlave-1/etc/monitor-promise/check-_replicate-error-log-last-day
TestReplicateSlave-1/etc/monitor-promise/check-_replicate-error-log-last-hour
TestReplicateSlave-2/etc/monitor-promise/check-_replicate-error-log-last-day
TestReplicateSlave-2/etc/monitor-promise/check-_replicate-error-log-last-hour
\ No newline at end of file
TestReplicateSlave-0/etc/promise/check-free-disk-space
TestReplicateSlave-0/etc/promise/monitor-http-frontend
TestReplicateSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestReplicateSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestReplicateSlave-1/etc/promise/apache-frontend-is-running-actual-software-release
TestReplicateSlave-1/etc/promise/apache-mpm-watchdog
TestReplicateSlave-1/etc/promise/apache_cached
TestReplicateSlave-1/etc/promise/apache_frontend_ipv4_http
TestReplicateSlave-1/etc/promise/apache_frontend_ipv4_https
TestReplicateSlave-1/etc/promise/apache_frontend_ipv6_http
TestReplicateSlave-1/etc/promise/apache_frontend_ipv6_https
TestReplicateSlave-1/etc/promise/apache_ssl_cached
TestReplicateSlave-1/etc/promise/check-free-disk-space
TestReplicateSlave-1/etc/promise/frontend-apache-configuration-promise
TestReplicateSlave-1/etc/promise/monitor-http-frontend
TestReplicateSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestReplicateSlave-1/etc/promise/nginx-configuration-promise
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv4_http
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv4_https
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv6_http
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv6_https
TestReplicateSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestReplicateSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestReplicateSlave-1/etc/promise/re6st-connectivity
TestReplicateSlave-1/etc/promise/trafficserver-cache-availability
TestReplicateSlave-1/etc/promise/trafficserver-port-listening
TestReplicateSlave-2/etc/promise/apache-frontend-is-running-actual-software-release
TestReplicateSlave-2/etc/promise/apache-mpm-watchdog
TestReplicateSlave-2/etc/promise/apache_cached
TestReplicateSlave-2/etc/promise/apache_frontend_ipv4_http
TestReplicateSlave-2/etc/promise/apache_frontend_ipv4_https
TestReplicateSlave-2/etc/promise/apache_frontend_ipv6_http
TestReplicateSlave-2/etc/promise/apache_frontend_ipv6_https
TestReplicateSlave-2/etc/promise/apache_ssl_cached
TestReplicateSlave-2/etc/promise/check-free-disk-space
TestReplicateSlave-2/etc/promise/frontend-apache-configuration-promise
TestReplicateSlave-2/etc/promise/monitor-http-frontend
TestReplicateSlave-2/etc/promise/monitor-httpd-listening-on-tcp
TestReplicateSlave-2/etc/promise/nginx-configuration-promise
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv4_http
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv4_https
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv6_http
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv6_https
TestReplicateSlave-2/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestReplicateSlave-2/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestReplicateSlave-2/etc/promise/re6st-connectivity
TestReplicateSlave-2/etc/promise/trafficserver-cache-availability
TestReplicateSlave-2/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestReplicateSlave-0/etc/promise/check-free-disk-space
TestReplicateSlave-0/etc/promise/monitor-http-frontend
TestReplicateSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestReplicateSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestReplicateSlave-1/etc/promise/caddy-frontend-is-running-actual-software-release
TestReplicateSlave-1/etc/promise/caddy_cached
TestReplicateSlave-1/etc/promise/caddy_frontend_ipv4_http
TestReplicateSlave-1/etc/promise/caddy_frontend_ipv4_https
TestReplicateSlave-1/etc/promise/caddy_frontend_ipv6_http
TestReplicateSlave-1/etc/promise/caddy_frontend_ipv6_https
TestReplicateSlave-1/etc/promise/caddy_ssl_cached
TestReplicateSlave-1/etc/promise/check-free-disk-space
TestReplicateSlave-1/etc/promise/frontend-caddy-configuration-promise
TestReplicateSlave-1/etc/promise/monitor-http-frontend
TestReplicateSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestReplicateSlave-1/etc/promise/nginx-configuration-promise
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv4_http
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv4_https
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv6_http
TestReplicateSlave-1/etc/promise/nginx_frontend_ipv6_https
TestReplicateSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestReplicateSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestReplicateSlave-1/etc/promise/re6st-connectivity
TestReplicateSlave-1/etc/promise/trafficserver-cache-availability
TestReplicateSlave-1/etc/promise/trafficserver-port-listening
TestReplicateSlave-2/etc/promise/caddy-frontend-is-running-actual-software-release
TestReplicateSlave-2/etc/promise/caddy_cached
TestReplicateSlave-2/etc/promise/caddy_frontend_ipv4_http
TestReplicateSlave-2/etc/promise/caddy_frontend_ipv4_https
TestReplicateSlave-2/etc/promise/caddy_frontend_ipv6_http
TestReplicateSlave-2/etc/promise/caddy_frontend_ipv6_https
TestReplicateSlave-2/etc/promise/caddy_ssl_cached
TestReplicateSlave-2/etc/promise/check-free-disk-space
TestReplicateSlave-2/etc/promise/frontend-caddy-configuration-promise
TestReplicateSlave-2/etc/promise/monitor-http-frontend
TestReplicateSlave-2/etc/promise/monitor-httpd-listening-on-tcp
TestReplicateSlave-2/etc/promise/nginx-configuration-promise
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv4_http
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv4_https
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv6_http
TestReplicateSlave-2/etc/promise/nginx_frontend_ipv6_https
TestReplicateSlave-2/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestReplicateSlave-2/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestReplicateSlave-2/etc/promise/re6st-connectivity
TestReplicateSlave-2/etc/promise/trafficserver-cache-availability
TestReplicateSlave-2/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestReplicateSlave-0:bootstrap-monitor EXITED
TestReplicateSlave-0:certificate_authority-on-watch RUNNING
TestReplicateSlave-0:crond RUNNING
TestReplicateSlave-0:monitor-httpd-graceful EXITED
TestReplicateSlave-0:monitor-httpd-on-watch RUNNING
TestReplicateSlave-1:bootstrap-monitor EXITED
TestReplicateSlave-1:certificate_authority-on-watch RUNNING
TestReplicateSlave-1:crond-on-watch RUNNING
TestReplicateSlave-1:frontend-apache-safe-graceful EXITED
TestReplicateSlave-1:frontend-nginx-safe-graceful EXITED
TestReplicateSlave-1:frontend_apache-on-watch RUNNING
TestReplicateSlave-1:frontend_nginx-on-watch RUNNING
TestReplicateSlave-1:monitor-httpd-graceful EXITED
TestReplicateSlave-1:monitor-httpd-on-watch RUNNING
TestReplicateSlave-1:trafficserver-on-watch RUNNING
TestReplicateSlave-1:trafficserver-reload EXITED
TestReplicateSlave-2:bootstrap-monitor STOPPED
TestReplicateSlave-2:certificate_authority-on-watch STOPPED
TestReplicateSlave-2:crond-on-watch STOPPED
TestReplicateSlave-2:frontend-apache-safe-graceful STOPPED
TestReplicateSlave-2:frontend-nginx-safe-graceful STOPPED
TestReplicateSlave-2:frontend_apache-on-watch STOPPED
TestReplicateSlave-2:frontend_nginx-on-watch STOPPED
TestReplicateSlave-2:monitor-httpd-graceful STOPPED
TestReplicateSlave-2:monitor-httpd-on-watch STOPPED
TestReplicateSlave-2:trafficserver-on-watch STOPPED
TestReplicateSlave-2:trafficserver-reload STOPPED
watchdog:watchdog RUNNING
\ No newline at end of file
TestReplicateSlave-0:bootstrap-monitor EXITED
TestReplicateSlave-0:certificate_authority-on-watch RUNNING
TestReplicateSlave-0:crond RUNNING
TestReplicateSlave-0:monitor-httpd-graceful EXITED
TestReplicateSlave-0:monitor-httpd-on-watch RUNNING
TestReplicateSlave-1:6tunnel-11080-on-watch RUNNING
TestReplicateSlave-1:6tunnel-11443-on-watch RUNNING
TestReplicateSlave-1:6tunnel-12080-on-watch RUNNING
TestReplicateSlave-1:6tunnel-12443-on-watch RUNNING
TestReplicateSlave-1:6tunnel-26011-on-watch RUNNING
TestReplicateSlave-1:6tunnel-26012-on-watch RUNNING
TestReplicateSlave-1:bootstrap-monitor EXITED
TestReplicateSlave-1:certificate_authority-on-watch RUNNING
TestReplicateSlave-1:crond-on-watch RUNNING
TestReplicateSlave-1:frontend-caddy-safe-graceful EXITED
TestReplicateSlave-1:frontend-nginx-safe-graceful EXITED
TestReplicateSlave-1:frontend_caddy-on-watch RUNNING
TestReplicateSlave-1:frontend_nginx-on-watch RUNNING
TestReplicateSlave-1:monitor-httpd-graceful EXITED
TestReplicateSlave-1:monitor-httpd-on-watch RUNNING
TestReplicateSlave-1:trafficserver-on-watch RUNNING
TestReplicateSlave-1:trafficserver-reload EXITED
TestReplicateSlave-2:6tunnel-11080-on-watch STOPPED
TestReplicateSlave-2:6tunnel-11443-on-watch STOPPED
TestReplicateSlave-2:6tunnel-12080-on-watch STOPPED
TestReplicateSlave-2:6tunnel-12443-on-watch STOPPED
TestReplicateSlave-2:6tunnel-26011-on-watch STOPPED
TestReplicateSlave-2:6tunnel-26012-on-watch STOPPED
TestReplicateSlave-2:bootstrap-monitor STOPPED
TestReplicateSlave-2:certificate_authority-on-watch STOPPED
TestReplicateSlave-2:crond-on-watch STOPPED
TestReplicateSlave-2:frontend-caddy-safe-graceful STOPPED
TestReplicateSlave-2:frontend-nginx-safe-graceful STOPPED
TestReplicateSlave-2:frontend_caddy-on-watch STOPPED
TestReplicateSlave-2:frontend_nginx-on-watch STOPPED
TestReplicateSlave-2:monitor-httpd-graceful STOPPED
TestReplicateSlave-2:monitor-httpd-on-watch STOPPED
TestReplicateSlave-2:trafficserver-on-watch STOPPED
TestReplicateSlave-2:trafficserver-reload STOPPED
watchdog:watchdog RUNNING
\ No newline at end of file
TestSlave-1/var/log/frontend-apache-access.log
TestSlave-1/var/log/frontend-apache-error.log
TestSlave-1/var/log/httpd/_apache_custom_http_s-accepted_access_log
TestSlave-1/var/log/httpd/_apache_custom_http_s-accepted_error_log
TestSlave-1/var/log/httpd/_custom_domain_access_log
TestSlave-1/var/log/httpd/_custom_domain_error_log
TestSlave-1/var/log/httpd/_custom_domain_ssl_crt_ssl_key_access_log
TestSlave-1/var/log/httpd/_custom_domain_ssl_crt_ssl_key_error_log
TestSlave-1/var/log/httpd/_disabled-cookie-list_access_log
TestSlave-1/var/log/httpd/_disabled-cookie-list_error_log
TestSlave-1/var/log/httpd/_empty_access_log
TestSlave-1/var/log/httpd/_empty_error_log
TestSlave-1/var/log/httpd/_enable-http2-default_access_log
TestSlave-1/var/log/httpd/_enable-http2-default_error_log
TestSlave-1/var/log/httpd/_enable-http2-false_access_log
TestSlave-1/var/log/httpd/_enable-http2-false_error_log
TestSlave-1/var/log/httpd/_enable_cache-disable-no-cache-request_access_log
TestSlave-1/var/log/httpd/_enable_cache-disable-no-cache-request_error_log
TestSlave-1/var/log/httpd/_enable_cache-disable-via-header_access_log
TestSlave-1/var/log/httpd/_enable_cache-disable-via-header_error_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify-unverified_access_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify-unverified_error_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt_access_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt_error_log
TestSlave-1/var/log/httpd/_enable_cache_access_log
TestSlave-1/var/log/httpd/_enable_cache_error_log
TestSlave-1/var/log/httpd/_https-only_access_log
TestSlave-1/var/log/httpd/_https-only_error_log
TestSlave-1/var/log/httpd/_monitor-ipv4-test_access_log
TestSlave-1/var/log/httpd/_monitor-ipv4-test_error_log
TestSlave-1/var/log/httpd/_monitor-ipv6-test_access_log
TestSlave-1/var/log/httpd/_monitor-ipv6-test_error_log
TestSlave-1/var/log/httpd/_prefer-gzip-encoding-to-backend_access_log
TestSlave-1/var/log/httpd/_prefer-gzip-encoding-to-backend_error_log
TestSlave-1/var/log/httpd/_re6st-optimal-test_access_log
TestSlave-1/var/log/httpd/_re6st-optimal-test_error_log
TestSlave-1/var/log/httpd/_server-alias_access_log
TestSlave-1/var/log/httpd/_server-alias_error_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify-unverified_access_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify-unverified_error_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify_ssl_proxy_ca_crt_access_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify_ssl_proxy_ca_crt_error_log
TestSlave-1/var/log/httpd/_type-eventsource_access_log
TestSlave-1/var/log/httpd/_type-eventsource_error_log
TestSlave-1/var/log/httpd/_type-notebook_access_log
TestSlave-1/var/log/httpd/_type-notebook_error_log
TestSlave-1/var/log/httpd/_type-redirect_access_log
TestSlave-1/var/log/httpd/_type-redirect_error_log
TestSlave-1/var/log/httpd/_type-zope-default-path_access_log
TestSlave-1/var/log/httpd/_type-zope-default-path_error_log
TestSlave-1/var/log/httpd/_type-zope-path_access_log
TestSlave-1/var/log/httpd/_type-zope-path_error_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify-unverified_access_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify-unverified_error_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt_access_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt_error_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-http-port_access_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-http-port_error_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-https-port_access_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-https-port_error_log
TestSlave-1/var/log/httpd/_type-zope_access_log
TestSlave-1/var/log/httpd/_type-zope_error_log
TestSlave-1/var/log/httpd/_url_access_log
TestSlave-1/var/log/httpd/_url_error_log
TestSlave-1/var/log/httpd/_url_https-url_access_log
TestSlave-1/var/log/httpd/_url_https-url_error_log
TestSlave-1/var/log/monitor-httpd-error.log
TestSlave-1/var/log/nginx-access.log
TestSlave-1/var/log/nginx-error.log
TestSlave-1/var/log/trafficserver/manager.log
TestSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestSlave-0/var/log/monitor-httpd-error.log
TestSlave-1/var/log/frontend-access.log
TestSlave-1/var/log/frontend-error.log
TestSlave-1/var/log/httpd/_apache_custom_http_s-accepted_access_log
TestSlave-1/var/log/httpd/_apache_custom_http_s-accepted_error_log
TestSlave-1/var/log/httpd/_custom_domain_access_log
TestSlave-1/var/log/httpd/_custom_domain_error_log
TestSlave-1/var/log/httpd/_custom_domain_ssl_crt_ssl_key_access_log
TestSlave-1/var/log/httpd/_custom_domain_ssl_crt_ssl_key_error_log
TestSlave-1/var/log/httpd/_disabled-cookie-list_access_log
TestSlave-1/var/log/httpd/_disabled-cookie-list_error_log
TestSlave-1/var/log/httpd/_empty_access_log
TestSlave-1/var/log/httpd/_empty_error_log
TestSlave-1/var/log/httpd/_enable-http2-default_access_log
TestSlave-1/var/log/httpd/_enable-http2-default_error_log
TestSlave-1/var/log/httpd/_enable-http2-false_access_log
TestSlave-1/var/log/httpd/_enable-http2-false_error_log
TestSlave-1/var/log/httpd/_enable_cache-disable-no-cache-request_access_log
TestSlave-1/var/log/httpd/_enable_cache-disable-no-cache-request_error_log
TestSlave-1/var/log/httpd/_enable_cache-disable-via-header_access_log
TestSlave-1/var/log/httpd/_enable_cache-disable-via-header_error_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify-unverified_access_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify-unverified_error_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt_access_log
TestSlave-1/var/log/httpd/_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt_error_log
TestSlave-1/var/log/httpd/_enable_cache_access_log
TestSlave-1/var/log/httpd/_enable_cache_error_log
TestSlave-1/var/log/httpd/_https-only_access_log
TestSlave-1/var/log/httpd/_https-only_error_log
TestSlave-1/var/log/httpd/_monitor-ipv4-test_access_log
TestSlave-1/var/log/httpd/_monitor-ipv4-test_error_log
TestSlave-1/var/log/httpd/_monitor-ipv6-test_access_log
TestSlave-1/var/log/httpd/_monitor-ipv6-test_error_log
TestSlave-1/var/log/httpd/_prefer-gzip-encoding-to-backend_access_log
TestSlave-1/var/log/httpd/_prefer-gzip-encoding-to-backend_error_log
TestSlave-1/var/log/httpd/_re6st-optimal-test_access_log
TestSlave-1/var/log/httpd/_re6st-optimal-test_error_log
TestSlave-1/var/log/httpd/_server-alias_access_log
TestSlave-1/var/log/httpd/_server-alias_error_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify-unverified_access_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify-unverified_error_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify_ssl_proxy_ca_crt_access_log
TestSlave-1/var/log/httpd/_ssl-proxy-verify_ssl_proxy_ca_crt_error_log
TestSlave-1/var/log/httpd/_type-notebook_access_log
TestSlave-1/var/log/httpd/_type-notebook_error_log
TestSlave-1/var/log/httpd/_type-redirect_access_log
TestSlave-1/var/log/httpd/_type-redirect_error_log
TestSlave-1/var/log/httpd/_type-zope-default-path_access_log
TestSlave-1/var/log/httpd/_type-zope-default-path_error_log
TestSlave-1/var/log/httpd/_type-zope-path_access_log
TestSlave-1/var/log/httpd/_type-zope-path_error_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify-unverified_access_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify-unverified_error_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt_access_log
TestSlave-1/var/log/httpd/_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt_error_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-http-port_access_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-http-port_error_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-https-port_access_log
TestSlave-1/var/log/httpd/_type-zope-virtualhostroot-https-port_error_log
TestSlave-1/var/log/httpd/_type-zope_access_log
TestSlave-1/var/log/httpd/_type-zope_error_log
TestSlave-1/var/log/httpd/_url_access_log
TestSlave-1/var/log/httpd/_url_error_log
TestSlave-1/var/log/httpd/_url_https-url_access_log
TestSlave-1/var/log/httpd/_url_https-url_error_log
TestSlave-1/var/log/monitor-httpd-error.log
TestSlave-1/var/log/nginx-access.log
TestSlave-1/var/log/nginx-error.log
TestSlave-1/var/log/trafficserver/manager.log
TestSlave-1/var/log/trafficserver/traffic.out
\ No newline at end of file
TestSlave-0/var/run/monitor/monitor-bootstrap.pid
TestSlave-1/var/run/apache_configuration.signature
TestSlave-1/var/run/httpd.pid
TestSlave-1/var/run/monitor-httpd.pid
TestSlave-1/var/run/monitor/monitor-bootstrap.pid
TestSlave-1/var/run/napache_configuration.signature
TestSlave-1/var/run/nginx.pid
\ No newline at end of file
TestSlave-0/var/run/monitor-httpd.pid
TestSlave-0/var/run/monitor/monitor-bootstrap.pid
TestSlave-1/var/run/caddy_configuration.signature
TestSlave-1/var/run/httpd.pid
TestSlave-1/var/run/monitor-httpd.pid
TestSlave-1/var/run/monitor/monitor-bootstrap.pid
TestSlave-1/var/run/ncaddy_configuration.signature
TestSlave-1/var/run/nginx.pid
\ No newline at end of file
TestSlave-1/etc/monitor-promise/check-_apache_custom_http_s-accepted-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_apache_custom_http_s-accepted-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_custom_domain-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_custom_domain-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_custom_domain_ssl_crt_ssl_key-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_custom_domain_ssl_crt_ssl_key-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_disabled-cookie-list-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_disabled-cookie-list-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_empty-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_empty-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-no-cache-request-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-no-cache-request-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-via-header-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-via-header-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify-unverified-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify-unverified-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_https-only-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_https-only-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_monitor-ipv4-test-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_monitor-ipv4-test-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_monitor-ipv4-test-ipv4-packet-list-test
TestSlave-1/etc/monitor-promise/check-_monitor-ipv6-test-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_monitor-ipv6-test-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_monitor-ipv6-test-ipv6-packet-list-test
TestSlave-1/etc/monitor-promise/check-_prefer-gzip-encoding-to-backend-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_prefer-gzip-encoding-to-backend-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-re6st-optimal-test
TestSlave-1/etc/monitor-promise/check-_server-alias-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_server-alias-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify-unverified-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify-unverified-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-eventsource-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-eventsource-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-notebook-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-notebook-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-redirect-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-redirect-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-default-path-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-default-path-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-path-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-path-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify-unverified-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify-unverified-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-http-port-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-http-port-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-https-port-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-https-port-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_url-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_url-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_url_https-url-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_url_https-url-error-log-last-hour
\ No newline at end of file
TestSlave-1/etc/monitor-promise/check-_apache_custom_http_s-accepted-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_apache_custom_http_s-accepted-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_custom_domain-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_custom_domain-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_custom_domain_ssl_crt_ssl_key-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_custom_domain_ssl_crt_ssl_key-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_disabled-cookie-list-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_disabled-cookie-list-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_empty-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_empty-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable-http2-default-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable-http2-false-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-no-cache-request-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-no-cache-request-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-via-header-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-disable-via-header-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify-unverified-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify-unverified-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_enable_cache-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_https-only-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_https-only-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_monitor-ipv4-test-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_monitor-ipv4-test-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_monitor-ipv4-test-ipv4-packet-list-test
TestSlave-1/etc/monitor-promise/check-_monitor-ipv6-test-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_monitor-ipv6-test-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_monitor-ipv6-test-ipv6-packet-list-test
TestSlave-1/etc/monitor-promise/check-_prefer-gzip-encoding-to-backend-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_prefer-gzip-encoding-to-backend-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_re6st-optimal-test-re6st-optimal-test
TestSlave-1/etc/monitor-promise/check-_server-alias-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_server-alias-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify-unverified-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify-unverified-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-eventsource-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-eventsource-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-notebook-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-notebook-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-redirect-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-redirect-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-default-path-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-default-path-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-path-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-path-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify-unverified-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify-unverified-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-ssl-proxy-verify_ssl_proxy_ca_crt-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-http-port-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-http-port-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-https-port-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_type-zope-virtualhostroot-https-port-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_url-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_url-error-log-last-hour
TestSlave-1/etc/monitor-promise/check-_url_https-url-error-log-last-day
TestSlave-1/etc/monitor-promise/check-_url_https-url-error-log-last-hour
\ No newline at end of file
TestSlave-0/etc/promise/check-free-disk-space
TestSlave-0/etc/promise/monitor-http-frontend
TestSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestSlave-1/etc/promise/apache-frontend-is-running-actual-software-release
TestSlave-1/etc/promise/apache-mpm-watchdog
TestSlave-1/etc/promise/apache_cached
TestSlave-1/etc/promise/apache_frontend_ipv4_http
TestSlave-1/etc/promise/apache_frontend_ipv4_https
TestSlave-1/etc/promise/apache_frontend_ipv6_http
TestSlave-1/etc/promise/apache_frontend_ipv6_https
TestSlave-1/etc/promise/apache_ssl_cached
TestSlave-1/etc/promise/check-free-disk-space
TestSlave-1/etc/promise/frontend-apache-configuration-promise
TestSlave-1/etc/promise/monitor-http-frontend
TestSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestSlave-1/etc/promise/nginx-configuration-promise
TestSlave-1/etc/promise/nginx_frontend_ipv4_http
TestSlave-1/etc/promise/nginx_frontend_ipv4_https
TestSlave-1/etc/promise/nginx_frontend_ipv6_http
TestSlave-1/etc/promise/nginx_frontend_ipv6_https
TestSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestSlave-1/etc/promise/re6st-connectivity
TestSlave-1/etc/promise/trafficserver-cache-availability
TestSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestSlave-0/etc/promise/check-free-disk-space
TestSlave-0/etc/promise/monitor-http-frontend
TestSlave-0/etc/promise/monitor-httpd-listening-on-tcp
TestSlave-0/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestSlave-1/etc/promise/caddy-frontend-is-running-actual-software-release
TestSlave-1/etc/promise/caddy_cached
TestSlave-1/etc/promise/caddy_frontend_ipv4_http
TestSlave-1/etc/promise/caddy_frontend_ipv4_https
TestSlave-1/etc/promise/caddy_frontend_ipv6_http
TestSlave-1/etc/promise/caddy_frontend_ipv6_https
TestSlave-1/etc/promise/caddy_ssl_cached
TestSlave-1/etc/promise/check-free-disk-space
TestSlave-1/etc/promise/frontend-caddy-configuration-promise
TestSlave-1/etc/promise/monitor-http-frontend
TestSlave-1/etc/promise/monitor-httpd-listening-on-tcp
TestSlave-1/etc/promise/nginx-configuration-promise
TestSlave-1/etc/promise/nginx_frontend_ipv4_http
TestSlave-1/etc/promise/nginx_frontend_ipv4_https
TestSlave-1/etc/promise/nginx_frontend_ipv6_http
TestSlave-1/etc/promise/nginx_frontend_ipv6_https
TestSlave-1/etc/promise/promise-monitor-httpd-is-process-older-than-dependency-set
TestSlave-1/etc/promise/promise-nginx-is-process-older-than-dependency-set
TestSlave-1/etc/promise/re6st-connectivity
TestSlave-1/etc/promise/trafficserver-cache-availability
TestSlave-1/etc/promise/trafficserver-port-listening
\ No newline at end of file
TestSlave-0:bootstrap-monitor EXITED
TestSlave-0:certificate_authority-on-watch RUNNING
TestSlave-0:crond RUNNING
TestSlave-0:monitor-httpd-graceful EXITED
TestSlave-0:monitor-httpd-on-watch RUNNING
TestSlave-1:bootstrap-monitor EXITED
TestSlave-1:certificate_authority-on-watch RUNNING
TestSlave-1:crond-on-watch RUNNING
TestSlave-1:frontend-apache-safe-graceful EXITED
TestSlave-1:frontend-nginx-safe-graceful EXITED
TestSlave-1:frontend_apache-on-watch RUNNING
TestSlave-1:frontend_nginx-on-watch RUNNING
TestSlave-1:monitor-httpd-graceful EXITED
TestSlave-1:monitor-httpd-on-watch RUNNING
TestSlave-1:trafficserver-on-watch RUNNING
TestSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
TestSlave-0:bootstrap-monitor EXITED
TestSlave-0:certificate_authority-on-watch RUNNING
TestSlave-0:crond RUNNING
TestSlave-0:monitor-httpd-graceful EXITED
TestSlave-0:monitor-httpd-on-watch RUNNING
TestSlave-1:6tunnel-11080-on-watch RUNNING
TestSlave-1:6tunnel-11443-on-watch RUNNING
TestSlave-1:6tunnel-12080-on-watch RUNNING
TestSlave-1:6tunnel-12443-on-watch RUNNING
TestSlave-1:6tunnel-26011-on-watch RUNNING
TestSlave-1:6tunnel-26012-on-watch RUNNING
TestSlave-1:bootstrap-monitor EXITED
TestSlave-1:certificate_authority-on-watch RUNNING
TestSlave-1:crond-on-watch RUNNING
TestSlave-1:frontend-caddy-safe-graceful EXITED
TestSlave-1:frontend-nginx-safe-graceful EXITED
TestSlave-1:frontend_caddy-on-watch RUNNING
TestSlave-1:frontend_nginx-on-watch RUNNING
TestSlave-1:monitor-httpd-graceful EXITED
TestSlave-1:monitor-httpd-on-watch RUNNING
TestSlave-1:trafficserver-on-watch RUNNING
TestSlave-1:trafficserver-reload EXITED
watchdog:watchdog RUNNING
\ No newline at end of file
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAp0BSMfhzYo62X7FtSivZRpFn3HH5ij/fhQGla3C7gCIjsQCe
FZwYvK6i+qyGz4vC6fxj04ZHrAn6Xh3AQN/HA9OGEew0opL1tPtLoblbWTQv9gqh
nBupfPPZnvf7DOzfMKUvcl2RJAUZ9jWLGiUvYhtdCVGR9evq1z6O5ZMfoy29L1fB
Qc7k8Y6+bgunu85uVXxIxZQkb9wWY6A6B1qKLYkF3qi/6hto/XY+DEL23aBzWLuz
Zv1LmrzFarAsnc/UzsubrPaTho3EknNcfIxfNioFf0MBykEhTwZh6owh2c70ri2y
J0mg3bGMDcQyxlZrGPQVAlV9/1zrIKogrufDtQIDAQABAoIBACqXLZc+DpwNfZG2
y/70VZsr0ggIGiTDiTcEqUxH4+eIShB7+MXF/2KlEinFn3rgu1z8gatO6Zd83v3y
k4+xrKtjxSNxRCIWTG2vBJ6FZia8LG56XJc1UB7athNOUOcEtv1bQ07bVueWSPsy
vV6GE5/nGfUSiZnXXvE7JAaARbE2vix85CEZbSqps4plw+IRla5izgk2lfGeXZO4
tv0ci+5C+U5CbOA+i9I/m0qZBAqzBqCxiN/VRZSG6kxc0XF58NaJNCFqGUCzd+On
nLhSWxE+0+roj4BSsV8H2AHQzFy/d9eMiSoSGPLb0Sa0zvbcvf6SeknymEiTTAUK
nj94do0CgYEA0ontvQtCir443/2rkaUeXscJQO07QeGqztgSjEZj5GiT9cgBqlWQ
DsY6BoOHHMjJcWy4gEiz+whZOw87exy1ECevx5fazQzBwJvMD3qTOilOk49VzKs1
xrOdm3Me3E3X8AT3kKxrGdT/kHWlCij/Y+SIq2+YVh6t15p9P51eY2MCgYEAy12Q
K+llzNyL/6ml7CczfjNHkUlIMXlHs+bRk1eG+clUmoIQR7bxuhM6G23auGpq58mu
KhfThEytxU1vDSsXJKueLD59pWRDvwLDlLxoXXWgkdzWRMzKkJc/vd3GTJBW2ZpX
e66TEowBJkaftVAkGnded9EoKQKbGF2+/4/chAcCgYA1/8xrJT0u6rUZti1QEMKm
WnRkI7SEJEY0ATVYpyEtzyjL7D2JG6L0NyFg1FFOL62DGviDZqJK64w/WpvN6sIB
37v0/FzRJMl5BjyjZ7PlQfz2WdgOw4bqbN0qpq8uoASXeh6pC5/4oyndOl9XKMbA
LzhiiB/RTtMVrnkbXNh9swKBgDhBZI1RHhECfVO2ySg/W9YwNz7wZ6EP7I7ObfD1
SGg2kkm/auN7rviLMwq9Y8CZ54LA3oXUW3WAhJ1Mo0igP+Gr+7A/hSBIURk4mYO+
bpxT2pwe28LiZ7KBtGdAPweU8gF12XdkPljmE7dT2AAe8C3GEYLRf+uARgkCfcBS
OmznAoGAFXa3/sx8uBrA4rxpE9b/nEQNr8n0NatH7tW3fry88wYBLyFYdHrAmM/p
7a1/iLFvCl3fzZdiAxPplFw6neCpxD2ghHXZjN5njevs9AECNhf5M3EraNJW3tn5
b6+wwlbNqFm8NymFoq3Zeq8HUXPQbdUKOwSiwxQ5+5XdSsYOZoQ=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDRTCCAi0CCQDQ1EVpyJg5UzANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJB
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMRwwGgYDVQQDDBNUZXN0IFNlcnZlciBSb290IENBMB4XDTE4MDYy
NzExMjIxMloXDTI4MDYyNDExMjIxMlowZjELMAkGA1UEBhMCQVUxEzARBgNVBAgM
ClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEf
MB0GA1UEAwwWdGVzdHNlcnZlci5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKdAUjH4c2KOtl+xbUor2UaRZ9xx+Yo/34UBpWtwu4Ai
I7EAnhWcGLyuovqshs+Lwun8Y9OGR6wJ+l4dwEDfxwPThhHsNKKS9bT7S6G5W1k0
L/YKoZwbqXzz2Z73+wzs3zClL3JdkSQFGfY1ixolL2IbXQlRkfXr6tc+juWTH6Mt
vS9XwUHO5PGOvm4Lp7vOblV8SMWUJG/cFmOgOgdaii2JBd6ov+obaP12PgxC9t2g
c1i7s2b9S5q8xWqwLJ3P1M7Lm6z2k4aNxJJzXHyMXzYqBX9DAcpBIU8GYeqMIdnO
9K4tsidJoN2xjA3EMsZWaxj0FQJVff9c6yCqIK7nw7UCAwEAATANBgkqhkiG9w0B
AQsFAAOCAQEAtEfuCYN5xQ+xwFF4UwJtQvv+DGlxzSPZUxY4h5BH7BbyC+XVvo7l
iY0pCHI7PsZRSMK3KaUuLYll/7mNB6GCE2zocWfIZwTgoJEhw35iVj07SYIcnd5h
R1XBGEn2EQfZEkjH5kuTBUKR1EE5yJimhG89chQkP5eAWsPNUM55XmojNt5uZawb
C8bJXGtlNGSgmfXCcGBp9VW3ImEKDoyLJuBqIcBfMv/3ENnKbuTt+cLaaLWkqX48
JSqEL41S6tU8Jmv3HrhSWmZJjCJ+gRXKANhlAOxuddTkaEnToe9G51Ekj0uRHF37
LHdySTpMHXg1Cm4njhLqVcRoikrSkYcHPA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDmTCCAoGgAwIBAgIJAOZ30I7+VqTNMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxHDAaBgNVBAMME1Rlc3QgU2VydmVyIFJvb3QgQ0EwHhcN
MTgwNjI3MTExOTEzWhcNMjgwNjI0MTExOTEzWjBjMQswCQYDVQQGEwJBVTETMBEG
A1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg
THRkMRwwGgYDVQQDDBNUZXN0IFNlcnZlciBSb290IENBMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA6arXFNc2fl39wAgvFvB7XQILJ8xT/89n6KwvZHIs
eqptNgT7k2LCrsWDqvQS+fsAY62OSpt6gWckM2Q9toY6niXzvElj/+C3FxdEounN
dgHfG1M3imTbAPR/E2bPGUoWtod0DrHkIF3HlqvjTsKvk0t2XglbobZc3JFHzw2R
Vnh0NjGHxH5tvE0hiM2rdyMUOXJeLqz/iILqOEjBscHKUcb9rTvI08N0/FFpRtbB
JAgQeZB85ZxGqyg1pRwveG+mDALv9IImqtIpe9D/OwjOyF8MErS/Yfjqyw2eejj/
dX9GNFnuGxlyZ7GKRncHPR2QmKrIz+1NNqsXITPs5zVo/QIDAQABo1AwTjAdBgNV
HQ4EFgQUerhRsTxEadhORRVlRtqZryF456kwHwYDVR0jBBgwFoAUerhRsTxEadhO
RRVlRtqZryF456kwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAs6Oi
CMhQ6a8bW7u8jcC7Y2/50TlviQo+IQ44wgCJrnZCHDXdMLwwm7VjiUl33Z6YjnT+
UVzkA7O2aTHop1peR3kpJ/JP6yrGudj7gZJNLlQXEKopT0MFaZWxI80LP8gIHlsx
nzhe6Kzw8xtGiC0O4j3aJwsJp/ggaNYp37AyEA0KkGbLtA5QrpfZfvPV/zoiXQbn
HkzaYgf1VcfwjoSi4cBO0IE2iHWjGKCoo3WGCKzoyY/ldpyqFhOvAhL5FoS7hQcl
5meowzyz7OVGqvbhZgETNqFyl0la9JeMhbDG3+tHX6K5dbcOYRJUv/INO2CNnW/K
o1vE6iTVxjew2tnoMQ==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA6arXFNc2fl39wAgvFvB7XQILJ8xT/89n6KwvZHIseqptNgT7
k2LCrsWDqvQS+fsAY62OSpt6gWckM2Q9toY6niXzvElj/+C3FxdEounNdgHfG1M3
imTbAPR/E2bPGUoWtod0DrHkIF3HlqvjTsKvk0t2XglbobZc3JFHzw2RVnh0NjGH
xH5tvE0hiM2rdyMUOXJeLqz/iILqOEjBscHKUcb9rTvI08N0/FFpRtbBJAgQeZB8
5ZxGqyg1pRwveG+mDALv9IImqtIpe9D/OwjOyF8MErS/Yfjqyw2eejj/dX9GNFnu
GxlyZ7GKRncHPR2QmKrIz+1NNqsXITPs5zVo/QIDAQABAoIBAQDRYTFrTlFZOJXZ
TjwL3R9dvygJ2HDoh4w/lJK++gPbQv2raxmW/ucePoR2WlDqyTyXFPys49cJP0fT
+R3HgU3jSnS2IjlGHrFRMpthNAnUlWa7EH1zOF5545w+4V/v9FCX7JZVWJfnXMEs
xQdhGtjDLtp49v+xzzw0tMXYxfqWtJBuFT2Dft60lH/kcCyD7TWQD30OyP28QuYK
Zn4uCDBCOYuHTb/eu6MLKGRkuyRbgXoCCjjziQ/u8lcUx7nPa1qTdGHAglNei5CV
nrDsaEQGd3U7jUgOpbd+a5E5UaFtR8HoBtIDQf72JTWBrKSjkmIHZsJSU8tMKZi4
nGr7mA4hAoGBAPcGQWdAa6qZIKTwp6EDJMBbSDH70ykBFgE4nmKAlxcfPlR0CU3R
iahVvvuNyE//rPEhZBGqh8VEfZfkz1H5zLJQS5EV6ePbKYQE2q9JHugMrw8zh5MH
89NpK+O9p/3MrCPAZgWGVQ3nfLkV0WTGGiSdLFDAvBtRZeMmsi2JedTJAoGBAPIo
V1bwRzihtvZT/rc86jYvJbMR49lbal8pHsIg5FS0EAgQp4tgMnEfqI3UHvjYIUJa
CursrHOFX0hypP2DW2BxJ6yMYv/jQivyxziCSd+xrSfR0B3vjJ33ayqs3EnS4MzY
jbaWm1O2Z585ZlulqGWfhJ3m7dzeGqXmNrMWABCVAoGAYU59hQbDYrhfO5nw7mQm
nf9XORlR3N0opeJ/wZ2V5u3Px8TNxXG9ICpmyQDY32p/3ZyhprPeN777GlJvuIMG
N1eZ7NUNBUzX1cFzw4iyPAaDDyHlTe3cBnNvbo7PFhMB3DN1/Mclygxd/SqzCVdg
BPxE8Kp7budpk0ky9u0oqMECgYEAq6hPKXDQe+Oe6AToxgnnWRuY1NR0uOqlf+mN
RT29vhGaX602p4U8nJY9jLR2dB35jah4nsnBAW7k+V1TeeY4yyfLYPRvZUc67B6A
fJ1XMrwnq9d+eQoLmxr9m9XHnolfE7ba1jjyyKe/0s4Esii/M7KddrVxniTPrRSB
Z/fLefUCgYEAl2Al2BK4ZYK6HSeFxZ1kaVkcefL1QBMzgLY8LPVpReoaULdFzwat
3elM8C31FDBvIaWzJCQMIIrFEldvU4tvBF7Mbe8lDDQXotoI6zTWMnNUGV3Xd0wc
hep0oINBctav7pVJ7Mf+X0Wqfc4D40FPbMzHMUxfdKs9eo9qR/fktYI=
-----END RSA PRIVATE KEY-----
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
import os
import socket
import subprocess
from contextlib import closing
import logging
import StringIO
import json
from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler
import xmlrpclib
import supervisor.xmlrpc
from erp5.util.testnode.SlapOSControler import SlapOSControler
from erp5.util.testnode.ProcessManager import ProcessManager
LOCAL_IPV4 = os.environ['LOCAL_IPV4']
GLOBAL_IPV6 = os.environ['GLOBAL_IPV6']
def der2pem(der):
certificate, error = subprocess.Popen(
'openssl x509 -inform der'.split(), stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE
).communicate(der)
if error:
raise ValueError(error)
return certificate
def findFreeTCPPort(ip=''):
"""Find a free TCP port to listen to.
"""
family = socket.AF_INET6 if ':' in ip else socket.AF_INET
with closing(socket.socket(family, socket.SOCK_STREAM)) as s:
s.bind((ip, 0))
return s.getsockname()[1]
class SlapOSInstanceTestCase(unittest.TestCase):
def getSupervisorRPCServer(self):
"""Returns a XML-RPC connection to the supervisor used by slapos node
Refer to http://supervisord.org/api.html for details of available methods.
"""
# xmlrpc over unix socket https://stackoverflow.com/a/11746051/7294664
return xmlrpclib.ServerProxy(
'http://slapos-supervisor',
transport=supervisor.xmlrpc.SupervisorTransport(
None,
None,
# XXX hardcoded socket path
serverurl="unix://{working_directory}/inst/supervisord.socket"
.format(**self.config)))
@classmethod
def getSoftwareURLList(cls):
"""Return URL of software releases to install.
To be defined by subclasses.
"""
return [os.path.realpath(os.environ['TEST_SR'])]
@classmethod
def getInstanceParameterDict(cls):
"""Return instance parameters
To be defined by subclasses if they need to request instance with specific
parameters.
"""
return {}
# TODO: allow subclasses to request a specific software type ?
@classmethod
def setUpWorkingDirectory(cls):
cls.working_directory = os.environ.get(
'SLAPOS_TEST_WORKING_DIR',
os.path.join(os.path.dirname(__file__), '.slapos'))
# To prevent error: Cannot open an HTTP server: socket.error reported
# AF_UNIX path too long This `working_directory` should not be too deep.
# Socket path is 108 char max on linux
# https://github.com/torvalds/linux/blob/3848ec5/net/unix/af_unix.c#L234-L238
if len(cls.working_directory + '/inst/supervisord.socket.xxxxxxx') > 108:
raise RuntimeError(
'working directory ( {} ) is too deep, try setting '
'SLAPOS_TEST_WORKING_DIR'.format(cls.working_directory))
if not os.path.exists(cls.working_directory):
os.mkdir(cls.working_directory)
@classmethod
def setUpConfig(cls):
cls.config = {
"working_directory": cls.working_directory,
"slapos_directory": cls.working_directory,
"log_directory": cls.working_directory,
"computer_id": 'slapos.test', # XXX
'proxy_database': os.path.join(cls.working_directory, 'proxy.db'),
'partition_reference': cls.__name__,
# "proper" slapos command must be in $PATH
'slapos_binary': 'slapos',
}
ipv4_address = LOCAL_IPV4
ipv6_address = os.environ['GLOBAL_IPV6']
cls.config['proxy_host'] = cls.config['ipv4_address'] = ipv4_address
cls.config['ipv6_address'] = ipv6_address
cls.config['proxy_port'] = findFreeTCPPort(ipv4_address)
cls.config['master_url'] = 'http://{proxy_host}:{proxy_port}'.format(
**cls.config)
@classmethod
def setUpSlapOSController(cls):
cls._process_manager = ProcessManager()
# XXX this code is copied from testnode code
cls.slapos_controler = SlapOSControler(
cls.working_directory,
cls.config
)
slapproxy_log = os.path.join(cls.config['log_directory'], 'slapproxy.log')
logger = logging.getLogger(__name__)
logger.debug('Configured slapproxy log to %r', slapproxy_log)
cls.software_url_list = cls.getSoftwareURLList()
cls.slapos_controler.initializeSlapOSControler(
slapproxy_log=slapproxy_log,
process_manager=cls._process_manager,
reset_software=False,
software_path_list=cls.software_url_list)
cls._process_manager.supervisord_pid_file = os.path.join(
cls.slapos_controler.instance_root, 'var', 'run', 'supervisord.pid')
@classmethod
def runSoftwareRelease(cls):
logger = logging.getLogger()
logger.level = logging.DEBUG
stream = StringIO.StringIO()
stream_handler = logging.StreamHandler(stream)
logger.addHandler(stream_handler)
try:
cls.software_status_dict = cls.slapos_controler.runSoftwareRelease(
cls.config, environment=os.environ)
stream.seek(0)
stream.flush()
message = ''.join(stream.readlines()[-100:])
assert cls.software_status_dict['status_code'] == 0, message
finally:
logger.removeHandler(stream_handler)
del stream
@classmethod
def runComputerPartition(cls):
logger = logging.getLogger()
logger.level = logging.DEBUG
stream = StringIO.StringIO()
stream_handler = logging.StreamHandler(stream)
logger.addHandler(stream_handler)
instance_parameter_dict = cls.getInstanceParameterDict()
try:
cls.instance_status_dict = cls.slapos_controler.runComputerPartition(
cls.config,
cluster_configuration=instance_parameter_dict,
environment=os.environ)
stream.seek(0)
stream.flush()
message = ''.join(stream.readlines()[-100:])
assert cls.instance_status_dict['status_code'] == 0, message
finally:
logger.removeHandler(stream_handler)
del stream
# FIXME: similar to test node, only one (root) partition is really
# supported for now.
computer_partition_list = []
for i in range(len(cls.software_url_list)):
computer_partition_list.append(
cls.slapos_controler.slap.registerOpenOrder().request(
cls.software_url_list[i],
# This is how testnode's SlapOSControler name created partitions
partition_reference='testing partition {i}'.format(
i=i, **cls.config),
partition_parameter_kw=instance_parameter_dict))
# expose some class attributes so that tests can use them:
# the ComputerPartition instances, to getInstanceParameterDict
cls.computer_partition = computer_partition_list[0]
# expose instance directory
cls.instance_path = os.path.join(
cls.config['working_directory'],
'inst')
# the path of the instance on the filesystem, for low level inspection
cls.computer_partition_root_path = os.path.join(
cls.instance_path,
cls.computer_partition.getId())
# expose software directory, extract from found computer partition
cls.software_path = os.path.realpath(os.path.join(
cls.computer_partition_root_path, 'software_release'))
@classmethod
def setUpClass(cls):
try:
cls.setUpWorkingDirectory()
cls.setUpConfig()
cls.setUpSlapOSController()
cls.runSoftwareRelease()
cls.runComputerPartition()
except Exception:
cls.tearDownClass()
raise
@classmethod
def tearDownClass(cls):
if getattr(cls, '_process_manager', None) is not None:
cls._process_manager.killPreviousRun()
class TestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/json")
self.send_header('Set-Cookie', 'secured=value;secure')
self.send_header('Set-Cookie', 'nonsecured=value')
self.end_headers()
response = {
'Path': self.path,
'Incoming Headers': self.headers.dict
}
self.wfile.write(json.dumps(response, indent=2))
if __name__ == '__main__':
ip = LOCAL_IPV4
port = 8888
server = HTTPServer((ip, port), TestHandler)
print 'http://%s:%s' % server.server_address
server.serve_forever()
-----BEGIN CERTIFICATE-----
MIIDjzCCAnegAwIBAgIJAP4QzV9d5d8KMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxFjAUBgNVBAMMDSouZXhhbXBsZS5jb20wIBcNMTgwNDE3
MTE0MjAxWhgPMjExODAzMjQxMTQyMDFaMF0xCzAJBgNVBAYTAkFVMRMwEQYDVQQI
DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQx
FjAUBgNVBAMMDSouZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQC0MNnojTq6Yp60ecvP5lZGa6owZp64sumaT66JInTFJcSV/ls0AbPN
KPTcNRgbFLIuv/3Xhgi6YAxIz2PXdCDPj1fp4rVIijhpedaWZaIOeTqSGEg+5/iL
4UTxm166NgCU1zp0QsmU8MXJFv4YxTZsF9LlGFcP6uUQ9sY98yv+hErCxRXo+dXd
GGG4LTVLGPeRYNX2JVD5BxoNkL5/3IMylrFvI8aRFTKVn1P8UPJ5K9du3E0wHJY6
MkstZX3xKcGKSn2w1zIaq/NcrbLXvp6eZauLtMpZ9vW+CtYV3diOm2TiMvQIyCRM
4mWbaf76bpGiz9/+11w6U9n6zMzKTq+5AgMBAAGjUDBOMB0GA1UdDgQWBBT/Kswu
BKM3GXaIWvQ8Vs1xhs/1vzAfBgNVHSMEGDAWgBT/KswuBKM3GXaIWvQ8Vs1xhs/1
vzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAeeV7VIqbNL6Xe0I5y
fl44ogBY0zoYJH+p7HCebazZKepy7f+EeWv8B3dHODrilSYCnsOqhta8mMSMrgsT
TFByr/8NN/4UFe9FeKnxD9Sun0EetESkaeMqAGCK921lT0eU4IhA0JLRj16HomuK
I/JBFwUXFn6vVypw5R41zwnikv+EB0fSC4biSXWXUarGqlRCF7o00CPKqAaTE0yX
H4Yz3lR/Vuce7uFvkIY+F4vXtq1sy/tb4QBWlDS6t7cmeBGcvaQ8mlndA9T+us0l
/wb9mzdTcwkrkM2kk++GnS0NCAQfOalF3x8wG6j8DrU2dQ1NXh205c/zo0BljQr8
P84v
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC0MNnojTq6Yp60
ecvP5lZGa6owZp64sumaT66JInTFJcSV/ls0AbPNKPTcNRgbFLIuv/3Xhgi6YAxI
z2PXdCDPj1fp4rVIijhpedaWZaIOeTqSGEg+5/iL4UTxm166NgCU1zp0QsmU8MXJ
Fv4YxTZsF9LlGFcP6uUQ9sY98yv+hErCxRXo+dXdGGG4LTVLGPeRYNX2JVD5BxoN
kL5/3IMylrFvI8aRFTKVn1P8UPJ5K9du3E0wHJY6MkstZX3xKcGKSn2w1zIaq/Nc
rbLXvp6eZauLtMpZ9vW+CtYV3diOm2TiMvQIyCRM4mWbaf76bpGiz9/+11w6U9n6
zMzKTq+5AgMBAAECggEAR9n2+pFearYqnMK4b9Vkb7485gH1pqbJGdxON6bCs16F
Dl6X1ZwcK2H6idiuHRZamuO5//gVgOQN4fa41FAdSUbagowBR8S+C+kmlWA/h8/1
eA4wuMzdQkH4sPMIie5Auxk72OJM6ZQ8+huuBQiW0/GICgxzowhCgUo18LwHvfwt
XWLHplRFczgM4WEu+HVx1W9y/irOhEUEzwNfXdDTVE4bnwzb24qR0CRIdp3gc8Os
JoUFMgbV3qfJLmzqURLIlVc3Y9FFbWrr5zhzTx2vvoT1j83e56qKHbKanr2R6NQZ
UOsCgDvzrc9WqKE9/hwvxvPlx/L3UWuhPMpljZ8gBQKBgQDX4Qo27l8KPk9fXA18
SrRcAAGN+moc+Y0T9WbcbXCJLLU6TO3eJqW9H3Kwb80O/zycUBFK/dIOwZZYgsuQ
oXFG4ykSXFY/JGTEBIkvQ7LI/7t5mn0xlw3tqB7xuMO5QEyZMQFi0xP5h1B5coiO
Wv9T1xit4FHX2EN/CJLwlzzl1wKBgQDVrdvGi+j/1pGaEST1yhvrDduHrlMsF4BI
X8VaNXNXg9+GxsAA6+pRPRoHvmmz/RUr/km+JxWLHEZpFDOhIzJV4JYXv/q7KDH+
Mjf7uyRshBnR+QU38RqkENIJhEZJSa8ZYmkgU9yCDozkfVzYKdxUy6Z0+o2Omzls
cpZP1PFE7wKBgQCGXZx0+kMPZh8TFIGURg8iYCKXkzBu3miP7qNaOYfc6YXXRsCb
D+UC5MsGxF+WoQjBphhNW9RduOJyLt6zI7kUzRjoQ66u2GEbnFMipvlln765fo3D
yugxbv3rp/uylzHV+6mIMCbzneRZ4w7ZxAu9zFihCMkIFqRUMir7MrcFuwKBgFbK
88ZF9jJU+XdXF2gu3AAx9MW77VSvhw/ets7ZfyxBCH46JKs7KEYvR291zIGrfvoL
o/B09681oPP1nLMLFNsFCnJDLJjwzr2tsEez0CuzzLkZKSF78ZJKssXi0JncMB9j
dcgHyD2bo2b79MZo2nIm9kn1q6INMtn2AVAT8pxJAoGAZfysuUMc0bdKVi41SD0A
Ej7qX+qbXX+aA4OkTqJP3QxssD6CuZZwUKW7qj8AoOcLKsmwdjetetny46OMEXzN
5Fk3ahCD1cycFGBawNY10x5Xy+4iApzPiO1Ujd3t7FAIrLPWFwzmLIL8pxUNuHEn
OC9RrI4tzsvWHhMaLKVCh0g=
-----END PRIVATE KEY-----
[buildout]
extends =
../../stack/caddy/buildout.cfg
\ No newline at end of file
# Apache frontend test
This software release is simply to run the test suite from `../caddy-frontend/test/setup.py`,
but using apache-frontend software.
[buildout]
extends =
../caddy-frontend/software.cfg
[configuration]
test_software_release = ${:_profile_base_location_}/../../../apache-frontend/software.cfg
\ No newline at end of file
# Caddy frontend test
This software release is simply to run the test suite from `../caddy-frontend/test/setup.py`
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[template]
filename = instance.cfg
md5sum = 2eba374ea5b7ec6c95a1f79066cfb46b
[buildout]
parts =
slapos-test-runner
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
[download-source]
recipe = slapos.recipe.build:gitclone
git-executable = ${git:location}/bin/git
[slapos]
<= download-source
repository = ${slapos-repository:location}
[create-directory]
recipe = slapos.cookbook:mkdirectory
bin = $${buildout:directory}/bin
working-dir = $${buildout:directory}/tmp
[slapos-test-runner]
recipe = slapos.cookbook:wrapper
wrapper-path = $${create-directory:bin}/runTestSuite
command-line =
${buildout:bin-directory}/runTestSuite
--python_interpreter=${buildout:bin-directory}/${eggs:interpreter}
--source_code_path_list=$${slapos:location}/software/caddy-frontend/test
# XXX slapos.cookbook:wrapper does not allow extending env, so we add some default $PATH entries ( not sure they are needed )
# PATH=${buildout:bin-directory}:/usr/bin/:/bin/
environment =
LOCAL_IPV4=$${slap-configuration:ipv4-random}
GLOBAL_IPV6=$${slap-configuration:ipv6-random}
CURL=${curl:location}/bin/curl
SLAPOS_TEST_WORKING_DIR=$${create-directory:working-dir}
TEST_SR=${template:test_software_release}
[buildout]
extends =
../../../../component/git/buildout.cfg
../../../../component/curl/buildout.cfg
../../../../stack/slapos.cfg
./buildout.hash.cfg
parts =
slapos-cookbook
eggs
template
[setup-develop-egg]
recipe = zc.recipe.egg:develop
[slapos.test.caddy-frontend-setup]
<= setup-develop-egg
egg = slapos.test.caddy-frontend
setup = ${slapos-repository:location}/software/caddy-frontend/test/
[erp5.util-setup]
<= setup-develop-egg
egg = erp5.util[testnode]
setup = ${erp5.util-repository:location}
[eggs]
recipe = zc.recipe.egg
eggs =
${slapos.test.caddy-frontend-setup:egg}
${erp5.util-setup:egg}
slapos.core
entry-points =
runTestSuite=erp5.util.testsuite:runTestSuite
scripts =
runTestSuite
slapos
interpreter=
python_for_test
[git-clone-repository]
recipe = slapos.recipe.build:gitclone
git-executable = ${git:location}/bin/git
forbid-download-cache = true
[slapos-repository]
<= git-clone-repository
repository = https://lab.nexedi.com/nexedi/slapos.git
branch = master
# XXX we need an unreleased ( 0.4.51 ) version of erp5.util runTestSuite
# later we can stop fetching it from git and just use egg
[erp5.util-repository]
<= git-clone-repository
repository = https://lab.nexedi.com/nexedi/erp5.git
revision = 69013fa0fb67501089c776ab5e75d7bbf2e0e3bc
branch = master
[configuration]
test_software_release = ${:_profile_base_location_}/../../../caddy-frontend/software.cfg
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/template.cfg
mode = 640
test_software_release = ${configuration:test_software_release}
[versions]
# clear the version of tested eggs, to make sure we installed the developped ones
slapos.test.caddy-frontend =
erp5.util =
slapos.recipe.template = 4.3
forcediphttpsadapter = 1.0.1
# Re6stnet test
This software release is simply to run the test suite from `../re6stnet/test/setup.py`
Nexedi staff can see the results of this test from the test suite
`SLAPOS-RE6STNET-TEST` in test result module.
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# But avoid directories, they are not portable.
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[template]
filename = instance.cfg.in
md5sum = 9c5ec49295ceae71df715bf1c90976e2
[buildout]
parts =
slapos-test-runner
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
[download-source]
recipe = slapos.recipe.build:gitclone
git-executable = ${git:location}/bin/git
[slapos]
<= download-source
repository = ${slapos-repository:location}
[create-directory]
recipe = slapos.cookbook:mkdirectory
bin = $${buildout:directory}/bin
working-dir = $${buildout:directory}/tmp/
[slapos-test-runner]
recipe = slapos.cookbook:wrapper
wrapper-path = $${create-directory:bin}/runTestSuite
command-line =
${buildout:bin-directory}/runTestSuite
--python_interpreter=${buildout:bin-directory}/${eggs:interpreter}
--source_code_path_list=$${slapos:location}/software/re6stnet/test
# XXX slapos.cookbook:wrapper does not allow extending env, so we add some default $PATH entries ( not sure they are needed )
environment =
PATH=${buildout:bin-directory}:/usr/bin/:/bin/
LOCAL_IPV4=$${slap-configuration:ipv4-random}
GLOBAL_IPV6=$${slap-configuration:ipv6-random}
SLAPOS_TEST_WORKING_DIR=$${create-directory:working-dir}
[buildout]
extends =
../../../../component/git/buildout.cfg
../../../../stack/slapos.cfg
./buildout.hash.cfg
parts =
slapos-cookbook
eggs
template
[setup-develop-egg]
recipe = zc.recipe.egg:develop
[slapos.test.re6stnet-setup]
<= setup-develop-egg
egg = slapos.test.re6stnet
setup = ${slapos-repository:location}/software/re6stnet/test/
[erp5.util-setup]
<= setup-develop-egg
egg = erp5.util[testnode]
setup = ${erp5.util-repository:location}
[eggs]
recipe = zc.recipe.egg
eggs =
${slapos.test.re6stnet-setup:egg}
${erp5.util-setup:egg}
slapos.core
entry-points =
runTestSuite=erp5.util.testsuite:runTestSuite
scripts =
runTestSuite
slapos
interpreter=
python_for_test
[git-clone-repository]
recipe = slapos.recipe.build:gitclone
git-executable = ${git:location}/bin/git
forbid-download-cache = true
branch = master
[slapos-repository]
<= git-clone-repository
repository = https://lab.nexedi.com/nexedi/slapos.git
# XXX we need an unreleased ( 0.4.51 ) version of erp5.util runTestSuite
# later we can stop fetching it from git and just use egg
[erp5.util-repository]
<= git-clone-repository
repository = https://lab.nexedi.com/nexedi/erp5.git
revision = 69013fa0fb67501089c776ab5e75d7bbf2e0e3bc
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/template.cfg
mode = 640
[versions]
# clear the version of tested eggs, to make sure we installed the developped ones
slapos.test.re6stnet =
erp5.util =
#erp5.util = 0.4.51
pyasn1 = 0.4.2
slapos.recipe.template = 4.3
......@@ -28,6 +28,17 @@ rendered = ${directory:etc}/mariadb.cnf
template = {{ template_neo_my_cnf }}
context = section parameter_dict my-cnf-parameters
[{{ section('binary-wrap-mysql') }}]
recipe = slapos.cookbook:wrapper
command-line = ${mysqld:mysql-base-directory}/bin/${:command} --defaults-file=${my-cnf:rendered}
wrapper-path = ${directory:bin}/${:command}
command = mysql
[{{ section('binary-neolog') }}]
recipe = slapos.cookbook:symbolic.link
target-directory = ${directory:bin}
link-binary = {{ bin_directory }}/neolog
{% set master_list = [] -%}
{% set admin_list = [] -%}
{% for k, v in slapparameter_dict.iteritems() -%}
......
......@@ -105,7 +105,7 @@ md5sum = 1fee10f02c2fa2a581e21878ca0fd704
[instance-neo-storage-mysql]
<= download-base-neo
md5sum = 9ca3283659f98713ffe3b08ba9442ff1
md5sum = 16024af1cde9c0fcc7e8e05ec0854b30
[template-neo-my-cnf]
<= download-base-neo
......
......@@ -25,4 +25,4 @@ neotest = ${:home}/neotest
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:bin}/${:_buildout_section_name_}
command-line = /bin/bash -c 'cd ${directory:neotest} && ${software:bin}/neotest-runTestSuite "$@"' runTestSuite
# vvv appends "$@" to argv ^^^ without shell-escaping
# "$@" is implicitly added to argv
......@@ -93,7 +93,7 @@ context =
[instance.cfg]
<= jinja2-template
md5sum = 19b011baacc5abf253da6a52bb90d1f8
md5sum = 8a40d365c85d70f057ce997405ac3e88
# eggs:
......
......@@ -92,6 +92,17 @@ recipe = slapos.cookbook:wrapper
command-line = ${powerdns:location}/bin/pdns_control reload --config-dir=$${pdns-directory:configuration}
wrapper-path = $${directory:etc-run}/pdns-reload
# Port redirection
[port-redirection]
<= jinja2-template-base
template = inline:
{%- raw %}
[{"srcPort": 53, "destPort": {{ pdns['port'] }}}]
{% endraw -%}
rendered = $${buildout:directory}/.slapos-port-redirect
extra-context =
section pdns pdns
# Promises
[pdns-promise-listen-port]
recipe = slapos.cookbook:check_port_listening
......@@ -136,6 +147,7 @@ parts =
pdns-configuration-template
pdns-server
pdns-reload
port-redirection
pdns-promise-listen-port
monitor-base
publish-connection-informations
......
......@@ -25,7 +25,7 @@ mode = 0644
[template-powerdns]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-powerdns.cfg
md5sum = 7710007c0bd1817e3c1485ea9ece1e23
md5sum = 8ef7c87e23dd63c945c7e292fef7385d
output = ${buildout:directory}/template-powerdns.cfg
mode = 0644
......
......@@ -184,6 +184,16 @@ name = re6stnet
log = ${re6st-registry-conf-dict:logfile}
post = test ! -s ${re6st-registry-wrapper:pid-file} || {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${re6st-registry-wrapper:pid-file} -s USR1
[port-redirection]
recipe = slapos.recipe.template:jinja2
template = inline:
{%- raw %}
[{"srcPort": 9201, "destPort": 9201, "destAddress": "{{ parameter_dict['ipv4'] }}"}]
{% endraw -%}
rendered = ${buildout:directory}/.slapos-port-redirect
context =
section parameter_dict re6st-registry-conf-dict
[re6st-registry-promise]
recipe = slapos.cookbook:check_port_listening
path = ${directory:promises}/re6st-registry
......@@ -221,7 +231,8 @@ parts =
apache-httpd
apache-httpd-graceful
publish
port-redirection
re6st-registry-promise
apache-registry-promise
monitor-base
......
......@@ -87,7 +87,7 @@ extra-context =
[template-re6stnet]
< = download-base
filename = instance-re6stnet.cfg.in
md5sum = 7d65efffeae3f9ae4e64699303a083b4
md5sum = 6f28b611a0e2415768238f5e8d29d36e
[template-apache-conf]
< = download-base
......
Tests for Re6stnet software release
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.re6stnet'
long_description = open("README.md").read()
setup(name=name,
version=version,
description="Test for SlapOS' Re6stnet",
long_description=long_description,
long_description_content_type='text/markdown',
maintainer="Nexedi",
maintainer_email="info@nexedi.com",
url="https://lab.nexedi.com/nexedi/slapos",
packages=find_packages(),
install_requires=[
'slapos.core',
'erp5.util',
'supervisor',
'psutil',
],
zip_safe=True,
test_suite='test',
)
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import os
import shutil
import urlparse
import tempfile
import requests
import socket
import StringIO
import subprocess
import json
import psutil
import utils
LOCAL_IPV4 = os.environ['LOCAL_IPV4']
GLOBAL_IPV6 = os.environ['GLOBAL_IPV6']
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
class Re6stnetTestCase(utils.SlapOSInstanceTestCase):
def setUp(self):
import logging
utils.SlapOSInstanceTestCase.setUp(self)
self.logger = logging.getLogger(__name__)
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
class TestRe6stnetRegistry(Re6stnetTestCase):
def test_listen(self):
connection_parameters = self.computer_partition.getConnectionParameterDict()
registry_url = connection_parameters['re6stry-local-url']
_ = requests.get(registry_url)
class TestPortRedirection(Re6stnetTestCase):
def test_portredir_config(self):
portredir_config_path = os.path.join(self.computer_partition_root_path, '.slapos-port-redirect')
with open(portredir_config_path) as f:
portredir_config = json.load(f)
self.assertDictContainsSubset({
'srcPort': 9201,
'destPort': 9201,
}, portredir_config[0])
##############################################################################
#
# Copyright (c) 2018 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
import os
import socket
from contextlib import closing
import logging
import xmlrpclib
import supervisor.xmlrpc
from erp5.util.testnode.SlapOSControler import SlapOSControler
from erp5.util.testnode.ProcessManager import ProcessManager
import slapos
def findFreeTCPPort(ip=''):
"""Find a free TCP port to listen to.
"""
family = socket.AF_INET6 if ':' in ip else socket.AF_INET
with closing(socket.socket(family, socket.SOCK_STREAM)) as s:
s.bind((ip, 0))
return s.getsockname()[1]
class SlapOSInstanceTestCase(unittest.TestCase):
@classmethod
def getSoftwareURLList(cls):
"""Return URL of software releases to install.
To be defined by subclasses.
"""
raise NotImplementedError()
@classmethod
def getInstanceParameterDict(cls):
"""Return instance parameters
To be defined by subclasses if they need to request instance with specific
parameters.
"""
return {}
# TODO: allow subclasses to request a specific software type ?
@classmethod
def setUpClass(cls):
try:
cls._setUpClass()
except:
cls.stopSlapOSProcesses()
raise
@classmethod
def _setUpClass(cls):
working_directory = os.environ.get(
'SLAPOS_TEST_WORKING_DIR',
os.path.join(os.path.dirname(__file__), '.slapos'))
# To prevent error: Cannot open an HTTP server: socket.error reported
# AF_UNIX path too long This `working_directory` should not be too deep.
# Socket path is 108 char max on linux
# https://github.com/torvalds/linux/blob/3848ec5/net/unix/af_unix.c#L234-L238
# Supervisord socket name contains the pid number, which is why we add
# .xxxxxxx in this check.
if len(working_directory + '/inst/supervisord.socket.xxxxxxx') > 108:
raise RuntimeError('working directory ( {} ) is too deep, try setting '
'SLAPOS_TEST_WORKING_DIR'.format(working_directory))
if not os.path.exists(working_directory):
os.mkdir(working_directory)
cls.config = config = {
"working_directory": working_directory,
"slapos_directory": working_directory,
"log_directory": working_directory,
"computer_id": 'slapos.test', # XXX
'proxy_database': os.path.join(working_directory, 'proxy.db'),
'partition_reference': cls.__name__,
# "proper" slapos command must be in $PATH
'slapos_binary': 'slapos',
}
# Some tests are expecting that local IP is not set to 127.0.0.1
ipv4_address = os.environ.get('LOCAL_IPV4', '127.0.1.1')
ipv6_address = os.environ['GLOBAL_IPV6']
config['proxy_host'] = config['ipv4_address'] = ipv4_address
config['ipv6_address'] = ipv6_address
config['proxy_port'] = findFreeTCPPort(ipv4_address)
config['master_url'] = 'http://{proxy_host}:{proxy_port}'.format(**config)
cls._process_manager = process_manager = ProcessManager()
# XXX this code is copied from testnode code
slapos_controler = SlapOSControler(
working_directory,
config
)
slapproxy_log = os.path.join(config['log_directory'], 'slapproxy.log')
logger = logging.getLogger(__name__)
logger.debug('Configured slapproxy log to %r', slapproxy_log)
software_url_list = cls.getSoftwareURLList()
slapos_controler.initializeSlapOSControler(
slapproxy_log=slapproxy_log,
process_manager=process_manager,
reset_software=False,
software_path_list=software_url_list)
process_manager.supervisord_pid_file = os.path.join(
slapos_controler.instance_root, 'var', 'run', 'supervisord.pid')
software_status_dict = slapos_controler.runSoftwareRelease(config, environment=os.environ)
# TODO: log more details in this case
assert software_status_dict['status_code'] == 0
instance_parameter_dict = cls.getInstanceParameterDict()
instance_status_dict = slapos_controler.runComputerPartition(
config,
cluster_configuration=instance_parameter_dict,
environment=os.environ)
# TODO: log more details in this case
assert instance_status_dict['status_code'] == 0
# FIXME: similar to test node, only one (root) partition is really supported for now.
computer_partition_list = []
for i in range(len(software_url_list)):
computer_partition_list.append(
slapos_controler.slap.registerOpenOrder().request(
software_url_list[i],
# This is how testnode's SlapOSControler name created partitions
partition_reference='testing partition {i}'.format(i=i, **config),
partition_parameter_kw=instance_parameter_dict))
# expose some class attributes so that tests can use them:
# the ComputerPartition instances, to getInstanceParameterDict
cls.computer_partition = computer_partition_list[0]
# the path of the instance on the filesystem, for low level inspection
cls.computer_partition_root_path = os.path.join(
config['working_directory'],
'inst',
cls.computer_partition.getId())
@classmethod
def stopSlapOSProcesses(cls):
if hasattr(cls, '_process_manager'):
cls._process_manager.killPreviousRun()
@classmethod
def tearDownClass(cls):
cls.stopSlapOSProcesses()
# utility methods
def getSupervisorRPCServer(self):
"""Returns a XML-RPC connection to the supervisor used by slapos node
Refer to http://supervisord.org/api.html for details of available methods.
"""
# xmlrpc over unix socket https://stackoverflow.com/a/11746051/7294664
return xmlrpclib.ServerProxy(
'http://slapos-supervisor',
transport=supervisor.xmlrpc.SupervisorTransport(
None,
None,
# XXX hardcoded socket path
serverurl="unix://{working_directory}/inst/supervisord.socket".format(**self.config)))
{%- if parameter_dict['domain'] -%}
{{ parameter_dict['domain'] }} {
tls {{ custom_cert_dict['cert-file'] }} {{ custom_cert_dict['key-file'] }} {
ca {{ca_custom_frontend_dict['rendered']}}
}
log {{caddy_configuration_dict['access_log']}}
errors {{caddy_configuration_dict['error_log']}}
root {{ directory_dict['public_html'] }}
{% if parameter_dict['enable-basic-auth'] == 'true' -%}
basicauth / {{ parameter_dict['username'] }} {{parameter_dict['password']}}
{%- endif %}
{% if parameter_dict['proxy'] == 'true' -%}
{% if parameter_dict['type'] == 'zope' -%}
proxy / {{parameter_dict['url']}}/VirtualHostBase/https/{{ parameter_dict['domain'] }}/VirtualHostRoot/ {
insecure_skip_verify
}
{% else %}
proxy / {{parameter_dict['url']}}
{%- endif %}
{%- endif %}
bind {{caddy_configuration_dict['ipv6']}}
}
{%- endif %}
[{{caddy_configuration_dict['ipv6']}}]:{{parameter_dict['port']}} {
tls {{ custom_cert_dict['cert-file'] }} {{ custom_cert_dict['key-file'] }} {
ca {{ certificate_authority_dict['ca-cert-file'] }}
}
log {{caddy_configuration_dict['access_log']}}
errors {{caddy_configuration_dict['error_log']}}
root {{ directory_dict['public_html'] }}
{% if parameter_dict['enable-basic-auth'] == 'true' -%}
basicauth / {{ parameter_dict['username'] }} {{parameter_dict['password']}}
{%- endif %}
{% if parameter_dict['proxy'] == 'true' -%}
{% if parameter_dict['type'] == 'zope' -%}
proxy / {{parameter_dict['url']}}/VirtualHostBase/https/[{{caddy_configuration_dict['ipv6']}}]:{{parameter_dict['port']}}/VirtualHostRoot/ {
insecure_skip_verify
}
{% else %}
proxy / {{parameter_dict['url']}}
{%- endif %}
{%- endif %}
bind {{caddy_configuration_dict['ipv6']}}
}
[{{caddy_configuration_dict['local_ip']}}]:{{parameter_dict['port']}} {
log {{caddy_configuration_dict['access_log']}}
errors {{caddy_configuration_dict['error_log']}}
root {{ directory_dict['public_html'] }}
{% if parameter_dict['enable-basic-auth'] == 'true' -%}
basicauth / {{ parameter_dict['username'] }} {{parameter_dict['password']}}
{%- endif %}
bind {{caddy_configuration_dict['local_ip']}}
}
\ No newline at end of file
[buildout]
extends =
../../component/golang/buildout.cfg
../../stack/slapos.cfg
../../component/dash/buildout.cfg
gowork.cfg
parts =
gowork
slapos-cookbook
instance-profile
template-caddy
caddy
[gowork]
install =
github.com/mholt/caddy
[instance-profile]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg.in
md5sum = 403f86b667f7a5d397993735bcd162ab
output =${buildout:directory}/instance.cfg
filename = instance.cfg
mode = 0644
[template-caddyfile]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/Caddyfile.in
md5sum = 05b8347df3c5803a18a515687a3504e3
filename = Caddyfile.in
location = ${buildout:parts-directory}/${:_buildout_section_name_}
mode = 0644
[template-caddy]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-caddy.cfg.in
md5sum = 4ed3a50a15a793fec330332be30a9f3a
output = ${buildout:directory}/instance-caddy.cfg.in
mode = 0644
[template-public-html]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/templates/index.html
md5sum = b5794ac8b10ed90173ad566e6e324b35
output = ${buildout:directory}/index.html
mode = 0644
[template-caddy-service]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/template-caddy-service.sh.in
md5sum = 1736f72c7c76afe133753389da7c0b1f
output = ${buildout:directory}/template-caddy-service.sh.in
mode = 0644
[caddy]
recipe = slapos.recipe.cmmi
path = ${go_github.com_mholt_caddy:location}
go = ${gowork:golang}/bin/go
configure-command = :
make-targets =
make-binary = cd ${:path}/caddy && ${:go} install -v
environment =
PATH=${pkgconfig:location}/bin:${gowork:golang}/bin:${buildout:bin-directory}:%(PATH)s
GOPATH=${gowork:directory}
output = ${gowork:bin}/caddy
\ No newline at end of file
[buildout]
parts =
caddy-service
caddy-configuration
certificate-authority
custom-cert
htpasswd
public-html
publish-connection-information
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[directory]
recipe = slapos.cookbook:mkdirectory
etc = $${buildout:directory}/etc
bin = $${buildout:directory}/bin
srv = $${buildout:directory}/srv
var = $${buildout:directory}/var
service = $${:etc}/service
public_html = $${buildout:directory}/public_html
run = $${:var}/run
log = $${:var}/log
ca-dir = $${:srv}/ssl
#################################
# caddy service
#################################
[caddy-service]
recipe = slapos.recipe.template:jinja2
template = ${template-caddy-service:output}
rendered = $${directory:service}/caddy
mode = 0700
context =
key caddy_exec caddy-exec-dict:caddy-exec-file
section caddy_configuration_dict caddy-configuration
section parameter_dict slap-parameter
[caddy-exec-dict]
caddy-exec-file = ${caddy:output}
[caddy-configuration]
recipe = slapos.recipe.template:jinja2
template = ${template-caddyfile:location}/${template-caddyfile:filename}
rendered = $${directory:etc}/Caddyfile
mode = 0600
access_log = $${directory:log}/caddy-access.log
error_log = $${directory:log}/caddy-error.log
ipv6 = $${slap-network-information:global-ipv6}
local_ip = $${slap-network-information:local-ipv4}
context =
section parameter_dict slap-parameter
section directory_dict directory
section caddy_configuration_dict caddy-configuration
section certificate_authority_dict certificate-authority
key htpasswd_dict htpasswd:passwd
section custom_cert_dict custom-cert
section ca_custom_frontend_dict ca-custom-frontend
[ca-directory]
recipe = slapos.cookbook:mkdirectory
requests = $${directory:ca-dir}/requests/
private = $${directory:ca-dir}/private/
certs = $${directory:ca-dir}/certs
newcerts = $${directory:ca-dir}/newcerts/
crl = $${directory:ca-dir}/crl/
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = ${openssl:location}/bin/openssl
ca-dir = $${directory:ca-dir}
requests-directory = $${ca-directory:requests}
wrapper = $${directory:service}/certificate_authority
ca-private = $${ca-directory:private}
ca-certs = $${ca-directory:certs}
ca-newcerts = $${ca-directory:newcerts}
ca-crl = $${ca-directory:crl}
ca-cert-file = $${:ca-dir}/cacert.pem
ca-key-file = $${:ca-private}/cakey.pem
[custom-cert]
<= certificate-authority
recipe = slapos.cookbook:certificate_authority.request
executable = $${directory:service}/caddy
wrapper = $${directory:service}/caddy
key-file = $${ca-directory:private}/custom.key
cert-file = $${ca-directory:certs}/custom.crt
key-content = $${slap-parameter:key-content}
cert-content = $${slap-parameter:cert-content}
[ca-custom-frontend]
recipe = slapos.recipe.template:jinja2
template = $${template-empty:target}
rendered = $${ca-directory:certs}/caddy_frontend.ca.crt
context =
key content slap-parameter:caddy-ca-certificate
[template-empty]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/$${:filename}
filename = empty.in
[htpasswd]
recipe = slapos.cookbook:generate.password
storage-path = $${directory:etc}/.pwd
bytes = 8
[public-html]
recipe = slapos.recipe.template
url = ${template-public-html:output}
output = $${directory:public_html}/index.html
mode = 0600
[publish-connection-information]
recipe = slapos.cookbook:publish
password = $${slap-parameter:password}
user = $${slap-parameter:username}
secure_access = https://[$${caddy-configuration:ipv6}]:$${slap-parameter:port}
[slap-parameter]
domain =
key-content =
cert-content =
caddy-ca-certificate =
port = 9443
enable-quic = true
enable-basic-auth =
username = admin
password = $${htpasswd:passwd}
proxy = false
type = zope
url =
\ No newline at end of file
#############################
#
# Deploy caddy instance
#
#############################
[buildout]
parts =
switch-softwaretype
# publish-connection-parameter
# Define egg directories to be the one from Software Release
# (/opt/slapgrid/...)
# Always the same.
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[switch-softwaretype]
recipe = slapos.cookbook:softwaretype
default = $${:caddy}
caddy = $${dynamic-template-caddy:rendered}
[dynamic-template-caddy]
recipe = slapos.recipe.template:jinja2
template = ${template-caddy:output}
rendered = $${buildout:parts-directory}/${:_buildout_section_name_}/${:filename}
filename = instance-caddy.cfg
[slap-connection]
computer-id = $${slap_connection:computer_id}
partition-id = $${slap_connection:partition_id}
server-url = $${slap_connection:server_url}
software-release-url = $${slap_connection:software_release_url}
key-file = $${slap_connection:key_file}
cert-file = $${slap_connection:cert_file}
[instance-parameter]
# Fetch arbitrary parameters defined by the user in SlapOS Master for his instance.
# We use the slapconfiguration recipe with a few parameters (partition id,
# computer id, certificate, etc).
# It will then authenticate to SlapOS Master and fetch the instance parameters.
# The parameters are accessible from {instance-parameter:configuration.name-of-parameter}
# Always the same. Just copy/paste.
# See docstring of slapos.cookbook:slapconfiguration for more information.
recipe = slapos.cookbook:slapconfiguration
computer = $${slap_connection:computer_id}
partition = $${slap_connection:partition_id}
url = $${slap_connection:server_url}
key = $${slap_connection:key_file}
cert = $${slap_connection:cert_file}
\ No newline at end of file
#!${dash-output:dash}
# BEWARE: This file is operated by slapgrid
# BEWARE: It will be overwritten automatically
{{ caddy_exec }} -conf {{caddy_configuration_dict['rendered']}} \
{%- if parameter_dict['enable-quic'] != 'false' %}
-quic
{%- endif -%}
\ No newline at end of file
<h1>Welcome</h1>
\ No newline at end of file
......@@ -82,7 +82,7 @@ md5sum = 3e650915959ff31c9c13c84069bbcd35
[template-zope]
filename = instance-zope.cfg.in
md5sum = 7fb40624bd0dcd96a1df03395da64ebd
md5sum = a4dda17c1671ead45ac92b7decc32228
[template-balancer]
filename = instance-balancer.cfg.in
......
......@@ -16,36 +16,45 @@ partition. No more (undefined result), no less (IndexError).
-#}
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set hosts_dict = {} -%}
{% set port_dict = {} -%}
{% for alias, url in (
('erp5-memcached-volatile', slapparameter_dict['memcached-url']),
('erp5-memcached-persistent', slapparameter_dict['kumofs-url']),
('erp5-cloudooo', slapparameter_dict['cloudooo-url']),
('erp5-smtp', slapparameter_dict['smtp-url']),
) -%}
{% set parsed_url = urlparse.urlparse(url) -%}
{% do port_dict.__setitem__(alias, parsed_url.port) -%}
{% do hosts_dict.__setitem__(alias, parsed_url.hostname) -%}
{%- endfor %}
{% for i, url in enumerate(slapparameter_dict['mysql-url-list']) -%}
{% do hosts_dict.__setitem__(
'erp5-catalog-' ~ i,
urlparse.urlparse(url).hostname,
) -%}
{%- endfor %}
{% do hosts_dict.update(slapparameter_dict['hosts-dict']) -%}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
mode = 644
{% if slapparameter_dict['mysql-test-url-list'] -%}
[{{ section('test-runner') }}]
recipe = slapos.cookbook:erp5.test
certificate-authority-path = ${test-certificate-authority:ca-dir}
mysql-url-list = {{ dumps(slapparameter_dict['mysql-test-url-list']) }}
kumofs-url = {{ dumps(slapparameter_dict['kumofs-url']) }}
memcached-url = {{ dumps(slapparameter_dict['memcached-url']) }}
cloudooo-url = {{ dumps(slapparameter_dict['cloudooo-url']) }}
cloudooo-retry-count = {{ slapparameter_dict['cloudooo-retry-count'] }}
test-instance-path = ${directory:unit-test-path}
prepend-path = ${buildout:bin-directory}
run-unit-test = ${buildout:bin-directory}/runUnitTest.real
run-test-suite = ${buildout:bin-directory}/runTestSuite.real
openssl-binary = ${test-certificate-authority:openssl-binary}
run-unit-test-binary = {{ parameter_dict['bin-directory'] }}/runUnitTest
run-test-suite-binary = {{ parameter_dict['bin-directory'] }}/runTestSuite
[{{ section('run-unit-test-userhosts-wrapper') }}]
[run-common]
<= userhosts-wrapper-base
wrapped-command-line = ${test-runner:run-unit-test}
wrapper-path = ${buildout:bin-directory}/runUnitTest
[{{ section('run-test-suite-userhosts-wrapper') }}]
<= userhosts-wrapper-base
wrapped-command-line = ${test-runner:run-test-suite}
wrapper-path = ${buildout:bin-directory}/runTestSuite
environment-extra =
environment +=
TMP=${directory:tmp}
TMPDIR=${directory:tmp}
HOME=${buildout:directory}
PATH=${binary-link:target-directory}:{{ parameter_dict['coreutils'] }}/bin
TZ={{ slapparameter_dict['timezone'] }}
MATPLOTLIBRC={{ parameter_dict['matplotlibrc'] }}
INSTANCE_HOME=${:instance-home}
{% if slapparameter_dict.get('wendelin-core-zblk-fmt') %}
WENDELIN_CORE_ZBLK_FMT={{ slapparameter_dict['wendelin-core-zblk-fmt'] }}
{% endif %}
${:environment-extra}
[test-certificate-authority]
recipe = slapos.cookbook:certificate_authority
......@@ -57,6 +66,64 @@ ca-private = ${directory:test-ca-private}
ca-certs = ${directory:test-ca-certs}
ca-newcerts = ${directory:test-ca-newcerts}
ca-crl = ${directory:test-ca-crl}
{% if slapparameter_dict['mysql-test-url-list'] -%}
[{{ section('run-unit-test-userhosts-wrapper') }}]
<= userhosts-wrapper-base
wrapped-command-line = ${runUnitTest:wrapper-path}
wrapper-path = ${buildout:bin-directory}/runUnitTest
[{{ section('run-test-suite-userhosts-wrapper') }}]
<= userhosts-wrapper-base
wrapped-command-line = ${runTestSuite:wrapper-path}
wrapper-path = ${buildout:bin-directory}/runTestSuite
{% set connection_string_list = [] -%}
{% for url in slapparameter_dict['mysql-test-url-list'] -%}
{% set parsed_url = urlparse.urlparse(url) -%}
{% do connection_string_list.append(
'%s@%s:%s %s %s' % (
parsed_url.path.lstrip('/'),
parsed_url.hostname,
parsed_url.port,
parsed_url.username,
parsed_url.password,
),
) -%}
{% endfor -%}
[run-test-common]
< = run-common
environment-extra =
REAL_INSTANCE_HOME=${:instance-home}
OPENSSL_BINARY=${test-certificate-authority:openssl-binary}
TEST_CA_PATH=${test-certificate-authority:ca-dir}
instance-home = ${directory:unit-test-path}
wrapper-path = ${directory:bin}/${:command-name}.real
command-line =
'{{ parameter_dict['bin-directory'] }}/${:command-name}'
${:command-line-extra}
--conversion_server_url={{ slapparameter_dict['cloudooo-url'] }}
--conversion_server_retry_count={{ slapparameter_dict.get('cloudooo-retry-count', 2) }}
{#- BBB: We still have test suites that only accept the following 2 options. #}
--conversion_server_hostname=erp5-cloudooo
--conversion_server_port={{ port_dict['erp5-cloudooo'] }}
--volatile_memcached_server_hostname=erp5-memcached-volatile
--volatile_memcached_server_port={{ port_dict['erp5-memcached-volatile'] }}
--persistent_memcached_server_hostname=erp5-memcached-persistent
--persistent_memcached_server_port={{ port_dict['erp5-memcached-persistent'] }}
[{{ section('runUnitTest') }}]
< = run-test-common
command-name = runUnitTest
command-line-extra =
--erp5_sql_connection_string '{{ connection_string_list[0] }}'
--extra_sql_connection_string_list '{{ ','.join(connection_string_list[1:]) }}'
[{{ section('runTestSuite') }}]
< = run-test-common
command-name = runTestSuite
command-line-extra =
--db_list '{{ ','.join(connection_string_list) }}'
{%- endif %}
[directory]
......@@ -127,27 +194,6 @@ ipv4 = {{ ipv4 }}
ipv6 = {{ ipv6 }}
{% endif -%}
{% set hosts_dict = {} -%}
{% for alias, url in (
('erp5-memcached-volatile', slapparameter_dict['memcached-url']),
('erp5-memcached-persistent', slapparameter_dict['kumofs-url']),
('erp5-cloudooo', slapparameter_dict['cloudooo-url']),
('erp5-smtp', slapparameter_dict['smtp-url']),
) -%}
{% do hosts_dict.__setitem__(
alias,
urlparse.urlparse(url).hostname,
) -%}
{%- endfor %}
{% for i, url in enumerate(slapparameter_dict['mysql-url-list']) -%}
{% do hosts_dict.__setitem__(
'erp5-catalog-' ~ i,
urlparse.urlparse(url).hostname,
) -%}
{%- endfor %}
{% do hosts_dict.update(slapparameter_dict['hosts-dict']) -%}
[host-common]
[hosts-parameter]
# Used for both hosts and hostaliases sections.
host-dict = {{ dumps(hosts_dict) }}
......@@ -208,18 +254,8 @@ pem = {{dumps(storage_dict.pop(k))}}
{# endhack -#}
[runzope-base]
<= userhosts-wrapper-base
environment +=
TMP=${directory:tmp}
TMPDIR=${directory:tmp}
HOME=${buildout:directory}
PATH=${directory:bin}:{{ parameter_dict['coreutils'] }}/bin
TZ={{ slapparameter_dict['timezone'] }}
INSTANCE_HOME=${directory:instance}
MATPLOTLIBRC={{ parameter_dict['matplotlibrc'] }}
{% if slapparameter_dict.get('wendelin-core-zblk-fmt') %}
WENDELIN_CORE_ZBLK_FMT={{ slapparameter_dict['wendelin-core-zblk-fmt'] }}
{% endif %}
<= run-common
instance-home = ${directory:instance}
wrapped-command-line = '{{ bin_directory }}/runzope' -C '${:configuration-file}'
private-dev-shm = {{ slapparameter_dict['private-dev-shm'] }}
......
......@@ -42,6 +42,7 @@ find-links +=
# Use only quite well working sites.
allow-hosts +=
pypi.org
*.googlecode.com
*.nexedi.org
*.python.org
......@@ -59,7 +60,7 @@ allow-hosts +=
www.owlfish.com
# Use an https index
index = https://pypi.python.org/simple/
index = https://pypi.org/simple/
# XXX: Workaround of SlapOS limitation
# Unzippig of eggs is required, as SlapOS do not yet provide nicely working
......
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