Commit b9485921 authored by Rafael Monnerat's avatar Rafael Monnerat

Update Release Candidate

parents 92c1115a 1c492ab2
{
"$schema": "http://json-schema.org/draft-04/schema",
"properties": {
"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"
},
"url": {
"description": "Url of the backend",
"pattern": "^(http|https|ftp)://",
"title": "Backend URL",
"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, redirect, notebook and websocket, not implemneted is eventsource.",
"enum": [
"",
"zope",
"redirect",
"notebook",
"websocket",
"eventsource"
],
"title": "Backend Type",
"type": "string"
},
"path": {
"default": "",
"description": "Path to proxy to in the backend",
"title": "type:zope Backend Path",
"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"
},
"caddy_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",
......@@ -15,12 +67,6 @@
"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)",
......@@ -63,26 +109,6 @@
"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)://",
......@@ -101,12 +127,6 @@
"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"
},
"websocket-path-list": {
"default": "",
"description": "Space separated list of path to the websocket application. If not set the whole slave will be websocket, if set then / will be HTTP, and /<websocket-path> will be WSS. In order to have ' ' in the space use '%20'",
......@@ -183,26 +203,6 @@
"title": "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, redirect, notebook and websocket, not implemneted is eventsource.",
"enum": [
"",
"zope",
"redirect",
"notebook",
"websocket",
"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.",
......
......@@ -28,7 +28,8 @@ from setuptools import setup, find_packages
version = '0.0.1.dev0'
name = 'slapos.test.erp5'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
......
......@@ -25,15 +25,24 @@
#
##############################################################################
import json
import os
import unittest
import logging
if os.environ.get('DEBUG'):
raise ValueError("Don't set DEBUG - it breaks postfix compilation - set SLAPOS_TEST_DEBUG instead.")
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
debug_mode = os.environ.get('SLAPOS_TEST_DEBUG')
# for development: debugging logs and install Ctrl+C handler
if debug_mode:
logging.basicConfig(level=logging.DEBUG)
unittest.installHandler()
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..', 'software.cfg')))
class ERP5InstanceTestCase(SlapOSInstanceTestCase):
"""ERP5 base test case
"""
# ERP5 instanciation needs to run several times before being ready, as
# the root instance request more instances.
instance_max_retry = 7 # XXX how many times ?
def getRootPartitionConnectionParameterDict(self):
"""Return the output paramters from the root partition"""
return json.loads(
self.computer_partition.getConnectionParameterDict()['_'])
......@@ -29,28 +29,15 @@ import os
import json
import glob
import urlparse
import logging
import socket
import time
import psutil
import requests
from utils import SlapOSInstanceTestCase
class ERP5TestCase(SlapOSInstanceTestCase):
"""Test the remote driver on a minimal web server.
"""
logger = logging.getLogger(__name__)
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'software.cfg')), )
def getRootPartitionConnectionParameterDict(self):
"""Return the output paramters from the root partition"""
return json.loads(
self.computer_partition.getConnectionParameterDict()['_'])
from . import ERP5InstanceTestCase
from . import setUpModule
setUpModule # pyflakes
class TestPublishedURLIsReachableMixin(object):
......@@ -60,12 +47,14 @@ class TestPublishedURLIsReachableMixin(object):
# What happens is that instanciation just create the services, but does not
# wait for ERP5 to be initialized. When this test run ERP5 instance is
# instanciated, but zope is still busy creating the site and haproxy replies
# with 503 Service Unavailable.
# with 503 Service Unavailable, sometimes the first request is 404, so we
# retry in a loop.
# If we can move the "create site" in slapos node instance, then this retry loop
# would not be necessary.
for i in range(1, 20):
for i in range(1, 60):
r = requests.get(url, verify=False) # XXX can we get CA from caucase already ?
if r.status_code == requests.codes.service_unavailable:
if r.status_code in (requests.codes.service_unavailable,
requests.codes.not_found):
delay = i * 2
self.logger.warn("ERP5 was not available, sleeping for %ds and retrying", delay)
time.sleep(delay)
......@@ -91,13 +80,13 @@ class TestPublishedURLIsReachableMixin(object):
urlparse.urljoin(param_dict['family-default'], param_dict['site-id']))
class TestDefaultParameters(ERP5TestCase, TestPublishedURLIsReachableMixin):
class TestDefaultParameters(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 can be instanciated with no parameters
"""
__partition_reference__ = 'defp'
class TestMedusa(ERP5TestCase, TestPublishedURLIsReachableMixin):
class TestMedusa(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 Medusa server
"""
__partition_reference__ = 'medusa'
......@@ -107,7 +96,7 @@ class TestMedusa(ERP5TestCase, TestPublishedURLIsReachableMixin):
return {'_': json.dumps({'wsgi': False})}
class TestApacheBalancerPorts(ERP5TestCase):
class TestApacheBalancerPorts(ERP5InstanceTestCase):
"""Instanciate with two zope families, this should create for each family:
- a balancer entry point with corresponding haproxy
- a balancer entry point for test runner
......@@ -159,8 +148,8 @@ class TestApacheBalancerPorts(ERP5TestCase):
def test_zope_listen(self):
# we requested 3 zope in family1 and 5 zopes in family2, we should have 8 zope running.
all_process_info = self.getSupervisorRPCServer(
).supervisor.getAllProcessInfo()
with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo()
self.assertEqual(
3 + 5,
len([p for p in all_process_info if p['name'].startswith('zope-')]))
......@@ -168,8 +157,8 @@ class TestApacheBalancerPorts(ERP5TestCase):
def test_apache_listen(self):
# We have 2 families, apache should listen to a total of 3 ports per family
# normal access on ipv4 and ipv6 and test runner access on ipv4 only
all_process_info = self.getSupervisorRPCServer(
).supervisor.getAllProcessInfo()
with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo()
process_info, = [p for p in all_process_info if p['name'] == 'apache']
apache_process = psutil.Process(process_info['pid'])
self.assertEqual(
......@@ -182,8 +171,8 @@ class TestApacheBalancerPorts(ERP5TestCase):
def test_haproxy_listen(self):
# There is one haproxy per family
all_process_info = self.getSupervisorRPCServer(
).supervisor.getAllProcessInfo()
with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo()
process_info, = [
p for p in all_process_info if p['name'].startswith('haproxy-')
]
......@@ -193,7 +182,7 @@ class TestApacheBalancerPorts(ERP5TestCase):
])
class TestDisableTestRunner(ERP5TestCase, TestPublishedURLIsReachableMixin):
class TestDisableTestRunner(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 can be instanciated without test runner.
"""
__partition_reference__ = 'distr'
......@@ -215,8 +204,8 @@ class TestDisableTestRunner(ERP5TestCase, TestPublishedURLIsReachableMixin):
def test_no_apache_testrunner_port(self):
# Apache only listen on two ports, there is no apache ports allocated for test runner
all_process_info = self.getSupervisorRPCServer(
).supervisor.getAllProcessInfo()
with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo()
process_info, = [p for p in all_process_info if p['name'] == 'apache']
apache_process = psutil.Process(process_info['pid'])
self.assertEqual(
......
This diff is collapsed.
......@@ -28,9 +28,11 @@ from setuptools import setup, find_packages
version = '0.0.1.dev0'
name = 'slapos.test.helloworld'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
setup(
name=name,
version=version,
description="Test for SlapOS' helloworld",
long_description=long_description,
......@@ -47,4 +49,4 @@ setup(name=name,
],
zip_safe=True,
test_suite='test',
)
)
......@@ -27,26 +27,19 @@
import os
import requests
import utils
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class HelloWorldTestCase(utils.SlapOSInstanceTestCase):
class HelloWorldTestCase(SlapOSInstanceTestCase):
# to be defined by subclasses
name = None
kind = None
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')),)
@classmethod
def getInstanceParameterDict(cls):
return {"name": cls.name}
......
This diff is collapsed.
......@@ -25,26 +25,20 @@
#
##############################################################################
import utils
import httplib
import json
import os
import requests
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
setUpModule, InstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class TestJupyter(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')),)
class TestJupyter(InstanceTestCase):
def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
......@@ -54,12 +48,11 @@ class TestJupyter(utils.SlapOSInstanceTestCase):
except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
ip = os.environ['SLAPOS_TEST_IPV6']
self.assertEqual(
{
'jupyter-classic-url': 'https://[%s]:8888/tree' % (ip,),
'jupyterlab-url': 'https://[%s]:8888/lab' % (ip,),
'url': 'https://[%s]:8888/tree' % (ip,)
'jupyter-classic-url': 'https://[%s]:8888/tree' % (self._ipv6_address, ),
'jupyterlab-url': 'https://[%s]:8888/lab' % (self._ipv6_address, ),
'url': 'https://[%s]:8888/tree' % (self._ipv6_address, )
},
connection_dict
)
......
This diff is collapsed.
......@@ -4,8 +4,7 @@ kvm
Introduction
------------
This software release is used to deploy KVM instances, NBD instances and
Frontend instances of KVM.
This software release is used to deploy KVM and NBD instances.
For extensive parameters definition, please look at parameter-input-schema.json.
......@@ -35,9 +34,10 @@ See the instance-kvm-input-schema.json file for more instance parameters (cpu-co
KVM instance parameters:
~~~~~~~~~~~~~~~~~~~~~~~~~
- frontend-software-type (default: frontend)
- frontend-software-url (default: https://lab.nexedi.com/nexedi/slapos/raw/slapos-0.92/software/kvm/software.cfg)
- frontend-software-type (default: RootSoftwareInstance)
- frontend-software-url (default: http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg)
- frontend-instance-guid
- frontend-addtional-instance-guid
- frontend-instance-name (default: VNC Frontend)
- nbd-port (default: 1024)
- nbd-host
......@@ -119,21 +119,3 @@ files for more instance parameters (cpu-count, ram-size, disk-size, specific loc
Then, if you want one of the two clones to takeover, you need to login into
the hosting machine, go to the partition of the clone, and invoke bin/takeover.
KVM Frontend Master Instance (will host all frontend Slave Instances)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This type of instance will allow to host any frontend slave instance requested
by KVM instances. Slave instances (and thus KVM instance) will be accessible
at : https://mydomain.com/instancereference .
::
mykvmfrontend = request(
software_release=kvm,
partition_reference="mykvmfrontend",
partition_parameter_kw={
"domain":"mydomain.com"
},
software_type="frontend",
)
......@@ -15,15 +15,15 @@
[template]
filename = instance.cfg.in
md5sum = 028b6a6456d744c11b1bb2c51ecd51b2
md5sum = 2cbfd6b08c65369c1d45cf3ba2ff335a
[template-kvm]
filename = instance-kvm.cfg.jinja2
md5sum = 325326fa7266757dfed028b11aae58a0
md5sum = dc4dc40f9d950b5f963c22c62ca488a7
[template-kvm-cluster]
filename = instance-kvm-cluster.cfg.jinja2.in
md5sum = 2bbee46d39aec87e92c8462efab292b6
md5sum = c7ce0510c05753d428c18b756f827573
[template-kvm-resilient]
filename = instance-kvm-resilient.cfg.jinja2
......@@ -49,10 +49,6 @@ md5sum = b617d64de73de1eed518185f310bbc82
filename = instance-nbd.cfg.in
md5sum = f634a5249b773658b7a7bc9fa9bb0368
[template-frontend]
filename = instance-frontend.cfg.in
md5sum = 57a4be74e5afb00e378bc726cd7771f8
[template-ansible-promise]
filename = template/ansible-promise.in
md5sum = 2036bf145f472f62ef8dee5e729328fd
......
#############################
#
# Instanciate kvm frontend
#
#############################
[buildout]
parts =
ca-frontend
certificate-authority
frontend-promise-ipv6
frontend-promise-ipv4
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[rootdirectory]
recipe = slapos.cookbook:mkdirectory
etc = $${buildout:directory}/etc
bin = $${buildout:directory}/bin
srv = $${buildout:directory}/srv
var = $${buildout:directory}/var
[basedirectory]
recipe = slapos.cookbook:mkdirectory
services = $${rootdirectory:etc}/run
promises = $${rootdirectory:etc}/promise
nodejs-conf = $${rootdirectory:etc}/nodejs
run = $${rootdirectory:var}/run
log = $${rootdirectory:var}/log
ca-dir = $${rootdirectory:srv}/ssl
backup = $${rootdirectory:srv}/backup
[directory]
recipe = slapos.cookbook:mkdirectory
ca-dir = $${rootdirectory:srv}/ssl
[frontend-instance]
recipe = slapos.cookbook:kvm.frontend
domain = $${ca-frontend:name}
# port = $${slap-parameter:port}
ipv6 = $${slap-network-information:global-ipv6}
ipv4 = $${slap-network-information:local-ipv4}
port = $${slap-parameter:port}
http-redirection = $${slap-parameter:http-redirection}
ssl-key-path = $${ca-frontend:key-file}
ssl-cert-path = $${ca-frontend:cert-file}
slave-instance-list = $${slap-parameter:slave_instance_list}
map-path = $${basedirectory:nodejs-conf}/proxy_table.json
conf-path = $${basedirectory:nodejs-conf}/kvm-proxy.js
wrapper-path = $${rootdirectory:bin}/kvm_frontend
node-binary = ${nodejs:location}/bin/node
node-env = ${buildout:parts-directory}:${npm-modules:location}/node_modules
shell-path = ${dash:location}/bin/dash
[frontend-promise-ipv6]
recipe = slapos.cookbook:check_port_listening
path = $${basedirectory:promises}/frontend_promise
hostname = $${frontend-instance:ipv6}
port = $${frontend-instance:port}
[frontend-promise-ipv4]
recipe = slapos.cookbook:check_port_listening
path = $${basedirectory:promises}/frontend_promise
hostname = $${frontend-instance:ipv4}
port = $${frontend-instance:port}
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = ${openssl:location}/bin/openssl
ca-dir = $${basedirectory:ca-dir}
requests-directory = $${cadirectory:requests}
wrapper = $${basedirectory:services}/certificate_authority
ca-private = $${cadirectory:private}
ca-certs = $${cadirectory:certs}
ca-newcerts = $${cadirectory:newcerts}
ca-crl = $${cadirectory:crl}
[cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = $${basedirectory:ca-dir}/requests/
private = $${basedirectory:ca-dir}/private/
certs = $${basedirectory:ca-dir}/certs/
newcerts = $${basedirectory:ca-dir}/newcerts/
crl = $${basedirectory:ca-dir}/crl/
[ca-frontend]
<= certificate-authority
recipe = slapos.cookbook:certificate_authority.request
key-file = $${basedirectory:nodejs-conf}/nodejs.key
cert-file = $${basedirectory:nodejs-conf}/nodejs.crt
executable = $${frontend-instance:wrapper-path}
wrapper = $${basedirectory:services}/nodejs
# Put domain name
name = $${slap-parameter:domain}
[slap-parameter]
# Default value if no port is specified
port = 4443
http-redirection = 0
slave_instance_list =
......@@ -10,21 +10,38 @@
"frontend-instance-guid": {
"title": "Frontend Instance ID",
"description": "Unique identifier of the frontend instance, like \"SOFTINST-11031\".",
"type": "string",
"default": ""
"type": "string"
},
"frontend-software-type": {
"title": "Frontend Software Type",
"description": "Type of the frontend instance, like \"frontend\".",
"description": "Type of the frontend instance, like \"RootSoftwareInstance\".",
"type": "string",
"default": "frontend"
"default": "RootSoftwareInstance"
},
"frontend-software-url": {
"title": "Frontend Software URL",
"description": "Software Release URL of the frontend instance, like \"http://example.com/path/to/software.cfg\".",
"type": "string",
"format": "uri",
"default": "https://lab.nexedi.com/nexedi/slapos/raw/slapos-0.92/software/kvm/software.cfg"
"default": "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg"
},
"frontend-additional-instance-guid": {
"title": "Additional Frontend Instance ID",
"description": "Unique identifier of the additional frontend instance, like \"SOFTINST-11031\", if empty won't be requested.",
"type": "string"
},
"frontend-additional-software-type": {
"title": "Additional Frontend Software Type",
"description": "Type of the frontend instance, like \"RootSoftwareInstance\".",
"type": "string",
"default": "RootSoftwareInstance"
},
"frontend-additional-software-url": {
"title": "Additional Frontend Software URL",
"description": "Software Release URL of the frontend instance, like \"http://example.com/path/to/software.cfg\".",
"type": "string",
"format": "uri",
"default": "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg"
}
},
"type": "object"
......
......@@ -6,6 +6,8 @@
{% set slave_frontend_sr = slave_frontend_dict.get('software-url', 'http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg') -%}
{% set slave_frontend_stype = slave_frontend_dict.get('software-type', 'custom-personal') -%}
{% set slave_frontend_iguid = slave_frontend_dict.get('instance-guid', '') -%}
{% set WEBSOCKET_FRONTEND_DEFAULT_SR = 'http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg' %}
{% set WEBSOCKET_FRONTEND_DEFAULT_ST = 'RootSoftwareInstance' %}
{% set kvm_instance_dict = {} -%}
{% set kvm_hostname_list = [] -%}
{% set monitor_base_url_dict = {} -%}
......@@ -47,10 +49,16 @@ sla-project_guid = {{ dumps(kvm_parameter_dict.get('project-guid', '')) }}
state = stopped
{% endif -%}
config-frontend-instance-name = {{ instance_name ~ ' VNC Frontend' }}
config-frontend-software-type = {{ dumps(frontend_dict.get('software-type', 'frontend')) }}
config-frontend-software-url = {{ dumps(frontend_dict.get('software-url', 'http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.92:/software/kvm/software.cfg')) }}
{{ setconfig('frontend-instance-guid', kvm_parameter_dict.get('instance-guid', '')) }}
config-frontend-instance-name = {{ instance_name ~ ' VNC Real Frontend' }}
{{ setconfig('frontend-software-url', frontend_dict.get('frontend-software-url', WEBSOCKET_FRONTEND_DEFAULT_SR)) }}
{{ setconfig('frontend-software-type', frontend_dict.get('frontend-software-type', WEBSOCKET_FRONTEND_DEFAULT_ST)) }}
{{ setconfig('frontend-instance-guid', frontend_dict.get('frontend-instance-guid', '')) }}
config-frontend-additional-instance-name = {{ instance_name ~ ' VNC Real Frontend Additional' }}
{{ setconfig('frontend-additional-software-url', frontend_dict.get('frontend-additional-software-url', WEBSOCKET_FRONTEND_DEFAULT_SR)) }}
{{ setconfig('frontend-additional-software-type', frontend_dict.get('frontend-additional-software-type', WEBSOCKET_FRONTEND_DEFAULT_ST)) }}
{{ setconfig('frontend-additional-instance-guid', frontend_dict.get('frontend-additional-instance-guid', '')) }}
config-name = {{ instance_name }}
{% if slapparameter_dict.get('authorized-keys', []) -%}
config-authorized-key = {{ dumps(slapparameter_dict.get('authorized-keys') | join('\n')) }}
......@@ -100,7 +108,7 @@ config-httpd-port = {{ dumps(kvm_parameter_dict.get('httpd-port', 8081)) }}
config-disable-ansible-promise = {{ dumps(kvm_parameter_dict.get('disable-ansible-promise', False)) }}
config-monitor-cors-domains = {{ slapparameter_dict.get('monitor-cors-domains', 'monitor.app.officejs.com') }}
config-monitor-username = ${monitor-instance-parameter:username}
config-monitor-password = ${publish-early:monitor-password}
config-monitor-password = ${monitor-htpasswd:passwd}
# Enable disk wipe options
{% if kvm_parameter_dict.get('wipe-disk-ondestroy', False) -%}
config-wipe-disk-ondestroy = True
......@@ -126,6 +134,9 @@ sla-fw_restricted_access = {{ dumps(slapparameter_dict.get('fw-restricted-access
return =
url
{% if frontend_dict.get('frontend-additional-instance-guid', '') %}
url-additional
{% endif %}
backend-url
{% if str(use_nat).lower() == 'true' -%}
{% for port in nat_rules_list -%}
......@@ -151,6 +162,9 @@ return =
{% do monitor_base_url_dict.__setitem__(instance_name, '${' ~ section ~ ':connection-monitor-base-url}') -%}
{% do publish_dict.__setitem__(instance_name ~ '-backend-url', '${' ~ section ~ ':connection-backend-url}') -%}
{% do publish_dict.__setitem__(instance_name ~ '-url', '${' ~ section ~ ':connection-url}') -%}
{% if frontend_dict.get('frontend-additional-instance-guid', '') %}
{% do publish_dict.__setitem__(instance_name ~ '-url-additional', '${' ~ section ~ ':connection-url-additional}') -%}
{% endif %}
{% do kvm_instance_dict.__setitem__(instance_name, (use_nat, nat_rules_list)) -%}
{% endfor %}
......@@ -256,11 +270,6 @@ mode = {{ mode }}
{{ writefile('cluster-data-content', '${directory:webroot}/${hash-code:passwd}/data', slapparameter_dict.get('cluster-data', ''), '700') }}
{% endif -%}
[publish-early]
recipe = slapos.cookbook:publish-early
-init =
monitor-password monitor-htpasswd:passwd
[monitor-instance-parameter]
monitor-httpd-port = 8060
cors-domains = {{ slapparameter_dict.get('monitor-cors-domains', 'monitor.app.officejs.com') }}
......@@ -277,14 +286,11 @@ private-path-list +=
${directory:webroot}/
[publish-connection-information]
<= monitor-publish
recipe = slapos.cookbook:publish
{% for name, value in publish_dict.items() -%}
{{ name }} = {{ value }}
{% endfor %}
{% set monitor_interface_url = slapparameter_dict.get('monitor-interface-url', 'https://monitor.app.officejs.com') -%}
monitor-setup-url = {{ monitor_interface_url }}/#page=settings_configurator&url=${monitor-publish-parameters:monitor-url}&username=${monitor-publish-parameters:monitor-user}&password=${monitor-publish-parameters:monitor-password}
monitor-password = ${publish-early:monitor-password}
monitor-user = ${monitor-publish-parameters:monitor-user}
{% do part_list.append('monitor-base') -%}
[buildout]
......
......@@ -336,21 +336,38 @@
"frontend-instance-guid": {
"title": "Frontend Instance ID",
"description": "Unique identifier of the frontend instance, like \"SOFTINST-11031\".",
"type": "string",
"default": "SOFTINST-11031"
"type": "string"
},
"frontend-software-type": {
"title": "Frontend Software Type",
"description": "Type of the frontend instance, like \"frontend\".",
"type": "string",
"default": "frontend"
"default": "RootSoftwareInstance"
},
"frontend-software-url": {
"title": "Frontend Software URL",
"description": "Software Release URL of the frontend instance, like \"http://example.com/path/to/software.cfg\".",
"type": "string",
"format": "uri",
"default": "https://lab.nexedi.com/nexedi/slapos/raw/slapos-0.92/software/kvm/software.cfg"
"default": "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg"
},
"frontend-additional-instance-guid": {
"title": "Additional Frontend Instance ID",
"description": "Unique identifier of the additional frontend instance, like \"SOFTINST-11031\", if empty won't be requested.",
"type": "string"
},
"frontend-additional-software-type": {
"title": "Additional Frontend Software Type",
"description": "Type of the frontend instance, like \"frontend\".",
"type": "string",
"default": "RootSoftwareInstance"
},
"frontend-additional-software-url": {
"title": "Additional Frontend Software URL",
"description": "Software Release URL of the frontend instance, like \"http://example.com/path/to/software.cfg\".",
"type": "string",
"format": "uri",
"default": "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg"
}
}
}
{% set additional_frontend = (slapparameter_dict.get('frontend-additional-instance-guid', '').strip() != '') %}
{% set enable_http = slapparameter_dict.get('enable-http-server', 'False').lower() -%}
{% set use_tap = slapparameter_dict.get('use-tap', 'True').lower() -%}
{% set use_nat = slapparameter_dict.get('use-nat', 'True').lower() -%}
......@@ -8,7 +9,6 @@
{% set enable_device_hotplug = slapparameter_dict.get('enable-device-hotplug', 'false').lower() -%}
{% set instance_type = slapparameter_dict.get('type', 'standalone') -%}
{% set nat_rule_list = slapparameter_dict.get('nat-rules', '22 80 443') -%}
{% set frontend_software_type = 'default' -%}
{% set disk_device_path = slapparameter_dict.get('disk-device-path', None) -%}
{% set extends_list = [] -%}
{% set part_list = [] -%}
......@@ -359,20 +359,24 @@ log = ${directory:log}/crond.log
#--
#-- Deploy frontend.
[request-slave-frontend]
[request-slave-frontend-base]
recipe = slapos.cookbook:requestoptional
software-url = ${slap-parameter:frontend-software-url}
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
name = ${slap-parameter:frontend-instance-name}
software-type = ${slap-parameter:frontend-software-type}
slave = true
config-host = ${novnc-instance:ip}
config-port = ${novnc-instance:port}
return = url resource port domainname
config-https-only = True
config-type = websocket
config-url = https://[${novnc-instance:ip}]:${novnc-instance:port}
return = secure_access domain
[request-slave-frontend]
<= request-slave-frontend-base
software-url = ${slap-parameter:frontend-software-url}
software-type = ${slap-parameter:frontend-software-type}
name = ${slap-parameter:frontend-instance-name}
sla-instance_guid = ${slap-parameter:frontend-instance-guid}
[frontend-promise]
......@@ -382,6 +386,21 @@ url = ${publish-connection-information:url}
dash_path = {{ dash_executable_location }}
curl_path = {{ curl_executable_location }}
{% if additional_frontend %}
[request-slave-frontend-additional]
<= request-slave-frontend-base
software-url = ${slap-parameter:frontend-additional-software-url}
software-type = ${slap-parameter:frontend-additional-software-type}
name = ${slap-parameter:frontend-additional-instance-name}
sla-instance_guid = ${slap-parameter:frontend-additional-instance-guid}
[frontend-additional-promise]
recipe = slapos.cookbook:check_url_available
path = ${directory:promises}/frontend_additional_promise
url = ${publish-connection-information:url-additional}
dash_path = {{ dash_executable_location }}
curl_path = {{ curl_executable_location }}
{% endif %}
{% if enable_http == 'true' %}
[httpd]
......@@ -422,12 +441,47 @@ interface-url = {{ slapparameter_dict.get('monitor-interface-url', 'https://moni
[helper]
blank-line =
[frontend-port-execute-base]
recipe = plone.recipe.command
command =
set -e
port=$(echo '${request-slave-frontend:connection-secure_access}' | cut -d ':' -f 3 | cut -d '/' -f 1)
[ -z $port ] && port=443
echo $port > ${:output}
update-command = ${:command}
stop-on-error = True
[frontend-port-execute]
<= frontend-port-execute-base
secure_access = ${request-slave-frontend:connection-secure_access}
output = ${directory:var}/frontend_port.txt
[frontend-port]
recipe = collective.recipe.shelloutput
filename = ${frontend-port-execute:output}
commands =
port = [ -f '${:filename}' ] && cat '${:filename}' || echo "NotReady"
{% if additional_frontend %}
[frontend-additional-port-execute]
<= frontend-port-execute-base
secure_access = ${request-slave-frontend-additional:connection-secure_access}
output = ${directory:var}/frontend_additional_port.txt
[frontend-additional-port]
<= frontend-port
filename = ${frontend-additional-port-execute:output}
{% endif %}
[publish-connection-information]
<= monitor-publish
recipe = slapos.cookbook:publish
ipv6 = ${slap-network-information:global-ipv6}
backend-url = https://[${novnc-instance:ip}]:${novnc-instance:port}/vnc.html?host=[${novnc-instance:ip}]&port=${novnc-instance:port}&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd}
url = ${request-slave-frontend:connection-url}/vnc.html?host=${request-slave-frontend:connection-domainname}&port=${request-slave-frontend:connection-port}&encrypt=1&path=${request-slave-frontend:connection-resource}&password=${kvm-controller-parameter-dict:vnc-passwd}
url = ${request-slave-frontend:connection-secure_access}/vnc.html?host=${request-slave-frontend:connection-domain}&port=${frontend-port:port}&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd}
{% if additional_frontend %}
url-additional = ${request-slave-frontend-additional:connection-secure_access}/vnc.html?host=${request-slave-frontend-additional:connection-domain}&port=${frontend-additional-port:port}&encrypt=1&password=${kvm-controller-parameter-dict:vnc-passwd}
{% endif %}
{% set disk_number = len(storage_dict) -%}
maximum-extra-disk-amount = {{ disk_number }}
{% set iface = 'ens3' -%}
......@@ -648,10 +702,14 @@ log = ${directory:public}/ansible/vm-bootstrap.log
[slap-parameter]
# Default values if not specified
frontend-software-type = frontend
frontend-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.92:/software/kvm/software.cfg
frontend-software-type = RootSoftwareInstance
frontend-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
frontend-instance-guid =
frontend-instance-name = VNC Frontend
frontend-instance-name = VNC Real Frontend
frontend-additional-software-type = RootSoftwareInstance
frontend-additional-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
frontend-additional-instance-guid =
frontend-additional-instance-name = VNC Real Frontend Additional
nbd-port = 1024
nbd-host =
nbd2-port = 1024
......@@ -763,6 +821,9 @@ parts =
cron-service
cron-entry-logrotate
frontend-promise
{% if additional_frontend %}
frontend-additional-promise
{% endif %}
# monitor parts
monitor-base
# Complete parts with sections
......
......@@ -13,7 +13,6 @@ default = $${:kvm}
kvm-cluster = $${dynamic-template-kvm-cluster:rendered}
kvm = $${dynamic-template-kvm:rendered}
nbd = ${template-nbd:output}
frontend = ${template-frontend:output}
kvm-resilient = $${dynamic-template-kvm-resilient:rendered}
kvm-import = $${dynamic-template-kvm-import:rendered}
......
......@@ -56,6 +56,7 @@ eggs =
collective.recipe.template
plone.recipe.command
${pycurl:egg}
collective.recipe.shelloutput
[http-proxy]
# https://github.com/nodejitsu/node-http-proxy
......@@ -146,10 +147,6 @@ mode = 0755
<= template-file-base
output = ${buildout:directory}/template-nbd.cfg
[template-frontend]
<= template-file-base
output = ${buildout:directory}/template-frontend.cfg
[template-ansible-promise]
<= download-template-base
filename = ansible-promise.in
......@@ -201,6 +198,7 @@ context =
websockify = 0.5.1
collective.recipe.environment = 0.2.0
collective.recipe.shelloutput = 0.1
gitdb = 0.6.4
pycurl = 7.43.0
slapos.recipe.template = 4.3
......
......@@ -25,12 +25,11 @@
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.kvm'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
......
......@@ -25,31 +25,22 @@
#
##############################################################################
import httplib
import json
import os
import shutil
import urlparse
import tempfile
import requests
import socket
import StringIO
import subprocess
import json
import slapos.util
import sqlite3
import urlparse
import utils
from slapos.recipe.librecipe import generateHashFromFiles
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
setUpModule, InstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class InstanceTestCase(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
class ServicesTestCase(InstanceTestCase):
......@@ -67,7 +58,7 @@ class ServicesTestCase(InstanceTestCase):
'websockify-{hash}-on-watch',
]
supervisor = self.getSupervisorRPCServer().supervisor
with self.slap.instance_supervisor_rpc as supervisor:
process_names = [process['name']
for process in supervisor.getAllProcessInfo()]
......@@ -79,3 +70,185 @@ class ServicesTestCase(InstanceTestCase):
expected_process_name = name.format(hash=h)
self.assertIn(expected_process_name, process_names)
class MonitorAccessMixin(object):
def sqlite3_connect(self):
sqlitedb_file = os.path.join(
os.path.abspath(
os.path.join(
self.slap.instance_directory, os.pardir
)
), 'var', 'proxy.db'
)
return sqlite3.connect(sqlitedb_file)
def get_all_instantiated_partition_list(self):
connection = self.sqlite3_connect()
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
connection.row_factory = dict_factory
cursor = connection.cursor()
cursor.execute(
"SELECT reference, xml, connection_xml, partition_reference, "
"software_release, requested_state, software_type "
"FROM partition14 "
"WHERE slap_state='busy'")
return cursor.fetchall()
def test_access_monitor(self):
connection_parameter_dict = self.computer_partition\
.getConnectionParameterDict()
monitor_setup_url = connection_parameter_dict['monitor-setup-url']
monitor_url_with_auth = 'https' + monitor_setup_url.split('https')[2]
auth = urlparse.parse_qs(urlparse.urlparse(monitor_url_with_auth).path)
# check that monitor-base-url for all partitions in the tree are accessible
# with published username and password
partition_with_monitor_base_url_count = 0
for partition_information in self.get_all_instantiated_partition_list():
connection_xml = partition_information.get('connection_xml')
if not connection_xml:
continue
connection_dict = slapos.util.xml2dict(
partition_information['connection_xml'].encode('utf-8'))
monitor_base_url = connection_dict.get('monitor-base-url')
if not monitor_base_url:
continue
result = requests.get(
monitor_base_url, verify=False, auth=(
auth['username'][0],
auth['password'][0])
)
self.assertEqual(
httplib.OK,
result.status_code
)
partition_with_monitor_base_url_count += 1
self.assertEqual(
self.expected_partition_with_monitor_base_url_count,
partition_with_monitor_base_url_count
)
class TestAccessDefault(MonitorAccessMixin, InstanceTestCase):
__partition_reference__ = 'ad'
expected_partition_with_monitor_base_url_count = 1
def test(self):
connection_parameter_dict = self.computer_partition\
.getConnectionParameterDict()
result = requests.get(connection_parameter_dict['url'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertTrue('<title>noVNC</title>' in result.text)
self.assertFalse('url-additional' in connection_parameter_dict)
class TestAccessDefaultAdditional(MonitorAccessMixin, InstanceTestCase):
__partition_reference__ = 'ada'
expected_partition_with_monitor_base_url_count = 1
@classmethod
def getInstanceParameterDict(cls):
return {
'frontend-additional-instance-guid': 'SOMETHING'
}
def test(self):
connection_parameter_dict = self.computer_partition\
.getConnectionParameterDict()
result = requests.get(connection_parameter_dict['url'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertTrue('<title>noVNC</title>' in result.text)
result = requests.get(
connection_parameter_dict['url-additional'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertTrue('<title>noVNC</title>' in result.text)
class TestAccessKvmCluster(MonitorAccessMixin, InstanceTestCase):
__partition_reference__ = 'akc'
expected_partition_with_monitor_base_url_count = 2
@classmethod
def getInstanceSoftwareType(cls):
return 'kvm-cluster'
@classmethod
def getInstanceParameterDict(cls):
return {'_': json.dumps({
"kvm-partition-dict": {
"KVM0": {
"disable-ansible-promise": True
}
}
})}
def test(self):
connection_parameter_dict = self.computer_partition\
.getConnectionParameterDict()
result = requests.get(connection_parameter_dict['kvm0-url'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertTrue('<title>noVNC</title>' in result.text)
self.assertFalse('kvm0-url-additional' in connection_parameter_dict)
class TestAccessKvmClusterAdditional(MonitorAccessMixin, InstanceTestCase):
__partition_reference__ = 'akca'
expected_partition_with_monitor_base_url_count = 2
@classmethod
def getInstanceSoftwareType(cls):
return 'kvm-cluster'
@classmethod
def getInstanceParameterDict(cls):
return {'_': json.dumps({
"frontend": {
'frontend-additional-instance-guid': 'SOMETHING',
},
"kvm-partition-dict": {
"KVM0": {
"disable-ansible-promise": True,
}
}
})}
def test(self):
connection_parameter_dict = self.computer_partition\
.getConnectionParameterDict()
result = requests.get(connection_parameter_dict['kvm0-url'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertTrue('<title>noVNC</title>' in result.text)
result = requests.get(
connection_parameter_dict['kvm0-url-additional'], verify=False)
self.assertEqual(
httplib.OK,
result.status_code
)
self.assertTrue('<title>noVNC</title>' in result.text)
This diff is collapsed.
......@@ -25,12 +25,11 @@
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.monitor'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
......
......@@ -26,33 +26,17 @@
##############################################################################
import os
import shutil
import urlparse
import tempfile
import requests
import socket
import StringIO
import subprocess
import json
import utils
from slapos.recipe.librecipe import generateHashFromFiles
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class InstanceTestCase(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
class ServicesTestCase(InstanceTestCase):
class ServicesTestCase(SlapOSInstanceTestCase):
def test_hashes(self):
hash_files = [
......@@ -63,7 +47,7 @@ class ServicesTestCase(InstanceTestCase):
'crond-{hash}-on-watch',
]
supervisor = self.getSupervisorRPCServer().supervisor
with self.slap.instance_supervisor_rpc as supervisor:
process_names = [process['name']
for process in supervisor.getAllProcessInfo()]
......
This diff is collapsed.
......@@ -31,35 +31,43 @@ import json
import glob
import re
import utils
from slapos.recipe.librecipe import generateHashFromFiles
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
def subprocess_status_output(*args, **kwargs):
prc = subprocess.Popen(
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
*args,
**kwargs)
out, err = prc.communicate()
return prc.returncode, out
setUpModule, InstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class InstanceTestCase(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
def getNextcloudConfig(self, config_dict={}):
class NextCloudTestCase(InstanceTestCase):
# calculated in setUp
partition_dir = None
nextcloud_path = None
def setUp(self):
# we want full diff when assertions fail
self.maxDiff = None
# lookup the partition in which nextcloud was installed
partition_path_list = glob.glob(os.path.join(
self.slap.instance_directory, '*'))
for partition_path in partition_path_list:
path = os.path.join(partition_path, 'srv/www')
if os.path.exists(path):
self.nextcloud_path = path
self.instance_folder = partition_path
break
self.assertTrue(
self.nextcloud_path,
"Nextcloud path not found in %r" % (partition_path_list,))
def getNextcloudConfig(self, config_dict={}):
data_dict = dict(
datadirectory=self.partition_dir + "/srv/data",
dbhost="%s:2099" % self.config['ipv4_address'],
dbhost="%s:2099" % self._ipv4_address,
dbname="nextcloud",
dbpassword="insecure",
dbport="",
......@@ -72,9 +80,9 @@ class InstanceTestCase(utils.SlapOSInstanceTestCase):
mail_smtpport="587",
mail_smtppassword="",
mail_smtpname="",
cli_url="https://[%s]:9988/" % self.config['ipv6_address'],
cli_url="https://[%s]:9988/" % self._ipv6_address,
partition_dir=self.partition_dir,
trusted_domain_list=json.dumps(["[%s]:9988" % self.config['ipv6_address']]),
trusted_domain_list=json.dumps(["[%s]:9988" % self._ipv6_address]),
trusted_proxy_list=[],
)
data_dict.update(config_dict)
......@@ -165,7 +173,7 @@ class InstanceTestCase(utils.SlapOSInstanceTestCase):
return json.loads(template % data_dict)
class ServicesTestCase(InstanceTestCase):
class TestServices(NextCloudTestCase):
def test_process_list(self):
hash_list = [
......@@ -185,7 +193,7 @@ class ServicesTestCase(InstanceTestCase):
'redis-on-watch',
]
supervisor = self.getSupervisorRPCServer().supervisor
with self.slap.instance_supervisor_rpc as supervisor:
process_name_list = [process['name']
for process in supervisor.getAllProcessInfo()]
......@@ -199,24 +207,16 @@ class ServicesTestCase(InstanceTestCase):
self.assertIn(expected_process_name, process_name_list)
def test_nextcloud_installation(self):
partition_path_list = glob.glob(os.path.join(self.instance_path, '*'))
nextcloud_path = None
for partition_path in partition_path_list:
path = os.path.join(partition_path, 'srv/www')
if os.path.exists(path):
nextcloud_path = path
instance_folder = partition_path
break
can_install_path = os.path.join(nextcloud_path, 'config/CAN_INSTALL')
can_install_path = os.path.join(self.nextcloud_path, 'config/CAN_INSTALL')
self.assertTrue(os.path.exists(nextcloud_path))
self.assertTrue(os.path.exists(self.nextcloud_path))
self.assertFalse(os.path.exists(can_install_path))
self.assertTrue(os.path.exists(os.path.join(nextcloud_path, 'config/config.php')))
self.assertTrue(os.path.exists(os.path.join(self.nextcloud_path, 'config/config.php')))
php_bin = os.path.join(instance_folder, 'bin/php')
php_bin = os.path.join(self.partition_dir, 'bin/php')
nextcloud_status = subprocess.check_output([
php_bin,
os.path.join(nextcloud_path, 'occ'),
os.path.join(self.nextcloud_path, 'occ'),
'status',
'--output',
'json'])
......@@ -224,22 +224,13 @@ class ServicesTestCase(InstanceTestCase):
self.assertTrue(json_status['installed'], True)
def test_nextcloud_config(self):
partition_path_list = glob.glob(os.path.join(self.instance_path, '*'))
nextcloud_path = None
for partition_path in partition_path_list:
path = os.path.join(partition_path, 'srv/www')
if os.path.exists(path):
nextcloud_path = path
instance_folder = partition_path
break
config_file = os.path.join(nextcloud_path, 'config/config.php')
php_script = os.path.join(instance_folder, 'test.php')
config_file = os.path.join(self.nextcloud_path, 'config/config.php')
php_script = os.path.join(self.partition_dir, 'test.php')
with open(php_script, 'w') as f:
f.write("<?php include('%s'); echo json_encode($CONFIG); ?>" % config_file)
self.partition_dir = instance_folder
php_bin = os.path.join(instance_folder, 'bin/php')
occ = os.path.join(nextcloud_path, 'occ')
php_bin = os.path.join(self.partition_dir, 'bin/php')
occ = os.path.join(self.nextcloud_path, 'occ')
config_result = subprocess.check_output([
php_bin,
'-f',
......@@ -277,7 +268,7 @@ class ServicesTestCase(InstanceTestCase):
"turn_servers"
])
self.assertEqual(turn_config.strip(), '[{"server":"","secret":"","protocols":"udp,tcp"}]')
news_config_file = os.path.join(instance_folder, 'srv/data/news/config/config.ini')
news_config_file = os.path.join(self.instance_folder, 'srv/data/news/config/config.ini')
with open(news_config_file) as f:
config = f.read()
regex = r"(useCronUpdates\s+=\s+false)"
......@@ -285,64 +276,8 @@ class ServicesTestCase(InstanceTestCase):
self.assertNotEqual(result, None)
def test_nextcloud_promises(self):
partition_path_list = glob.glob(os.path.join(self.instance_path, '*'))
nextcloud_path = None
for partition_path in partition_path_list:
path = os.path.join(partition_path, 'srv/www')
if os.path.exists(path):
nextcloud_path = path
instance_folder = partition_path
break
promise_path_list = glob.glob(os.path.join(instance_folder, 'etc/plugin/*.py'))
promise_name_list = [x for x in
os.listdir(os.path.join(instance_folder, 'etc/plugin'))
if not x.endswith('.pyc')]
partition_name = os.path.basename(instance_folder.rstrip('/'))
self.assertEqual(sorted(promise_name_list),
sorted([
"__init__.py",
"check-free-disk-space.py",
"monitor-http-frontend.py",
"apache-httpd-port-listening.py",
"buildout-%s-status.py" % partition_name,
"monitor-bootstrap-status.py",
"monitor-httpd-listening-on-tcp.py"
]))
ignored_plugin_list = [
'__init__.py',
'monitor-http-frontend.py',
]
runpromise_bin = os.path.join(
self.software_path, 'bin', 'monitor.runpromise')
monitor_conf = os.path.join(instance_folder, 'etc', 'monitor.conf')
msg = []
status = 0
for plugin_path in promise_path_list:
plugin_name = os.path.basename(plugin_path)
if plugin_name in ignored_plugin_list:
continue
plugin_status, plugin_result = subprocess_status_output([
runpromise_bin,
'-c', monitor_conf,
'--run-only', plugin_name,
'--force',
'--check-anomaly'
])
status += plugin_status
if plugin_status == 1:
msg.append(plugin_result)
# sanity check
if 'Checking promise %s' % plugin_name not in plugin_result:
plugin_status = 1
msg.append(plugin_result)
msg = ''.join(msg).strip()
self.assertEqual(status, 0, msg)
class ParametersTestCase(InstanceTestCase):
class TestNextCloudParameters(NextCloudTestCase):
@classmethod
def getInstanceParameterDict(cls):
return {
......@@ -365,22 +300,13 @@ class ParametersTestCase(InstanceTestCase):
}
def test_nextcloud_config_with_parameters(self):
partition_path_list = glob.glob(os.path.join(self.instance_path, '*'))
nextcloud_path = None
for partition_path in partition_path_list:
path = os.path.join(partition_path, 'srv/www')
if os.path.exists(path):
nextcloud_path = path
instance_folder = partition_path
break
config_file = os.path.join(nextcloud_path, 'config/config.php')
php_script = os.path.join(instance_folder, 'test.php')
config_file = os.path.join(self.nextcloud_path, 'config/config.php')
php_script = os.path.join(self.partition_dir, 'test.php')
with open(php_script, 'w') as f:
f.write("<?php include('%s'); echo json_encode($CONFIG); ?>" % config_file)
self.partition_dir = instance_folder
php_bin = os.path.join(instance_folder, 'bin/php')
occ = os.path.join(nextcloud_path, 'occ')
php_bin = os.path.join(self.partition_dir, 'bin/php')
occ = os.path.join(self.nextcloud_path, 'occ')
config_result = subprocess.check_output([
php_bin,
'-f',
......@@ -404,7 +330,7 @@ class ParametersTestCase(InstanceTestCase):
cli_url="nextcloud.example.com",
partition_dir=self.partition_dir,
trusted_domain_list=json.dumps([
"[%s]:9988" % self.config['ipv6_address'],
"[%s]:9988" % self._ipv6_address,
"nextcloud.example.com",
"nextcloud.proxy.com"
]),
......
This diff is collapsed.
......@@ -25,12 +25,11 @@
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.plantuml'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
......
......@@ -35,21 +35,13 @@ from PIL import Image
import requests
import plantuml
import utils
from slapos.recipe.librecipe import generateHashFromFiles
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
class PlantUMLTestCase(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
setUpModule, PlantUMLTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class TestSimpleDiagram(PlantUMLTestCase):
......@@ -165,7 +157,7 @@ class ServicesTestCase(PlantUMLTestCase):
'tomcat-instance-{hash}-on-watch',
]
supervisor = self.getSupervisorRPCServer().supervisor
with self.slap.instance_supervisor_rpc as supervisor:
process_names = [process['name']
for process in supervisor.getAllProcessInfo()]
......
This diff is collapsed.
......@@ -120,7 +120,7 @@ monitor-password = $${monitor-publish-parameters:monitor-password}
#####################
# Power DNS Slave configuration
#
{% set slave_instance_list = json_module.loads(slapparameter_dict.get('extra_slave_instance_list', '')) %}
{% set slave_instance_list = json_module.loads(slapparameter_dict.get('extra_slave_instance_list', '[]')) %}
# Iter through slave list to prepare configuration
{% for slave in slave_instance_list %}
......
......@@ -25,7 +25,7 @@ mode = 0644
[template-powerdns]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-powerdns.cfg
md5sum = 5077ba344b641fa9703f9872a974d3d7
md5sum = f0d87be6df84f23c811638ce9d5f60ea
output = ${buildout:directory}/template-powerdns.cfg
mode = 0644
......
......@@ -25,12 +25,11 @@
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.powerdns'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
......
......@@ -26,33 +26,22 @@
##############################################################################
import os
import shutil
import urlparse
import tempfile
import requests
import socket
import StringIO
import subprocess
import json
import utils
from slapos.recipe.librecipe import generateHashFromFiles
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class InstanceTestCase(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
class PowerDNSTestCase(SlapOSInstanceTestCase):
# power dns uses sockets and need shorter paths on test nodes.
__partition_reference__ = 'pdns'
class ServicesTestCase(InstanceTestCase):
class ServicesTestCase(PowerDNSTestCase):
def test_hashes(self):
hash_files = [
......@@ -62,7 +51,7 @@ class ServicesTestCase(InstanceTestCase):
'pdns-{hash}-on-watch',
]
supervisor = self.getSupervisorRPCServer().supervisor
with self.slap.instance_supervisor_rpc as supervisor:
process_names = [process['name']
for process in supervisor.getAllProcessInfo()]
......
This diff is collapsed.
......@@ -25,14 +25,14 @@
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.proftpd'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
setup(
name=name,
version=version,
description="Test for SlapOS' ProFTPd",
long_description=long_description,
......@@ -51,4 +51,4 @@ setup(name=name,
],
zip_safe=True,
test_suite='test',
)
)
......@@ -37,22 +37,15 @@ import psutil
from paramiko.ssh_exception import SSHException
from paramiko.ssh_exception import AuthenticationException
import utils
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
from slapos.testing.utils import findFreeTCPPort
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_DEBUG'):
import logging
logging.basicConfig(level=logging.DEBUG)
import unittest
unittest.installHandler()
class ProFTPdTestCase(utils.SlapOSInstanceTestCase):
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'software.cfg')), )
class ProFTPdTestCase(SlapOSInstanceTestCase):
def _getConnection(self, username=None, password=None, hostname=None):
"""Returns a pysftp connection connected to the SFTP
......@@ -77,7 +70,7 @@ class ProFTPdTestCase(utils.SlapOSInstanceTestCase):
class TestSFTPListen(ProFTPdTestCase):
def test_listen_on_ipv4(self):
self.assertTrue(self._getConnection(hostname=self.config['ipv4_address']))
self.assertTrue(self._getConnection(hostname=self._ipv4_address))
def test_does_not_listen_on_all_ip(self):
with self.assertRaises(SSHException):
......@@ -115,20 +108,22 @@ class TestSFTPOperations(ProFTPdTestCase):
# download the file again, it should have same content
tempdir = tempfile.mkdtemp()
self.addCleanup(lambda : shutil.rmtree(tempdir))
self.addCleanup(lambda: shutil.rmtree(tempdir))
local_file = os.path.join(tempdir, 'testfile')
retrieve_same_file = sftp.get('testfile', local_file)
sftp.get('testfile', local_file)
with open(local_file) as f:
self.assertEqual(f.read(), "Hello FTP !")
def test_uploaded_file_not_visible_until_fully_uploaded(self):
test_self = self
class PartialFile(StringIO.StringIO):
def read(self, *args):
# file is not visible yet
test_self.assertNotIn('destination', os.listdir(test_self.upload_dir))
# it's just a hidden file
test_self.assertEqual(['.in.destination.'], os.listdir(test_self.upload_dir))
test_self.assertEqual(
['.in.destination.'], os.listdir(test_self.upload_dir))
return StringIO.StringIO.read(self, *args)
with self._getConnection() as sftp:
......@@ -140,13 +135,16 @@ class TestSFTPOperations(ProFTPdTestCase):
def test_partial_upload_are_deleted(self):
test_self = self
with self._getConnection() as sftp:
class ErrorFile(StringIO.StringIO):
def read(self, *args):
# at this point, file is already created on server
test_self.assertEqual(['.in.destination.'], os.listdir(test_self.upload_dir))
test_self.assertEqual(
['.in.destination.'], os.listdir(test_self.upload_dir))
# simulate a connection closed
sftp.sftp_client.close()
return "something that will not be sent to server"
with self.assertRaises(IOError):
sftp.sftp_client.putfo(ErrorFile(), "destination")
# no half uploaded file is kept
......@@ -164,11 +162,13 @@ class TestSFTPOperations(ProFTPdTestCase):
class TestUserManagement(ProFTPdTestCase):
def test_user_can_be_added_from_script(self):
with self.assertRaisesRegexp(AuthenticationException, 'Authentication failed'):
with self.assertRaisesRegexp(AuthenticationException,
'Authentication failed'):
self._getConnection(username='bob', password='secret')
subprocess.check_call(
'echo secret | %s/bin/ftpasswd --name=bob --stdin' % self.computer_partition_root_path,
'echo secret | %s/bin/ftpasswd --name=bob --stdin' %
self.computer_partition_root_path,
shell=True)
self.assertTrue(self._getConnection(username='bob', password='secret'))
......@@ -177,7 +177,8 @@ class TestBan(ProFTPdTestCase):
def test_client_are_banned_after_5_wrong_passwords(self):
# Simulate failed 5 login attempts
for i in range(5):
with self.assertRaisesRegexp(AuthenticationException, 'Authentication failed'):
with self.assertRaisesRegexp(AuthenticationException,
'Authentication failed'):
self._getConnection(password='wrong')
# after that, even with a valid password we cannot connect
......@@ -185,8 +186,10 @@ class TestBan(ProFTPdTestCase):
self._getConnection()
# ban event is logged
with open(os.path.join(
self.computer_partition_root_path, 'var', 'log', 'proftpd-ban.log')) as ban_log_file:
with open(os.path.join(self.computer_partition_root_path,
'var',
'log',
'proftpd-ban.log')) as ban_log_file:
self.assertRegexpMatches(
ban_log_file.readlines()[-1],
'login from host .* denied due to host ban')
......@@ -195,7 +198,7 @@ class TestBan(ProFTPdTestCase):
class TestInstanceParameterPort(ProFTPdTestCase):
@classmethod
def getInstanceParameterDict(cls):
cls.free_port = utils.findFreeTCPPort(cls.config['ipv4_address'])
cls.free_port = findFreeTCPPort(cls._ipv4_address)
return {'port': cls.free_port}
def test_instance_parameter_port(self):
......@@ -211,7 +214,8 @@ class TestFilesAndSocketsInInstanceDir(ProFTPdTestCase):
def setUp(self):
"""sets `self.proftpdProcess` to `psutil.Process` for the running proftpd in the instance.
"""
all_process_info = self.getSupervisorRPCServer().supervisor.getAllProcessInfo()
with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo()
# there is only one process in this instance
process_info, = [p for p in all_process_info if p['name'] != 'watchdog']
process = psutil.Process(process_info['pid'])
......@@ -221,13 +225,15 @@ class TestFilesAndSocketsInInstanceDir(ProFTPdTestCase):
def test_only_write_file_in_instance_dir(self):
self.assertEqual(
[],
[f for f in self.proftpdProcess.open_files()
if f.mode != 'r'
if not f.path.startswith(self.computer_partition_root_path)])
[
f for f in self.proftpdProcess.open_files() if f.mode != 'r'
if not f.path.startswith(self.computer_partition_root_path)
])
def test_only_unix_socket_in_instance_dir(self):
self.assertEqual(
[],
[s for s in self.proftpdProcess.connections('unix')
if not s.laddr.startswith(self.computer_partition_root_path)])
[
s for s in self.proftpdProcess.connections('unix')
if not s.laddr.startswith(self.computer_partition_root_path)
])
This diff is collapsed.
......@@ -25,14 +25,14 @@
#
##############################################################################
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()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
setup(
name=name,
version=version,
description="Test for SlapOS' Re6stnet",
long_description=long_description,
......@@ -51,4 +51,4 @@ setup(name=name,
],
zip_safe=True,
test_suite='test',
)
)
......@@ -26,61 +26,40 @@
##############################################################################
import os
import shutil
import urlparse
import tempfile
import requests
import socket
import StringIO
import subprocess
import json
import utils
from slapos.recipe.librecipe import generateHashFromFiles
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
SLAPOS_TEST_IPV4 = os.environ['SLAPOS_TEST_IPV4']
SLAPOS_TEST_IPV6 = os.environ['SLAPOS_TEST_IPV6']
setUpModule, Re6stnetTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
# for development: debugging logs and install Ctrl+C handler
if os.environ.get('SLAPOS_TEST_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):
class TestPortRedirection(Re6stnetTestCase):
def test_portredir_config(self):
portredir_config_path = os.path.join(self.computer_partition_root_path, '.slapos-port-redirect')
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({
self.assertDictContainsSubset(
{
'srcPort': 9201,
'destPort': 9201,
}, portredir_config[0])
class ServicesTestCase(Re6stnetTestCase):
@classmethod
......@@ -95,12 +74,15 @@ class ServicesTestCase(Re6stnetTestCase):
'httpd-{hash}-on-watch',
]
supervisor = self.getSupervisorRPCServer().supervisor
process_names = [process['name']
for process in supervisor.getAllProcessInfo()]
with self.slap.instance_supervisor_rpc as supervisor:
process_names = [
process['name'] for process in supervisor.getAllProcessInfo()
]
hash_files = [os.path.join(self.computer_partition_root_path, path)
for path in hash_files]
hash_files = [
os.path.join(self.computer_partition_root_path, path)
for path in hash_files
]
for name in expected_process_names:
h = generateHashFromFiles(hash_files)
......
This diff is collapsed.
......@@ -28,9 +28,11 @@ from setuptools import setup, find_packages
version = '0.0.1.dev0'
name = 'slapos.test.seleniumserver'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
setup(
name=name,
version=version,
description="Test for SlapOS' Selenium Server",
long_description=long_description,
......@@ -52,4 +54,4 @@ setup(name=name,
],
zip_safe=True,
test_suite='test',
)
)
This diff is collapsed.
This diff is collapsed.
Tests for ERP5 software release
Tests for Slapos Master software release
......@@ -25,15 +25,24 @@
#
##############################################################################
import json
import os
import unittest
import logging
if os.environ.get('DEBUG'):
raise ValueError("Don't set DEBUG - it breaks postfix compilation - set SLAPOS_TEST_DEBUG instead.")
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
debug_mode = os.environ.get('SLAPOS_TEST_DEBUG')
# for development: debugging logs and install Ctrl+C handler
if debug_mode:
logging.basicConfig(level=logging.DEBUG)
unittest.installHandler()
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..', 'software.cfg')))
class ERP5InstanceTestCase(SlapOSInstanceTestCase):
"""ERP5 base test case
"""
# ERP5 instanciation needs to run several times before being ready, as
# the root instance request more instances.
instance_max_retry = 7 # XXX how many times ?
def getRootPartitionConnectionParameterDict(self):
"""Return the output paramters from the root partition"""
return json.loads(
self.computer_partition.getConnectionParameterDict()['_'])
......@@ -29,26 +29,15 @@ import os
import json
import glob
import urlparse
import logging
import socket
import time
import psutil
import requests
from utils import SlapOSInstanceTestCase
class ERP5TestCase(SlapOSInstanceTestCase):
"""Test the remote driver on a minimal web server.
"""
logger = logging.getLogger(__name__)
@classmethod
def getSoftwareURLList(cls):
return (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'software.cfg')), )
def getRootPartitionConnectionParameterDict(self):
"""Return the output paramters from the root partition"""
return json.loads(
self.computer_partition.getConnectionParameterDict()['_'])
from . import ERP5InstanceTestCase
from . import setUpModule
setUpModule # pyflakes
class TestPublishedURLIsReachableMixin(object):
......@@ -61,9 +50,10 @@ class TestPublishedURLIsReachableMixin(object):
# with 503 Service Unavailable.
# If we can move the "create site" in slapos node instance, then this retry loop
# would not be necessary.
for i in range(1, 20):
for i in range(1, 60):
r = requests.get(url, verify=False) # XXX can we get CA from caucase already ?
if r.status_code == requests.codes.service_unavailable:
if r.status_code in (requests.codes.service_unavailable,
requests.codes.not_found):
delay = i * 2
self.logger.warn("ERP5 was not available, sleeping for %ds and retrying", delay)
time.sleep(delay)
......@@ -89,13 +79,13 @@ class TestPublishedURLIsReachableMixin(object):
urlparse.urljoin(param_dict['family-default'], param_dict['site-id']))
class TestDefaultParameters(ERP5TestCase, TestPublishedURLIsReachableMixin):
class TestDefaultParameters(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 can be instanciated with no parameters
"""
__partition_reference__ = 'defp'
class TestDisableTestRunner(ERP5TestCase, TestPublishedURLIsReachableMixin):
class TestDisableTestRunner(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 can be instanciated without test runner.
"""
__partition_reference__ = 'distr'
......
This diff is collapsed.
......@@ -112,6 +112,7 @@ eggs =
${bcrypt:egg}
slapos.libnetworkcache
slapos.core
supervisor
${slapos.cookbook-setup:egg}
${slapos.test.caddy-frontend-setup:egg}
${slapos.test.erp5-setup:egg}
......@@ -128,12 +129,13 @@ eggs =
${slapos.test.nextcloud-setup:egg}
${slapos.test.turnserver-setup:egg}
${backports.lzma:egg}
entry-points =
runTestSuite=erp5.util.testsuite:runTestSuite
scripts =
runTestSuite
slapos
supervisorctl
supervisord
interpreter=
python_for_test
......
......@@ -15,5 +15,5 @@
[template]
filename = instance.cfg
md5sum = c7becd2a66b3305406f965b969907d52
md5sum = b48db2861644d9e9c30d2652c100d70e
......@@ -84,7 +84,7 @@ command-line =
# guarantee about free ports on IPV4 and IPV6
# * LOCAL_IPV4 is backward compatible, to be migrated, SLAPOS_TEST_IPV4
environment =
PATH=${coreutils:location}/bin:${curl:location}/bin:${openssl:location}/bin:${git:location}/bin:${libxslt:location}/bin:${socat:location}/bin:${lmsensors:location}/bin:/usr/bin/:/bin/
PATH=${coreutils:location}/bin:${curl:location}/bin:${openssl:location}/bin:${git:location}/bin:${libxslt:location}/bin:${socat:location}/bin:${lmsensors:location}/bin:${buildout:bin-directory}:/usr/bin/:/bin/
LOCAL_IPV4=$${slap-configuration:ipv4-random}
SLAPOS_TEST_IPV4=$${slap-configuration:ipv4-random}
SLAPOS_TEST_IPV6=$${slap-configuration:ipv6-random}
......
......@@ -114,10 +114,13 @@ eggs =
zope.testing
httmock
pyflakes
supervisor
entry-points =
runTestSuite=erp5.util.testsuite:runTestSuite
scripts =
runTestSuite
slapos
supervisord
interpreter=
python_for_test
......@@ -182,11 +185,14 @@ output = ${buildout:directory}/template.cfg
mode = 640
[versions]
Pygments = 2.1.3
slapos.recipe.template = 4.3
# clear version pins of tested eggs for which we want to generate scripts
# otherwise, the scripts will be generated for the pinned version.
slapos.core =
erp5.util =
# All depencies should be pinned.
Pygments = 2.1.3
slapos.recipe.template = 4.3
zc.lockfile = 1.4
bcrypt = 3.1.4
dnspython = 1.15.0
......
......@@ -25,12 +25,11 @@
#
##############################################################################
from setuptools import setup, find_packages
import glob
import os
version = '0.0.1.dev0'
name = 'slapos.test.slaprunner'
long_description = open("README.md").read()
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
......
This diff is collapsed.
This diff is collapsed.
# 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).
[instance-cfg]
filename = instance.cfg.in
md5sum = d027a2dccaf15ae6e7d3a28cc02d70c3
[template-turnserver]
filename = instance-turnserver.cfg.jinja2.in
md5sum = 6ba54fb299e1fd59617e5a6a9545e36e
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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