Commit 7a9ae1f7 authored by Jérome Perrin's avatar Jérome Perrin

Update Release Candidate

parents 4bfc0533 8a1f4101
...@@ -27,5 +27,5 @@ environment = ...@@ -27,5 +27,5 @@ environment =
LZMA_LIBRARY_PATH=${xz-utils:location}/lib LZMA_LIBRARY_PATH=${xz-utils:location}/lib
patch-options = -p1 patch-options = -p1
patches = patches =
${:_profile_base_location_}/fix-ftbfs-python-3.3.patch#c85fb479d51354deafd1cc7af78f25d2 https://sources.debian.org/data/main/b/boost1.67/1.67.0-17/debian/patches/fix-ftbfs-python-3.3.patch#c85fb479d51354deafd1cc7af78f25d2
patch-binary = ${patch:location}/bin/patch patch-binary = ${patch:location}/bin/patch
Description: python3.3 has an extra multiarch include location
Author: Dmitrijs Ledkovs <dmitrij.ledkov@ubuntu.com>
Last-Update: 2012-10-26
Forwarded: no
--- boost1.65.1-1.65.1+dfsg.orig/tools/build/src/tools/python.jam
+++ boost1.65.1-1.65.1+dfsg/tools/build/src/tools/python.jam
@@ -544,7 +544,9 @@
}
else
{
- includes ?= $(prefix)/include/python$(version) ;
+ python_includes = [ shell-cmd "printf `python$(version) -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc());'`" ] ;
+ python_platincludes = [ shell-cmd "printf `python$(version) -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc(plat_specific=1));'`" ] ;
+ includes ?= $(python_includes) $(python_platincludes) ;
local lib = $(exec-prefix)/lib ;
libraries ?= $(lib)/python$(version)/config $(lib) ;
...@@ -14,16 +14,13 @@ recipe = slapos.recipe.build:gitclone ...@@ -14,16 +14,13 @@ recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/nexedi/cloudooo.git repository = https://lab.nexedi.com/nexedi/cloudooo.git
branch = master branch = master
git-executable = ${git:location}/bin/git git-executable = ${git:location}/bin/git
revision = 67e233f25845335aaf191e80abae53733d1f2579 revision = bf99e5dea3ecf45c59083085540316c48cfa5488
[cloudooo] [cloudooo]
recipe = zc.recipe.egg recipe = zc.recipe.egg
eggs = eggs =
${lxml-python:egg} ${lxml-python:egg}
PasteScript PasteScript
python-magic
psutil
WSGIUtils
cloudooo cloudooo
entry-points = entry-points =
main=cloudooo.paster_application:application main=cloudooo.paster_application:application
......
...@@ -40,6 +40,9 @@ install = ...@@ -40,6 +40,9 @@ install =
cd {} cd {}
export LD_LIBRARY_PATH=$PWD:{} export LD_LIBRARY_PATH=$PWD:{}
export PATH={}:$PATH export PATH={}:$PATH
# BBB use a default fonts.conf for compatibility, but it's software instance
# responsability to build a fonts.conf with the fonts they want.
[ -z $FONTCONFIG_FILE ] && export FONTCONFIG_FILE=${firefox-default-fonts-conf:rendered}
exec ./firefox "$@" exec ./firefox "$@"
""".format( """.format(
firefox, firefox,
...@@ -68,6 +71,21 @@ part = ${firefox-52:location} ...@@ -68,6 +71,21 @@ part = ${firefox-52:location}
wrapper-name = firefox-51 wrapper-name = firefox-51
part = ${firefox-51:location} part = ${firefox-51:location}
[firefox-default-fonts-conf]
recipe = slapos.recipe.template:jinja2
template = ${template-fonts-conf:output}
rendered = ${buildout:parts-directory}/${:_buildout_section_name_}/fonts.conf
context =
key cachedir :cache-dir
key fonts :fonts
key includes :includes
fonts =
${ipaex-fonts:location}
${liberation-fonts:location}
includes =
${fontconfig:location}/etc/fonts/conf.d
cache-dir =
~/.fontconfig-firefox/
[firefox] [firefox]
# The default installed firefox version when installing firefox-wrapper. # The default installed firefox version when installing firefox-wrapper.
......
...@@ -4,6 +4,7 @@ extends = ...@@ -4,6 +4,7 @@ extends =
../glib/buildout.cfg ../glib/buildout.cfg
../libsigc/buildout.cfg ../libsigc/buildout.cfg
../perl/buildout.cfg ../perl/buildout.cfg
../patch/buildout.cfg
../pkgconfig/buildout.cfg ../pkgconfig/buildout.cfg
../xz-utils/buildout.cfg ../xz-utils/buildout.cfg
parts = parts =
...@@ -17,8 +18,10 @@ md5sum = e7416beff6cba1f38c2bccd0dc8c3278 ...@@ -17,8 +18,10 @@ md5sum = e7416beff6cba1f38c2bccd0dc8c3278
pkg_config_depends = ${glib:location}/lib/pkgconfig:${libsigc:location}/lib/pkgconfig:${pcre:location}/lib/pkgconfig pkg_config_depends = ${glib:location}/lib/pkgconfig:${libsigc:location}/lib/pkgconfig:${pcre:location}/lib/pkgconfig
configure-options = configure-options =
--disable-documentation --disable-documentation
patches = ${:_profile_base_location_}/glibmm-fix-threads-gobject.patch#75ab0e9e5d1df55e8f6177b9934359ae
patch-options = -p1
environment = environment =
PATH=${perl:location}/bin:${pkgconfig:location}/bin:${xz-utils:location}/bin:${glib:location}/bin:%(PATH)s PATH=${patch:location}/bin:${perl:location}/bin:${pkgconfig:location}/bin:${xz-utils:location}/bin:${glib:location}/bin:%(PATH)s
PKG_CONFIG_PATH=${:pkg_config_depends} PKG_CONFIG_PATH=${:pkg_config_depends}
CPPFLAGS=-I${gettext:location}/include CPPFLAGS=-I${gettext:location}/include
LDFLAGS=-L${gettext:location}/lib -Wl,-rpath=${gettext:location}/lib LDFLAGS=-L${gettext:location}/lib -Wl,-rpath=${gettext:location}/lib
From 37d57ae9572b7d74aa385a30313eceae7f2d3fce Mon Sep 17 00:00:00 2001
From: Kjell Ahlstedt <kjellahlstedt@gmail.com>
Date: Wed, 20 Dec 2017 20:00:32 +0100
Subject: [PATCH] Glib::Threads::Private: Fix gobj()
Bug 791711
---
glib/src/threads.hg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/glib/src/threads.hg b/glib/src/threads.hg
index 86d7a17b..c82a6130 100644
--- a/glib/src/threads.hg
+++ b/glib/src/threads.hg
@@ -628,7 +628,7 @@ public:
*/
inline void replace(T* data);
- GPrivate* gobj() { return gobject_; }
+ GPrivate* gobj() { return &gobject_; }
private:
GPrivate gobject_;
--- a/glib/glibmm/threads.h 2017-09-04 15:27:31.000000000 +0200
+++ b/glib/glibmm/threads.h 2018-05-05 10:53:44.339288554 +0200
@@ -657,7 +657,7 @@
*/
inline void replace(T* data);
- GPrivate* gobj() { return gobject_; }
+ GPrivate* gobj() { return &gobject_; }
private:
GPrivate gobject_;
...@@ -8,6 +8,10 @@ extends = ...@@ -8,6 +8,10 @@ extends =
parts = kumo parts = kumo
[gcc]
# KumoFS fails to build with GCC 6.
min_version = 7
[kumo] [kumo]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
......
...@@ -30,13 +30,14 @@ parts = ...@@ -30,13 +30,14 @@ parts =
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = https://downloads.mariadb.org/f/mariadb-${:version}/source/mariadb-${:version}.tar.gz/from/http%3A//fr.mirror.babylon.network/mariadb/?serve url = https://downloads.mariadb.org/f/mariadb-${:version}/source/mariadb-${:version}.tar.gz/from/http%3A//fr.mirror.babylon.network/mariadb/?serve
version = 10.4.12 version = 10.4.13
md5sum = 97d7c0f508c04a31c138fdb24e95dbc4 md5sum = 89e832d6d89dc9bd4c98657a954e0f2c
location = @@LOCATION@@ location = @@LOCATION@@
pre-configure = pre-configure =
set '\bSET(PLUGIN_AUTH_PAM YES)' cmake/build_configurations/mysql_release.cmake set '\bSET(PLUGIN_AUTH_PAM YES)' cmake/build_configurations/mysql_release.cmake
grep -q "$@" grep -q "$@"
sed -i "/$1/d" "$2" sed -i "/$1/d" "$2"
mv cmake/Findzstd.cmake cmake/FindZSTD.cmake
configure-command = ${cmake:location}/bin/cmake configure-command = ${cmake:location}/bin/cmake
configure-options = configure-options =
-DCMAKE_INSTALL_PREFIX=${:location} -DCMAKE_INSTALL_PREFIX=${:location}
...@@ -80,6 +81,10 @@ patch-options = -p1 ...@@ -80,6 +81,10 @@ patch-options = -p1
patches = patches =
https://sources.debian.org/data/main/m/mariadb-10.3/1:10.3.22-0+deb10u1/debian/patches/0024-Revert-to-using-system-pcre-library.patch#1c6a0f2634f5a56122299674b77b1131 https://sources.debian.org/data/main/m/mariadb-10.3/1:10.3.22-0+deb10u1/debian/patches/0024-Revert-to-using-system-pcre-library.patch#1c6a0f2634f5a56122299674b77b1131
post-install = post-install =
ldd=`ldd ${:location}/lib/plugin/ha_rocksdb.so`
for x in ${lz4:location} ${snappy:location} ${zstd:location}
do echo "$ldd" |grep -qF " $x/lib/"
done
set -- wsrep-lib/wsrep-API/*/wsrep_api.h set -- wsrep-lib/wsrep-API/*/wsrep_api.h
install -DpT $1 ${:location}/$1 install -DpT $1 ${:location}/$1
cp -a wsrep-lib/include ${:location}/wsrep-lib cp -a wsrep-lib/include ${:location}/wsrep-lib
......
...@@ -9,6 +9,9 @@ extends = ...@@ -9,6 +9,9 @@ extends =
parts = parts =
re6stnet re6stnet
[gcc]
min_version = 0
[re6stnet] [re6stnet]
recipe = zc.recipe.egg recipe = zc.recipe.egg
eggs = eggs =
......
[buildout]
extends =
../git/buildout.cfg
[userhosts] [userhosts]
recipe = plone.recipe.command recipe = slapos.recipe.cmmi
stop-on-error = true shared = true
update-command = ${:command} url = https://lab.nexedi.com/nexedi/userhosts/repository/${:revision}/archive.tar.gz
command = cd ${userhosts-get:location} && make
# For convenience (one section to build & know result path)
location = ${userhosts-get:location}/userhosts
[userhosts-get]
recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/nexedi/userhosts.git
revision = 1d3b463e7856db6e674a06258c0840206e6a7b72 revision = 1d3b463e7856db6e674a06258c0840206e6a7b72
git-executable = ${git:location}/bin/git configure-command = true
location = ${buildout:parts-directory}/userhosts make-options = PREFIX=@@LOCATION@@
make-targets = check install
...@@ -8,6 +8,9 @@ parts = ...@@ -8,6 +8,9 @@ parts =
template template
download-cache = ${:directory}/download-cache download-cache = ${:directory}/download-cache
[gcc]
min_version = 0
[template] [template]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
# XXX: "template.cfg" is hardcoded in instanciation recipe # XXX: "template.cfg" is hardcoded in instanciation recipe
......
...@@ -6,6 +6,11 @@ from erp5.util import taskdistribution ...@@ -6,6 +6,11 @@ from erp5.util import taskdistribution
from erp5.util.testsuite import SubprocessError, TestSuite from erp5.util.testsuite import SubprocessError, TestSuite
from zc.buildout.buildout import Buildout from zc.buildout.buildout import Buildout
if str is bytes:
str2bytes = lambda s: s
else:
str2bytes = lambda s: s.encode()
slapos_buildout = {{repr(slapos_buildout)}} slapos_buildout = {{repr(slapos_buildout)}}
test_dict = { test_dict = {
'zc.buildout': slapos_buildout, 'zc.buildout': slapos_buildout,
...@@ -90,7 +95,7 @@ def main(): ...@@ -90,7 +95,7 @@ def main():
fd = os.open('buildout.cfg', os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0666) fd = os.open('buildout.cfg', os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0666)
try: try:
os.write(fd, """\ os.write(fd, str2bytes("""\
[buildout] [buildout]
extends = %s extends = %s
develop =%s develop =%s
...@@ -112,7 +117,7 @@ scripts = ...@@ -112,7 +117,7 @@ scripts =
zope-testrunner zope-testrunner
""" % (os.path.join(slapos_buildout, 'buildout.cfg'), """ % (os.path.join(slapos_buildout, 'buildout.cfg'),
''.join('\n ' + x for x in test_dict.itervalues()), ''.join('\n ' + x for x in test_dict.itervalues()),
'\n'.join(x + ' =' for x in test_dict))) '\n'.join(x + ' =' for x in test_dict))))
finally: finally:
os.close(fd) os.close(fd)
Buildout('buildout.cfg', {}).install(['bootstrap']) Buildout('buildout.cfg', {}).install(['bootstrap'])
......
[buildout]
extends =
software.cfg
[python]
part = python3
...@@ -30,7 +30,7 @@ md5sum = 087bd9404cd120bd7602a9fbfcddc064 ...@@ -30,7 +30,7 @@ md5sum = 087bd9404cd120bd7602a9fbfcddc064
[template-slave-list] [template-slave-list]
filename = templates/apache-custom-slave-list.cfg.in filename = templates/apache-custom-slave-list.cfg.in
md5sum = 29a61267959cc9ba7cdcd96fef41641a md5sum = d96fea7dd4d7f0a157c86d25a263d8e1
[template-slave-configuration] [template-slave-configuration]
filename = templates/custom-virtualhost.conf.in filename = templates/custom-virtualhost.conf.in
...@@ -42,7 +42,7 @@ md5sum = 7e3ee70c447f8203273d78f66ab519c3 ...@@ -42,7 +42,7 @@ md5sum = 7e3ee70c447f8203273d78f66ab519c3
[template-caddy-frontend-configuration] [template-caddy-frontend-configuration]
filename = templates/Caddyfile.in filename = templates/Caddyfile.in
md5sum = 908b859ff76469381024947f5c98c891 md5sum = f0faf6d2e6c187df7e25bf717676f9df
[caddy-backend-url-validator] [caddy-backend-url-validator]
filename = templates/caddy-backend-url-validator.in filename = templates/caddy-backend-url-validator.in
......
...@@ -4,7 +4,8 @@ import {{frontend_configuration.get('log-access-configuration')}} ...@@ -4,7 +4,8 @@ import {{frontend_configuration.get('log-access-configuration')}}
import {{ slave_configuration_directory }}/*.conf import {{ slave_configuration_directory }}/*.conf
import {{ slave_with_cache_configuration_directory }}/*.conf import {{ slave_with_cache_configuration_directory }}/*.conf
:{{ https_port }} { {% for port in [https_port] %}
:{{ port }} {
tls {{ master_certificate }} {{ master_certificate }} tls {{ master_certificate }} {{ master_certificate }}
bind {{ local_ipv4 }} bind {{ local_ipv4 }}
status 404 / status 404 /
...@@ -16,8 +17,10 @@ import {{ slave_with_cache_configuration_directory }}/*.conf ...@@ -16,8 +17,10 @@ import {{ slave_with_cache_configuration_directory }}/*.conf
* {{ not_found_file }} * {{ not_found_file }}
} }
} }
{%- endfor %}
:{{ http_port }} { {% for port in [http_port, cached_port, ssl_cached_port] %}
:{{ port }} {
bind {{ local_ipv4 }} bind {{ local_ipv4 }}
status 404 / status 404 /
log / {{ access_log }} "{remote} - {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}" { log / {{ access_log }} "{remote} - {>REMOTE_USER} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\" {latency_ms}" {
...@@ -28,6 +31,7 @@ import {{ slave_with_cache_configuration_directory }}/*.conf ...@@ -28,6 +31,7 @@ import {{ slave_with_cache_configuration_directory }}/*.conf
* {{ not_found_file }} * {{ not_found_file }}
} }
} }
{%- endfor %}
# Access to server-status Caddy-style # Access to server-status Caddy-style
https://[{{ global_ipv6 }}]:{{ https_port }}/server-status, https://{{ local_ipv4 }}:{{ https_port }}/server-status { https://[{{ global_ipv6 }}]:{{ https_port }}/server-status, https://{{ local_ipv4 }}:{{ https_port }}/server-status {
......
...@@ -42,6 +42,10 @@ create = true ...@@ -42,6 +42,10 @@ create = true
{% set slave_kedifa_information = {} %} {% set slave_kedifa_information = {} %}
{% endif %} {% endif %}
# empty sections if no slaves are available
[slave-log-directory-dict]
[slave-password]
# empty section if no cached slaves are available # empty section if no cached slaves are available
[slave-log-cache-direct-directory-dict] [slave-log-cache-direct-directory-dict]
......
...@@ -500,193 +500,19 @@ class TestHandler(BaseHTTPRequestHandler): ...@@ -500,193 +500,19 @@ class TestHandler(BaseHTTPRequestHandler):
self.wfile.write(response) self.wfile.write(response)
class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase): class HttpFrontendTestCase(SlapOSInstanceTestCase):
# show full diffs, as it is required for proper analysis of problems # show full diffs, as it is required for proper analysis of problems
maxDiff = None maxDiff = None
# minimise partition path # minimise partition path
__partition_reference__ = 'T-' __partition_reference__ = 'T-'
@classmethod
def callSupervisorMethod(cls, method, *args, **kwargs):
with cls.slap.instance_supervisor_rpc as instance_supervisor:
return getattr(instance_supervisor, method)(*args, **kwargs)
@classmethod
def requestSlaves(cls):
software_url = cls.getSoftwareURL()
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
cls.logger.debug(
'requesting slave "%s" software:%s parameters:%s',
slave_reference, software_url, partition_parameter_kw)
cls.slap.request(
software_release=software_url,
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
)
@classmethod @classmethod
def getInstanceSoftwareType(cls): def getInstanceSoftwareType(cls):
# Because of unknown problem yet, the root instance software type changes # Because of unknown problem yet, the root instance software type changes
# from RootSoftwareInstance to '', so always request it with given type # from RootSoftwareInstance to '', so always request it with given type
return "RootSoftwareInstance" return "RootSoftwareInstance"
@classmethod
def requestDefaultInstance(cls, state='started'):
default_instance = super(
SlaveHttpFrontendTestCase, cls).requestDefaultInstance(state=state)
if state != 'destroyed':
cls.requestSlaves()
return default_instance
@classmethod
def setUpClass(cls):
try:
cls.createWildcardExampleComCertificate()
cls.startServerProcess()
except BaseException:
cls.logger.exception("Error during setUpClass")
cls._cleanup("{}.{}.setUpClass".format(cls.__module__, cls.__name__))
cls.setUp = lambda self: self.fail('Setup Class failed.')
raise
super(SlaveHttpFrontendTestCase, cls).setUpClass()
try:
# expose instance directory
cls.instance_path = cls.slap.instance_directory
# expose software directory, extract from found computer partition
cls.software_path = os.path.realpath(os.path.join(
cls.computer_partition_root_path, 'software_release'))
# do working directory
cls.working_directory = os.path.join(os.path.realpath(
os.environ.get(
'SLAPOS_TEST_WORKING_DIR',
os.path.join(os.getcwd(), '.slapos'))),
'caddy-frontend-test')
if not os.path.isdir(cls.working_directory):
os.mkdir(cls.working_directory)
cls.setUpMaster()
cls.setUpSlaves()
cls.waitForCaddy()
except BaseException:
cls.logger.exception("Error during setUpClass")
# "{}.{}.setUpClass".format(cls.__module__, cls.__name__) is already used
# by SlapOSInstanceTestCase.setUpClass so we use another name for
# snapshot, to make sure we don't store another snapshot in same
# directory.
cls._cleanup("{}.SlaveHttpFrontendTestCase.{}.setUpClass".format(
cls.__module__, cls.__name__))
cls.setUp = lambda self: self.fail('Setup Class failed.')
raise
def assertLogAccessUrlWithPop(self, parameter_dict):
log_access_url = parameter_dict.pop('log-access-url')
self.assertTrue(len(log_access_url) >= 1)
# check only the first one, as second frontend will be stopped
log_access = log_access_url[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(
httplib.OK,
result.status_code,
'While accessing %r of %r the status code was %r' % (
url, frontend, result.status_code))
def assertKedifaKeysWithPop(self, parameter_dict, prefix=''):
generate_auth_url = parameter_dict.pop('%skey-generate-auth-url' % (
prefix,))
upload_url = parameter_dict.pop('%skey-upload-url' % (prefix,))
kedifa_ipv6_base = 'https://[%s]:%s' % (self._ipv6_address, KEDIFA_PORT)
base = '^' + kedifa_ipv6_base.replace(
'[', r'\[').replace(']', r'\]') + '/.{32}'
self.assertRegexpMatches(
generate_auth_url,
base + r'\/generateauth$'
)
self.assertRegexpMatches(
upload_url,
base + r'\?auth=$'
)
kedifa_caucase_url = parameter_dict.pop('kedifa-caucase-url')
self.assertEqual(
kedifa_caucase_url,
'http://[%s]:%s' % (self._ipv6_address, CAUCASE_PORT),
)
return generate_auth_url, upload_url
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(value, j[key])
def parseParameterDict(self, parameter_dict):
parsed_parameter_dict = {}
for key, value in parameter_dict.items():
if key in [
'rejected-slave-dict',
'warning-slave-dict',
'warning-list',
'request-error-list',
'log-access-url']:
value = json.loads(value)
parsed_parameter_dict[key] = value
return parsed_parameter_dict
def parseConnectionParameterDict(self):
return self.parseParameterDict(
self.requestDefaultInstance().getConnectionParameterDict()
)
@classmethod
def runComputerPartitionUntil(cls, until):
max_try = 10
try_num = 1
while True:
if until():
break
if try_num > max_try:
raise ValueError('Failed to run computer partition with %r' % (until,))
try:
cls.slap.waitForInstance()
except Exception:
cls.logger.exception("Error during until run")
try_num += 1
@classmethod
def untilNotReadyYetNotInMasterKeyGenerateAuthUrl(cls):
parameter_dict = cls.requestDefaultInstance().getConnectionParameterDict()
key = 'master-key-generate-auth-url'
if key not in parameter_dict:
return False
if 'NotReadyYet' in parameter_dict[key]:
return False
return True
@classmethod
def getSlaveParameterDictDict(cls):
return {
'waitforcaddyslave': {
'url': cls.backend_url,
'enable_cache': True,
}
}
@classmethod @classmethod
def startServerProcess(cls): def startServerProcess(cls):
server = HTTPServer( server = HTTPServer(
...@@ -789,50 +615,6 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase): ...@@ -789,50 +615,6 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase):
# block until caddy is refreshed # block until caddy is refreshed
time.sleep(2) time.sleep(2)
@classmethod
def untilSlavePartitionReady(cls):
# all on-watch services shall not be exited
for process in cls.callSupervisorMethod('getAllProcessInfo'):
if process['name'].endswith('-on-watch') and \
process['statename'] == 'EXITED':
if process['name'].startswith('monitor-http'):
continue
return False
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
parameter_dict = cls.slap.request(
software_release=cls.getSoftwareURL(),
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
).getConnectionParameterDict()
log_access_ready = 'log-access-url' in parameter_dict
key = 'key-generate-auth-url'
key_generate_auth_ready = key in parameter_dict \
and 'NotReadyYet' not in parameter_dict[key]
if log_access_ready and key_generate_auth_ready:
return True
return False
@classmethod
def setUpSlaves(cls):
cls.slave_connection_parameter_dict_dict = {}
# run partition for slaves to be setup
cls.runComputerPartitionUntil(
cls.untilSlavePartitionReady)
request = cls.slap.request
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
slave_instance = request(
software_release=cls.getSoftwareURL(),
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
)
cls.slave_connection_parameter_dict_dict[slave_reference] = \
slave_instance.getConnectionParameterDict()
@classmethod @classmethod
def createWildcardExampleComCertificate(cls): def createWildcardExampleComCertificate(cls):
_, cls.key_pem, _, cls.certificate_pem = createSelfSignedCertificate( _, cls.key_pem, _, cls.certificate_pem = createSelfSignedCertificate(
...@@ -842,39 +624,88 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase): ...@@ -842,39 +624,88 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase):
'*.alias1.example.com', '*.alias1.example.com',
]) ])
check_slave_id = 'waitforcaddyslave'
@classmethod @classmethod
def waitForCaddy(cls): def runComputerPartitionUntil(cls, until):
# awaits until caddy is ready to serve slaves max_try = 10
parameter_dict = cls.slave_connection_parameter_dict_dict[ try_num = 1
cls.check_slave_id
]
wait_time = 600
begin = time.time()
try_num = 0
cls.logger.debug('waitForCaddy for %is' % (wait_time,))
while True: while True:
if until():
break
if try_num > max_try:
raise ValueError('Failed to run computer partition with %r' % (until,))
try: try:
try_num += 1 cls.slap.waitForInstance()
fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'],
'/',
)
except Exception: except Exception:
if time.time() - begin > wait_time: cls.logger.exception("Error during until run")
cls.logger.exception( try_num += 1
"Error during waitForCaddy after %.2fs" % ((time.time() - begin),))
raise
else:
time.sleep(0.5)
else:
cls.logger.info("waitForCaddy took %.2fs" % ((time.time() - begin),))
break
@classmethod @classmethod
def _cleanup(cls, snapshot_name): def untilNotReadyYetNotInMasterKeyGenerateAuthUrl(cls):
cls.stopServerProcess() parameter_dict = cls.requestDefaultInstance().getConnectionParameterDict()
super(SlaveHttpFrontendTestCase, cls)._cleanup(snapshot_name) key = 'master-key-generate-auth-url'
if key not in parameter_dict:
return False
if 'NotReadyYet' in parameter_dict[key]:
return False
return True
@classmethod
def callSupervisorMethod(cls, method, *args, **kwargs):
with cls.slap.instance_supervisor_rpc as instance_supervisor:
return getattr(instance_supervisor, method)(*args, **kwargs)
def assertLogAccessUrlWithPop(self, parameter_dict):
log_access_url = parameter_dict.pop('log-access-url')
self.assertTrue(len(log_access_url) >= 1)
# check only the first one, as second frontend will be stopped
log_access = log_access_url[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(
httplib.OK,
result.status_code,
'While accessing %r of %r the status code was %r' % (
url, frontend, result.status_code))
def assertKedifaKeysWithPop(self, parameter_dict, prefix=''):
generate_auth_url = parameter_dict.pop('%skey-generate-auth-url' % (
prefix,))
upload_url = parameter_dict.pop('%skey-upload-url' % (prefix,))
kedifa_ipv6_base = 'https://[%s]:%s' % (self._ipv6_address, KEDIFA_PORT)
base = '^' + kedifa_ipv6_base.replace(
'[', r'\[').replace(']', r'\]') + '/.{32}'
self.assertRegexpMatches(
generate_auth_url,
base + r'\/generateauth$'
)
self.assertRegexpMatches(
upload_url,
base + r'\?auth=$'
)
kedifa_caucase_url = parameter_dict.pop('kedifa-caucase-url')
self.assertEqual(
kedifa_caucase_url,
'http://[%s]:%s' % (self._ipv6_address, CAUCASE_PORT),
)
return generate_auth_url, upload_url
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(value, j[key])
def patchRequests(self): def patchRequests(self):
HTTPResponse = requests.packages.urllib3.response.HTTPResponse HTTPResponse = requests.packages.urllib3.response.HTTPResponse
...@@ -917,7 +748,216 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase): ...@@ -917,7 +748,216 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase):
def tearDown(self): def tearDown(self):
self.unpatchRequests() self.unpatchRequests()
super(SlaveHttpFrontendTestCase, self).tearDown() super(HttpFrontendTestCase, self).tearDown()
def parseParameterDict(self, parameter_dict):
parsed_parameter_dict = {}
for key, value in parameter_dict.items():
if key in [
'rejected-slave-dict',
'warning-slave-dict',
'warning-list',
'request-error-list',
'log-access-url']:
value = json.loads(value)
parsed_parameter_dict[key] = value
return parsed_parameter_dict
def getMasterPartitionPath(self):
return '/' + os.path.join(
*glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'Caddyfile-rejected-slave'
)
)[0].split('/')[:-2])
def parseConnectionParameterDict(self):
return self.parseParameterDict(
self.requestDefaultInstance().getConnectionParameterDict()
)
@classmethod
def waitForMethod(cls, name, method):
wait_time = 600
begin = time.time()
try_num = 0
cls.logger.debug('%s for %is' % (name, wait_time,))
while True:
try:
try_num += 1
method()
except Exception:
if time.time() - begin > wait_time:
cls.logger.exception(
"Error during %s after %.2fs" % (name, (time.time() - begin),))
raise
else:
time.sleep(0.5)
else:
cls.logger.info("%s took %.2fs" % (name, (time.time() - begin),))
break
@classmethod
def waitForCaddy(cls):
def method():
fakeHTTPSResult(
cls._ipv4_address, cls._ipv4_address,
'/',
)
cls.waitForMethod('waitForCaddy', method)
@classmethod
def _cleanup(cls, snapshot_name):
cls.stopServerProcess()
super(HttpFrontendTestCase, cls)._cleanup(snapshot_name)
@classmethod
def setUpClass(cls):
try:
cls.createWildcardExampleComCertificate()
cls.startServerProcess()
except BaseException:
cls.logger.exception("Error during setUpClass")
cls._cleanup("{}.{}.setUpClass".format(cls.__module__, cls.__name__))
cls.setUp = lambda self: self.fail('Setup Class failed.')
raise
super(HttpFrontendTestCase, cls).setUpClass()
try:
# expose instance directory
cls.instance_path = cls.slap.instance_directory
# expose software directory, extract from found computer partition
cls.software_path = os.path.realpath(os.path.join(
cls.computer_partition_root_path, 'software_release'))
# do working directory
cls.working_directory = os.path.join(os.path.realpath(
os.environ.get(
'SLAPOS_TEST_WORKING_DIR',
os.path.join(os.getcwd(), '.slapos'))),
'caddy-frontend-test')
if not os.path.isdir(cls.working_directory):
os.mkdir(cls.working_directory)
cls.setUpMaster()
cls.waitForCaddy()
except BaseException:
cls.logger.exception("Error during setUpClass")
# "{}.{}.setUpClass".format(cls.__module__, cls.__name__) is already used
# by SlapOSInstanceTestCase.setUpClass so we use another name for
# snapshot, to make sure we don't store another snapshot in same
# directory.
cls._cleanup("{}.SlaveHttpFrontendTestCase.{}.setUpClass".format(
cls.__module__, cls.__name__))
cls.setUp = lambda self: self.fail('Setup Class failed.')
raise
class SlaveHttpFrontendTestCase(HttpFrontendTestCase):
@classmethod
def requestDefaultInstance(cls, state='started'):
default_instance = super(
SlaveHttpFrontendTestCase, cls).requestDefaultInstance(state=state)
if state != 'destroyed':
cls.requestSlaves()
return default_instance
@classmethod
def requestSlaves(cls):
software_url = cls.getSoftwareURL()
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
cls.logger.debug(
'requesting slave "%s" software:%s parameters:%s',
slave_reference, software_url, partition_parameter_kw)
cls.slap.request(
software_release=software_url,
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
)
@classmethod
def setUpClass(cls):
super(SlaveHttpFrontendTestCase, cls).setUpClass()
try:
cls.setUpSlaves()
cls.waitForSlave()
except BaseException:
cls.logger.exception("Error during setUpClass")
# "{}.{}.setUpClass".format(cls.__module__, cls.__name__) is already used
# by SlapOSInstanceTestCase.setUpClass so we use another name for
# snapshot, to make sure we don't store another snapshot in same
# directory.
cls._cleanup("{}.SlaveHttpFrontendTestCase.{}.setUpClass".format(
cls.__module__, cls.__name__))
cls.setUp = lambda self: self.fail('Setup Class failed.')
raise
@classmethod
def waitForSlave(cls):
def method():
for parameter_dict in cls.getSlaveConnectionParameterDictList():
if 'domain' in parameter_dict and 'public-ipv4' in parameter_dict:
try:
fakeHTTPSResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], '/')
except requests.exceptions.InvalidURL:
# ignore slaves to which connection is impossible by default
continue
cls.waitForMethod('waitForSlave', method)
@classmethod
def getSlaveConnectionParameterDictList(cls):
parameter_dict_list = []
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
parameter_dict_list.append(cls.slap.request(
software_release=cls.getSoftwareURL(),
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
).getConnectionParameterDict())
return parameter_dict_list
@classmethod
def untilSlavePartitionReady(cls):
# all on-watch services shall not be exited
for process in cls.callSupervisorMethod('getAllProcessInfo'):
if process['name'].endswith('-on-watch') and \
process['statename'] == 'EXITED':
if process['name'].startswith('monitor-http'):
continue
return False
for parameter_dict in cls.getSlaveConnectionParameterDictList():
log_access_ready = 'log-access-url' in parameter_dict
key = 'key-generate-auth-url'
key_generate_auth_ready = key in parameter_dict \
and 'NotReadyYet' not in parameter_dict[key]
if not(log_access_ready and key_generate_auth_ready):
return False
return True
@classmethod
def setUpSlaves(cls):
cls.slave_connection_parameter_dict_dict = {}
# run partition for slaves to be setup
cls.runComputerPartitionUntil(
cls.untilSlavePartitionReady)
request = cls.slap.request
for slave_reference, partition_parameter_kw in cls\
.getSlaveParameterDictDict().items():
slave_instance = request(
software_release=cls.getSoftwareURL(),
partition_reference=slave_reference,
partition_parameter_kw=partition_parameter_kw,
shared=True
)
cls.slave_connection_parameter_dict_dict[slave_reference] = \
slave_instance.getConnectionParameterDict()
def parseSlaveParameterDict(self, key): def parseSlaveParameterDict(self, key):
return self.parseParameterDict( return self.parseParameterDict(
...@@ -945,16 +985,8 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase): ...@@ -945,16 +985,8 @@ class SlaveHttpFrontendTestCase(SlapOSInstanceTestCase):
return parameter_dict return parameter_dict
def getMasterPartitionPath(self):
return '/' + os.path.join(
*glob.glob(
os.path.join(
self.instance_path, '*', 'etc', 'Caddyfile-rejected-slave'
)
)[0].split('/')[:-2])
class TestMasterRequestDomain(SlaveHttpFrontendTestCase, TestDataMixin): class TestMasterRequestDomain(HttpFrontendTestCase, TestDataMixin):
@classmethod @classmethod
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return { return {
...@@ -965,14 +997,7 @@ class TestMasterRequestDomain(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -965,14 +997,7 @@ class TestMasterRequestDomain(SlaveHttpFrontendTestCase, TestDataMixin):
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
@classmethod
def waitForCaddy(cls):
pass
def test(self): def test(self):
# run partition until AIKC finishes
self.runComputerPartitionUntil(
self.untilNotReadyYetNotInMasterKeyGenerateAuthUrl)
parameter_dict = self.parseConnectionParameterDict() parameter_dict = self.parseConnectionParameterDict()
self.assertKeyWithPop('monitor-setup-url', parameter_dict) self.assertKeyWithPop('monitor-setup-url', parameter_dict)
self.assertKedifaKeysWithPop(parameter_dict, 'master-') self.assertKedifaKeysWithPop(parameter_dict, 'master-')
...@@ -982,16 +1007,16 @@ class TestMasterRequestDomain(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -982,16 +1007,16 @@ class TestMasterRequestDomain(SlaveHttpFrontendTestCase, TestDataMixin):
{ {
'monitor-base-url': 'https://[%s]:8401' % self._ipv6_address, 'monitor-base-url': 'https://[%s]:8401' % self._ipv6_address,
'domain': 'example.com', 'domain': 'example.com',
'accepted-slave-amount': '1', 'accepted-slave-amount': '0',
'rejected-slave-amount': '0', 'rejected-slave-amount': '0',
'slave-amount': '1', 'slave-amount': '0',
'rejected-slave-dict': {} 'rejected-slave-dict': {}
}, },
parameter_dict parameter_dict
) )
class TestMasterRequest(SlaveHttpFrontendTestCase, TestDataMixin): class TestMasterRequest(HttpFrontendTestCase, TestDataMixin):
@classmethod @classmethod
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return { return {
...@@ -1001,14 +1026,7 @@ class TestMasterRequest(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -1001,14 +1026,7 @@ class TestMasterRequest(SlaveHttpFrontendTestCase, TestDataMixin):
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
@classmethod
def waitForCaddy(cls):
pass
def test(self): def test(self):
# run partition until AIKC finishes
self.runComputerPartitionUntil(
self.untilNotReadyYetNotInMasterKeyGenerateAuthUrl)
parameter_dict = self.parseConnectionParameterDict() parameter_dict = self.parseConnectionParameterDict()
self.assertKeyWithPop('monitor-setup-url', parameter_dict) self.assertKeyWithPop('monitor-setup-url', parameter_dict)
self.assertKedifaKeysWithPop(parameter_dict, 'master-') self.assertKedifaKeysWithPop(parameter_dict, 'master-')
...@@ -1017,9 +1035,9 @@ class TestMasterRequest(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -1017,9 +1035,9 @@ class TestMasterRequest(SlaveHttpFrontendTestCase, TestDataMixin):
{ {
'monitor-base-url': 'https://[%s]:8401' % self._ipv6_address, 'monitor-base-url': 'https://[%s]:8401' % self._ipv6_address,
'domain': 'None', 'domain': 'None',
'accepted-slave-amount': '1', 'accepted-slave-amount': '0',
'rejected-slave-amount': '0', 'rejected-slave-amount': '0',
'slave-amount': '1', 'slave-amount': '0',
'rejected-slave-dict': {}}, 'rejected-slave-dict': {}},
parameter_dict parameter_dict
) )
...@@ -1101,8 +1119,6 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s { ...@@ -1101,8 +1119,6 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
'request-timeout': '12', 'request-timeout': '12',
} }
check_slave_id = 'Url'
@classmethod @classmethod
def startServerProcess(cls): def startServerProcess(cls):
cls.ca = CertificateAuthority('TestSlave') cls.ca = CertificateAuthority('TestSlave')
...@@ -1621,7 +1637,7 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s { ...@@ -1621,7 +1637,7 @@ http://apachecustomhttpsaccepted.example.com:%%(http_port)s {
r'"python-requests.*" \d+' r'"python-requests.*" \d+'
self.assertRegexpMatches( self.assertRegexpMatches(
open(log_file, 'r').read(), open(log_file, 'r').readlines()[-1],
log_regexp) log_regexp)
result_http = fakeHTTPResult( result_http = fakeHTTPResult(
parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path') parameter_dict['domain'], parameter_dict['public-ipv4'], 'test-path')
...@@ -4270,7 +4286,6 @@ class TestReplicateSlave(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -4270,7 +4286,6 @@ class TestReplicateSlave(SlaveHttpFrontendTestCase, TestDataMixin):
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
check_slave_id = 'replicate'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4338,7 +4353,6 @@ class TestReplicateSlaveOtherDestroyed(SlaveHttpFrontendTestCase): ...@@ -4338,7 +4353,6 @@ class TestReplicateSlaveOtherDestroyed(SlaveHttpFrontendTestCase):
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
check_slave_id = 'empty'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4377,7 +4391,6 @@ class TestEnableHttp2ByDefaultFalseSlave(SlaveHttpFrontendTestCase, ...@@ -4377,7 +4391,6 @@ class TestEnableHttp2ByDefaultFalseSlave(SlaveHttpFrontendTestCase,
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
check_slave_id = 'dummy-cached'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4469,7 +4482,6 @@ class TestEnableHttp2ByDefaultDefaultSlave(SlaveHttpFrontendTestCase, ...@@ -4469,7 +4482,6 @@ class TestEnableHttp2ByDefaultDefaultSlave(SlaveHttpFrontendTestCase,
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
check_slave_id = 'dummy-cached'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4559,10 +4571,6 @@ class TestRe6stVerificationUrlDefaultSlave(SlaveHttpFrontendTestCase, ...@@ -4559,10 +4571,6 @@ class TestRe6stVerificationUrlDefaultSlave(SlaveHttpFrontendTestCase,
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
@classmethod
def waitForCaddy(cls):
pass
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4572,6 +4580,11 @@ class TestRe6stVerificationUrlDefaultSlave(SlaveHttpFrontendTestCase, ...@@ -4572,6 +4580,11 @@ class TestRe6stVerificationUrlDefaultSlave(SlaveHttpFrontendTestCase,
}, },
} }
@classmethod
def waitForSlave(cls):
# no need to wait for slave availability here
return True
def test_default(self): def test_default(self):
parameter_dict = self.parseSlaveParameterDict('default') parameter_dict = self.parseSlaveParameterDict('default')
self.assertLogAccessUrlWithPop(parameter_dict) self.assertLogAccessUrlWithPop(parameter_dict)
...@@ -4618,10 +4631,6 @@ class TestRe6stVerificationUrlSlave(SlaveHttpFrontendTestCase, ...@@ -4618,10 +4631,6 @@ class TestRe6stVerificationUrlSlave(SlaveHttpFrontendTestCase,
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
@classmethod
def waitForCaddy(cls):
pass
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4777,7 +4786,6 @@ class TestDefaultMonitorHttpdPort(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -4777,7 +4786,6 @@ class TestDefaultMonitorHttpdPort(SlaveHttpFrontendTestCase, TestDataMixin):
def runKedifaUpdater(cls): def runKedifaUpdater(cls):
return return
check_slave_id = 'test'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -4828,7 +4836,6 @@ class TestQuicEnabled(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -4828,7 +4836,6 @@ class TestQuicEnabled(SlaveHttpFrontendTestCase, TestDataMixin):
'caucase_port': CAUCASE_PORT, 'caucase_port': CAUCASE_PORT,
} }
check_slave_id = 'url'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -5591,7 +5598,6 @@ class TestSlaveSlapOSMasterCertificateCompatibilityOverrideMaster( ...@@ -5591,7 +5598,6 @@ class TestSlaveSlapOSMasterCertificateCompatibilityOverrideMaster(
'mpm-graceful-shutdown-timeout': 2, 'mpm-graceful-shutdown-timeout': 2,
} }
check_slave_id = 'ssl_from_master_kedifa_overrides_master_certificate'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -5730,7 +5736,6 @@ class TestSlaveSlapOSMasterCertificateCompatibility( ...@@ -5730,7 +5736,6 @@ class TestSlaveSlapOSMasterCertificateCompatibility(
'mpm-graceful-shutdown-timeout': 2, 'mpm-graceful-shutdown-timeout': 2,
} }
check_slave_id = 'ssl_from_master'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -6489,7 +6494,6 @@ class TestSlaveSlapOSMasterCertificateCompatibilityUpdate( ...@@ -6489,7 +6494,6 @@ class TestSlaveSlapOSMasterCertificateCompatibilityUpdate(
cls.instance_parameter_dict['public-ipv4'] = cls._ipv4_address cls.instance_parameter_dict['public-ipv4'] = cls._ipv4_address
return cls.instance_parameter_dict return cls.instance_parameter_dict
check_slave_id = 'ssl_from_master'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
...@@ -6591,7 +6595,6 @@ class TestSlaveCiphers(SlaveHttpFrontendTestCase, TestDataMixin): ...@@ -6591,7 +6595,6 @@ class TestSlaveCiphers(SlaveHttpFrontendTestCase, TestDataMixin):
'ciphers': 'ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384' 'ciphers': 'ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384'
} }
check_slave_id = 'default_ciphers'
@classmethod @classmethod
def getSlaveParameterDictDict(cls): def getSlaveParameterDictDict(cls):
return { return {
......
...@@ -7,11 +7,7 @@ T-1/var/log/monitor-httpd-access.log ...@@ -7,11 +7,7 @@ T-1/var/log/monitor-httpd-access.log
T-1/var/log/monitor-httpd-error.log T-1/var/log/monitor-httpd-error.log
T-2/var/log/frontend-access.log T-2/var/log/frontend-access.log
T-2/var/log/frontend-error.log T-2/var/log/frontend-error.log
T-2/var/log/httpd-cache-direct/_waitforcaddyslave_access_log
T-2/var/log/httpd-cache-direct/_waitforcaddyslave_error_log
T-2/var/log/httpd-csr_id/expose-csr_id.log T-2/var/log/httpd-csr_id/expose-csr_id.log
T-2/var/log/httpd/_waitforcaddyslave_access_log
T-2/var/log/httpd/_waitforcaddyslave_error_log
T-2/var/log/monitor-httpd-access.log T-2/var/log/monitor-httpd-access.log
T-2/var/log/monitor-httpd-error.log T-2/var/log/monitor-httpd-error.log
T-2/var/log/trafficserver/manager.log T-2/var/log/trafficserver/manager.log
......
...@@ -7,11 +7,7 @@ T-1/var/log/monitor-httpd-access.log ...@@ -7,11 +7,7 @@ T-1/var/log/monitor-httpd-access.log
T-1/var/log/monitor-httpd-error.log T-1/var/log/monitor-httpd-error.log
T-2/var/log/frontend-access.log T-2/var/log/frontend-access.log
T-2/var/log/frontend-error.log T-2/var/log/frontend-error.log
T-2/var/log/httpd-cache-direct/_waitforcaddyslave_access_log
T-2/var/log/httpd-cache-direct/_waitforcaddyslave_error_log
T-2/var/log/httpd-csr_id/expose-csr_id.log T-2/var/log/httpd-csr_id/expose-csr_id.log
T-2/var/log/httpd/_waitforcaddyslave_access_log
T-2/var/log/httpd/_waitforcaddyslave_error_log
T-2/var/log/monitor-httpd-access.log T-2/var/log/monitor-httpd-access.log
T-2/var/log/monitor-httpd-error.log T-2/var/log/monitor-httpd-error.log
T-2/var/log/trafficserver/manager.log T-2/var/log/trafficserver/manager.log
......
...@@ -7,11 +7,6 @@ extends = ...@@ -7,11 +7,6 @@ extends =
parts = parts =
${cloudooo-buildout:parts} ${cloudooo-buildout:parts}
[gcc]
# For old version of glibmm.
part = gcc-5.5
max_version = 6
[cloudooo-buildout] [cloudooo-buildout]
parts = parts =
${stack-cloudooo-buildout:parts} ${stack-cloudooo-buildout:parts}
......
...@@ -18,4 +18,4 @@ md5sum = 307663d73ef3ef94b02567ecd322252e ...@@ -18,4 +18,4 @@ md5sum = 307663d73ef3ef94b02567ecd322252e
[template-default] [template-default]
filename = instance-default.cfg filename = instance-default.cfg
md5sum = cf68a9c7e03ee0a3a527c4edfb6ab5d1 md5sum = 40364ff26e9284cea97a58f3cd8c75e3
...@@ -240,5 +240,5 @@ config-port = $${shellinabox-frontend:port} ...@@ -240,5 +240,5 @@ config-port = $${shellinabox-frontend:port}
node-quantity = 1 node-quantity = 1
test-suite-master-url = test-suite-master-url =
instance-dict = instance-dict =
software-path-list = ["https://lab.nexedi.com/nexedi/slapos/raw/1.0.152/software/seleniumrunner/software.cfg"] software-path-list = ["https://lab.nexedi.com/nexedi/slapos/raw/1.0.154/software/seleniumrunner/software.cfg"]
keep-log-days = 15 keep-log-days = 15
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
[instance] [instance]
filename = instance.cfg.in filename = instance.cfg.in
md5sum = ab08e75c26d06d95674042d4a2934716 md5sum = cd8648ca8a4a098e1a6faf7246f0d395
[template-nginx-service] [template-nginx-service]
filename = template-nginx-service.sh.in filename = template-nginx-service.sh.in
...@@ -27,4 +27,4 @@ md5sum = 98faa5ad8cfb23a11d97a459078a1d05 ...@@ -27,4 +27,4 @@ md5sum = 98faa5ad8cfb23a11d97a459078a1d05
[template-runTestSuite] [template-runTestSuite]
filename = runTestSuite.in filename = runTestSuite.in
md5sum = 5cac160fd6f14cd69cc8d63f87cc9726 md5sum = bb3f053b6cdb0a8888e9d32e63085ed5
...@@ -28,6 +28,21 @@ www = $${:srv}/www ...@@ -28,6 +28,21 @@ www = $${:srv}/www
home = $${:etc}/home home = $${:etc}/home
ssl = $${:etc}/ssl ssl = $${:etc}/ssl
framebuffer = $${:srv}/framebuffer framebuffer = $${:srv}/framebuffer
fontconfig-cache = $${buildout:directory}/.fontconfig
[fontconfig-conf]
recipe = slapos.recipe.template:jinja2
template = ${template-fonts-conf:output}
rendered = $${directory:etc}/fonts.conf
context =
key cachedir directory:fontconfig-cache
key fonts :fonts
key includes :includes
fonts =
${ipaex-fonts:location}
${liberation-fonts:location}
includes =
${fontconfig:location}/etc/fonts/conf.d
################################# #################################
# Test runner # Test runner
......
...@@ -20,6 +20,7 @@ import json ...@@ -20,6 +20,7 @@ import json
os.environ['XORG_LOCK_DIR'] = '$${xvfb-instance:lock-dir}' os.environ['XORG_LOCK_DIR'] = '$${xvfb-instance:lock-dir}'
os.environ['DISPLAY'] = '$${xvfb-instance:display}' os.environ['DISPLAY'] = '$${xvfb-instance:display}'
os.environ['FONTCONFIG_FILE'] = '$${fontconfig-conf:rendered}'
BASE_URL = 'http://[$${nginx-configuration:ip}]:$${nginx-configuration:port}/' BASE_URL = 'http://[$${nginx-configuration:ip}]:$${nginx-configuration:port}/'
ETC_DIRECTORY = '$${directory:etc}' ETC_DIRECTORY = '$${directory:etc}'
......
...@@ -5,6 +5,8 @@ extends = ...@@ -5,6 +5,8 @@ extends =
../../component/coreutils/buildout.cfg ../../component/coreutils/buildout.cfg
../../component/git/buildout.cfg ../../component/git/buildout.cfg
../../component/xorg/buildout.cfg ../../component/xorg/buildout.cfg
../../component/fontconfig/buildout.cfg
../../component/fonts/buildout.cfg
../../component/firefox/buildout.cfg ../../component/firefox/buildout.cfg
../../component/dash/buildout.cfg ../../component/dash/buildout.cfg
../../component/nginx/buildout.cfg ../../component/nginx/buildout.cfg
......
...@@ -51,6 +51,9 @@ eggs = ...@@ -51,6 +51,9 @@ eggs =
websockify websockify
slapos.cookbook slapos.cookbook
erp5.util erp5.util
# BBB: eggs used as recipe should be kept otherwise sections depending
# on it can't be uninstalled
collective.recipe.shelloutput
scripts = scripts =
websockify websockify
......
...@@ -365,14 +365,6 @@ class TestAccessKvmClusterBootstrap(MonitorAccessMixin, InstanceTestCase): ...@@ -365,14 +365,6 @@ class TestAccessKvmClusterBootstrap(MonitorAccessMixin, InstanceTestCase):
) )
self.assertIn('<title>noVNC</title>', result.text) self.assertIn('<title>noVNC</title>', result.text)
result = requests.get(
connection_parameter_dict['KVM1-url'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertIn('<title>noVNC</title>', result.text)
@skipUnlessKvm @skipUnlessKvm
class TestInstanceResilient(InstanceTestCase): class TestInstanceResilient(InstanceTestCase):
__partition_reference__ = 'ir' __partition_reference__ = 'ir'
......
# Metabae
https://www.metabase.com/
## TODO:
* export backups for resilience
* security (proper passwords, verifiable certificate, study metabase encryption option)
[instance-profile]
filename = instance.cfg.in
md5sum = 8e48fa7c66a59b3d5faf0216922a574f
[buildout]
parts =
publish-connection-parameter
extends = ${monitor2-template:rendered}
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[metabase-instance]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:service}/$${:_buildout_section_name_}
command-line = sh -c "cd $${directory:srv-metabase}; ${java-re-8:location}/bin/java $JAVA_ARGS -jar ${metabase.jar:location}/metabase.jar"
# https://www.metabase.com/docs/latest/operations-guide/customizing-jetty-webserver.html
# note that we set org.quartz.scheduler.instanceId through $JAVA_ARGS as a workaround for machines
# which cannot resolve their hostnames. See also https://github.com/metabase/metabase/issues/8373
environment =
MB_EMOJI_IN_LOGS=false
MB_JETTY_HOST=$${:ip}
MB_JETTY_PORT=$${:-http-port}
MB_JETTY_SSL_PORT=$${:port}
MB_JETTY_SSL=true
MB_JETTY_SSL_KEYSTORE=$${metabase-keystore:file}
MB_JETTY_SSL_KEYSTORE_PASSWORD=$${metabase-keystore:password}
MB_DB_TYPE=postgres
MB_DB_DBNAME=$${postgresql:dbname}
MB_DB_PORT=$${postgresql:port}
MB_DB_USER=$${postgresql:superuser}
MB_DB_PASS=$${postgresql:password}
MB_DB_HOST=$${postgresql:ipv4}
JAVA_ARGS=-Dorg.quartz.scheduler.instanceId=$${slap-connection:computer-id}.$${slap-connection:partition-id}
hash-existing-files =
$${buildout:directory}/software_release/buildout.cfg
ip = $${instance-parameter:ipv6-random}
port = 8443
# XXX It does not seem we can prevent metabase to also listen on http, so we
# give it an http port, but don't use it.
-http-port = 18080
hostname = [$${:ip}]
scheme = https
url = $${:scheme}://$${:hostname}:$${:port}
promises =
$${metabase-promise:name}
[metabase-promise]
<= monitor-promise-base
module = check_url_available
name = $${:_buildout_section_name_}.py
config-url= $${metabase-instance:url}/api/session/properties
[metabase-keystore]
recipe = plone.recipe.command
command =
${java-re-8-output:keytool} \
-genkeypair \
-alias "metabase" \
-keyalg RSA \
-keypass "$${:password}" \
-dname "CN=$${metabase-instance:ip},OU=Unit,O=Organization,L=City,S=State,C=Country" \
-keystore "$${:file}" \
-storepass "$${:password}"
file = $${directory:etc}/.metabase_keystore
password = insecure
[postgresql]
recipe = slapos.cookbook:postgres
bin = ${postgresql10:location}/bin/
services = $${directory:service}
dbname = metabase_db
superuser = metabase-psql
password = insecure
pgdata-directory = $${directory:srv}/postgresql
ipv4 = $${instance-parameter:ipv4-random}
# disable listening on ipv6
ipv6 =
port = 5432
promises = $${postgresql-promise:name}
[postgresql-psql]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:bin}/$${:_buildout_section_name_}
command-line =
$${postgresql:bin}/psql
-h $${postgresql:pgdata-directory}
-U $${postgresql:superuser}
-d $${postgresql:dbname}
[postgresql-promise]
<= monitor-promise-base
module = check_command_execute
name = promise-postgresql.py
config-command = $${postgresql-psql:wrapper-path} -c '\q'
[postgresql-backup-crontab-entry]
recipe = slapos.cookbook:cron.d
name = $${:_buildout_section_name_}
cron-entries = $${cron:cron-entries}
time = daily
command = $${postgresql-backup:wrapper-path}
[postgresql-backup]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:bin}/$${:_buildout_section_name_}
# XXX there's a recipe for backup in slapos cookbook, but it does not create
# the backup file in an atomic way, which is not acceptable here, because we
# don't want to risk pulling a partial file. To prevent this, we create a
# temp file and move it when finished.
command-line =
sh -c "$${postgresql:bin}/pg_dump \
-h $${postgresql:pgdata-directory} \
-U $${postgresql:superuser} \
--format=custom \
-f $${:backup-file}.tmp \
$${postgresql:dbname} \
&& mv $${:backup-file}.tmp $${:backup-file}"
backup-file = $${directory:srv-backup}/backup.pg_dump
[postgresql-restore-backup]
recipe = slapos.cookbook:wrapper
wrapper-path = $${directory:bin}/$${:_buildout_section_name_}
command-line =
sh -e -c "\
echo 'This will replace current database with latest backup. Hit Ctrl+C to cancel';
sleep 5;
$${postgresql:bin}/pg_restore \
--exit-on-error \
-h $${postgresql:pgdata-directory} \
-U $${postgresql:superuser} \
-d $${postgresql:dbname} \
$${postgresql-backup:backup-file}"
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = ${dcron-output:crond}
cron-entries = $${directory:etc-cron.d}
crontabs = $${directory:var-crontabs}
cronstamps = $${directory:var-cronstamps}
catcher = $${cron-simplelogger:wrapper}
binary = $${directory:bin}/crond
[cron-service]
recipe = slapos.cookbook:wrapper
command-line = $${cron:binary}
wrapper-path = $${directory:services}/crond
hash-existing-files = $${buildout:directory}/software_release/buildout.cfg
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = $${directory:bin}/cron_simplelogger
log = $${directory:log}/cron.log
[instance-parameter]
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}
[directory]
recipe = slapos.cookbook:mkdirectory
etc = $${buildout:directory}/etc
etc-cron.d = $${:etc}/cron.d
var = $${buildout:directory}/var
var-crontabs = $${:var}/crontabs
var-cronstamps = $${:var}/cronstamps
var-cron-entries = $${:var}/cron-entries
srv = $${buildout:directory}/srv
bin = $${buildout:directory}/bin
tmp = $${buildout:directory}/tmp
service = $${:etc}/service
srv-metabase = $${:srv}/metabase
srv-backup = $${:srv}/backup
[publish-connection-parameter]
recipe = slapos.cookbook:publish
url = $${metabase-instance:url}
backup-crontab = $${postgresql-backup-crontab-entry:name}
restore-backup-script = $${postgresql-restore-backup:wrapper-path}
[buildout]
extends =
../../component/defaults.cfg
../../component/java/buildout.cfg
../../component/postgresql/buildout.cfg
../../component/dcron/buildout.cfg
../../stack/slapos.cfg
buildout.hash.cfg
../../stack/monitor/buildout.cfg
parts =
slapos-cookbook
instance-profile
[python]
part = python3
[metabase.jar]
recipe = slapos.recipe.build:download
url = https://downloads.metabase.com/v0.35.3/metabase.jar
md5sum = 73c98cdf5cecde80463ef868e77d3b0e
[instance-profile]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/instance.cfg
[versions]
slapos.recipe.template = 4.4
Tests for Metabase 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
version = '0.0.1.dev0'
name = 'slapos.test.metabase'
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
description="Test for SlapOS' metabase",
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',
'slapos.cookbook',
'slapos.libnetworkcache',
'supervisor',
'six',
'requests'
],
zip_safe=True,
test_suite='test',
)
##############################################################################
# coding: utf-8
#
# Copyright (c) 2020 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 json
from six.moves.urllib import parse
import requests
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
setUpModule, MetabaseTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class TestMetabaseSetup(MetabaseTestCase):
__partition_reference__ = 'S' # postgresql use a socket in data dir
# instance can take time, /api/session/properties timeout at the beginning.
instance_max_retry = 30
def test_setup(self):
url = self.computer_partition.getConnectionParameterDict()['url']
resp = requests.get(parse.urljoin(url, '/setup'), verify=False)
self.assertTrue(resp.text)
# get a setup token as described in https://github.com/metabase/metabase/issues/4240#issuecomment-290717451
properties = requests.get(
parse.urljoin(url, '/api/session/properties'), verify=False,
timeout=10).json()
email = "youlooknicetoday@email.com"
password = "password123456"
request_json = {
'token': properties['setup-token'],
'prefs': {
'allow_tracking': 'false',
'site_name': 'Org'
},
'user': {
'email': email,
'password': password,
'first_name': 'Johnny',
'last_name': 'Appleseed',
'site_name': 'Org',
},
'database': None
}
resp = requests.post(
parse.urljoin(url, '/api/setup'),
json=request_json,
verify=False,
timeout=5)
self.assertTrue(resp.ok)
resp = requests.post(
parse.urljoin(url, '/api/session'),
verify=False,
json={
"username": email,
"password": "wrong"
})
self.assertEqual(requests.codes.bad_request, resp.status_code)
session = requests.post(
parse.urljoin(url, '/api/session'),
verify=False,
json={
"username": email,
"password": password
}).json()
self.assertTrue(session.get('id'))
...@@ -4,11 +4,6 @@ extends = ...@@ -4,11 +4,6 @@ extends =
../../component/redis/buildout.cfg ../../component/redis/buildout.cfg
../../stack/lamp/buildout.cfg ../../stack/lamp/buildout.cfg
[gcc]
# For old version of glibmm.
part = gcc-5.5
max_version = 6
[nc-download-base] [nc-download-base]
recipe = hexagonit.recipe.download recipe = hexagonit.recipe.download
ignore-existing = true ignore-existing = true
......
...@@ -98,6 +98,11 @@ setup = ${slapos-repository:location}/software/seleniumserver/test/ ...@@ -98,6 +98,11 @@ setup = ${slapos-repository:location}/software/seleniumserver/test/
egg = slapos.test.slaprunner egg = slapos.test.slaprunner
setup = ${slapos-repository:location}/software/slaprunner/test/ setup = ${slapos-repository:location}/software/slaprunner/test/
[slapos.test.metabase-setup]
<= setup-develop-egg
egg = slapos.test.metabase
setup = ${slapos-repository:location}/software/metabase/test/
[slapos.test.helloworld-setup] [slapos.test.helloworld-setup]
<= setup-develop-egg <= setup-develop-egg
egg = slapos.test.helloworld egg = slapos.test.helloworld
...@@ -187,6 +192,7 @@ eggs = ...@@ -187,6 +192,7 @@ eggs =
${slapos.test.theia-setup:egg} ${slapos.test.theia-setup:egg}
${slapos.test.cloudooo-setup:egg} ${slapos.test.cloudooo-setup:egg}
${slapos.test.dream-setup:egg} ${slapos.test.dream-setup:egg}
${slapos.test.metabase-setup:egg}
${backports.lzma:egg} ${backports.lzma:egg}
entry-points = entry-points =
runTestSuite=erp5.util.testsuite:runTestSuite runTestSuite=erp5.util.testsuite:runTestSuite
...@@ -229,6 +235,7 @@ context = ...@@ -229,6 +235,7 @@ context =
tests = tests =
${slapos.test.kvm-setup:setup} ${slapos.test.kvm-setup:setup}
${slapos.test.slaprunner-setup:setup} ${slapos.test.slaprunner-setup:setup}
${slapos.test.metabase-setup:setup}
${:extra} ${:extra}
extra = extra =
${slapos.cookbook-setup:setup} ${slapos.cookbook-setup:setup}
......
...@@ -72,14 +72,15 @@ recipe = plone.recipe.command ...@@ -72,14 +72,15 @@ recipe = plone.recipe.command
command = true command = true
[versions] [versions]
Paste = 2.0.2 Paste = 3.4.0
PasteScript = 2.0.2 PasteScript = 3.2.0
WSGIUtils = 0.7 WSGIUtils = 0.7.2
python-magic = 0.4.6 WSGIserver = 1.3
python-magic = 0.4.18
rdiff-backup = 1.0.5+SlapOSPatched001 rdiff-backup = 1.0.5+SlapOSPatched001
slapos.recipe.template = 4.4 slapos.recipe.template = 4.4
# Required by: # Required by:
# PasteScript==2.0 # PasteScript== 3.2.0
# cloudooo==1.2.5.dev0 # cloudooo==1.2.6.dev0
PasteDeploy = 1.5.2 PasteDeploy = 2.1.0
...@@ -84,10 +84,6 @@ parts += ...@@ -84,10 +84,6 @@ parts +=
# jupyter # jupyter
jupyter-notebook-initialized-scripts jupyter-notebook-initialized-scripts
[gcc]
# KumoFS is known not to build with gcc>6.
# It may work with slightly more recent but not tested.
part = gcc-5.5
# override instance-jupyter-notebook not to render into default template.cfg # override instance-jupyter-notebook not to render into default template.cfg
[instance-jupyter-notebook] [instance-jupyter-notebook]
......
...@@ -70,7 +70,7 @@ md5sum = cc19560b9400cecbd23064d55c501eec ...@@ -70,7 +70,7 @@ md5sum = cc19560b9400cecbd23064d55c501eec
[template] [template]
filename = instance.cfg.in filename = instance.cfg.in
md5sum = e19aaec1878f40bf4ddb4c45a4470b21 md5sum = f0f3b18f9963b137e366752886591fc3
[monitor-template-dummy] [monitor-template-dummy]
filename = dummy.cfg filename = dummy.cfg
......
...@@ -102,7 +102,7 @@ link-binary = {{ dumps(zope_link_binary) }} ...@@ -102,7 +102,7 @@ link-binary = {{ dumps(zope_link_binary) }}
fonts = {{ dumps(zope_fonts) }} fonts = {{ dumps(zope_fonts) }}
fontconfig-includes = {{ dumps(zope_fontconfig_includes) }} fontconfig-includes = {{ dumps(zope_fontconfig_includes) }}
template-fonts-conf = {{ dumps(template_fonts_conf) }} template-fonts-conf = {{ dumps(template_fonts_conf) }}
userhosts = {{ userhosts_location }} userhosts = {{ userhosts_location }}/bin/userhosts
site-zcml = {{ site_zcml }} site-zcml = {{ site_zcml }}
extra-path-list = {{ dumps(extra_path_list) }} extra-path-list = {{ dumps(extra_path_list) }}
matplotlibrc = {{ matplotlibrc_location }} matplotlibrc = {{ matplotlibrc_location }}
......
...@@ -118,7 +118,7 @@ eggs = ...@@ -118,7 +118,7 @@ eggs =
[versions] [versions]
setuptools = 44.0.0 setuptools = 44.0.0
# Use SlapOS patched zc.buildout # Use SlapOS patched zc.buildout
zc.buildout = 2.7.1+slapos007 zc.buildout = 2.7.1+slapos008
# Use SlapOS patched zc.recipe.egg (zc.recipe.egg 2.x is for Buildout 2) # Use SlapOS patched zc.recipe.egg (zc.recipe.egg 2.x is for Buildout 2)
zc.recipe.egg = 2.0.3+slapos003 zc.recipe.egg = 2.0.3+slapos003
# Use own version of h.r.download to be able to open .xz and .lz archives # Use own version of h.r.download to be able to open .xz and .lz archives
...@@ -212,7 +212,7 @@ enum34 = 1.1.6 ...@@ -212,7 +212,7 @@ enum34 = 1.1.6
# Required by: # Required by:
# slapos.toolbox==0.94 # slapos.toolbox==0.94
erp5.util = 0.4.67 erp5.util = 0.4.68
# Required by: # Required by:
# slapos.toolbox==0.94 # slapos.toolbox==0.94
......
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