Commit eaaa854c authored by Nicolas Wavrant's avatar Nicolas Wavrant

slaprunner: test support of multiple software release

And the upgrade from one to another
parent 18cfae51
......@@ -292,3 +292,5 @@ testfixtures = 6.11
funcsigs = 1.0.2
PyPDF2 = 1.26.0
mysqlclient = 1.3.12
BeautifulSoup = 3.2.2
......@@ -41,6 +41,7 @@ setup(name=name,
url="https://lab.nexedi.com/nexedi/slapos",
packages=find_packages(),
install_requires=[
'BeautifulSoup',
'slapos.core',
'slapos.cookbook',
'slapos.libnetworkcache',
......
[buildout]
parts = instance
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[instance]
recipe = plone.recipe.command
command = echo -n 1 > $${buildout:directory}/version.txt
[buildout]
parts =
eggs
instance
extends =
../../../../stack/slapos.cfg
[eggs]
recipe = zc.recipe.egg
eggs =
plone.recipe.command
[instance]
recipe = slapos.recipe.template
filename = instance.cfg
url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/${:filename}
#md5sum = 869d5362b3daaa04db81129ce4f77c30
[versions]
slapos.recipe.template = 4.3
[buildout]
parts = instance
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[instance]
recipe = plone.recipe.command
command = echo -n 2 > $${buildout:directory}/version.txt
[buildout]
parts =
eggs
instance
extends =
../../../../stack/slapos.cfg
[eggs]
recipe = zc.recipe.egg
eggs =
plone.recipe.command
[instance]
recipe = slapos.recipe.template
filename = instance.cfg
url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/${:filename}
#md5sum = 869d5362b3daaa04db81129ce4f77c30
[versions]
slapos.recipe.template = 4.3
......@@ -25,13 +25,19 @@
#
##############################################################################
import os
import unittest
import paramiko
import contextlib
import base64
import contextlib
import hashlib
import json
import os
import paramiko
import requests
import subprocess
import time
import unittest
from lxml import etree
from lxml.html import soupparser
from six.moves.urllib.parse import urlparse
from six.moves.urllib.parse import quote
......@@ -315,3 +321,168 @@ class TestCustomFrontend(SlaprunnerTestCase):
self.assertEqual(
parameter_dict['custom-frontend-url'],
'https://www.erp5.com')
class TestSlapProxyIntegration(SlaprunnerTestCase):
instance_max_retry = 5
@classmethod
def getInstanceParameterDict(cls):
return {
'autorun': True,
'auto-deploy': True,
'slapos-repository': 'https://lab.nexedi.com/nexedi/slapos.git',
'slapos-reference': 'runner-multi-sr',
}
def setUp(self):
self.parameter_dict = parameter_dict = self.computer_partition.getConnectionParameterDict()
self.base_url = parameter_dict['url']
def _call(self, path, method="GET", data=None, assert_result_code=False):
resp = {
"GET": requests.get,
"POST": requests.post,
}[method](
"%s/%s" % (self.base_url, path),
verify=False,
auth=(self.parameter_dict['init-user'], self.parameter_dict['init-password']),
data=data
)
if assert_result_code:
try:
self.assertEqual(json.loads(resp.text)['code'], 1)
except ValueError:
raise ValueError("call to %s failed with HTTP code %s" % (
path, result.status_code
))
return resp
def _buildAndRun(self):
self.logger.debug('Running Build&Run')
self._call('runSoftwareProfile')
while True:
time.sleep(10)
try:
response = self._call('slapgridResult')
result = json.loads(response.text)
except ValueError:
raise ValueError("couldnt decode JSON result of call (code: %s) : %s" % (response.status_code, response.text))
self.logger.debug('%s', result)
# If software or instance is currently under process, wait
if result['software']['state'] or result['instance']['state']:
self.logger.debug('Currently doing Build&Run')
continue
if result['software']['success'] == 0:
if result['instance']['success'] == 0:
self.logger.debug('Instance is up!')
# Done
return
else:
self.logger.debug('Starting Run')
self._call('runInstanceProfile')
else:
self.logger.debug('Try to Build one more time')
self._call('runSoftwareProfile')
def test_upgrade_of_software_release(self):
"""
Test that 2 Software Releases can be built at the same time in a webrunner,
and that the instance can be moved from one to another.
Also check border cases, including :
* ordering a new SR won't delete the existing ones
* only SR correctly built can be chosen for the instance
* the SR in-use can't be deleted
"""
# 1: Request 2 Software Releases, and do build&run
result = self._call(
'supplySoftwareRelease',
method="POST",
data={"path": "workspace/slapos/software/slaprunner/test/software_v1/"},
assert_result_code=True,
)
result = self._call(
'supplySoftwareRelease',
method="POST",
data={"path": "workspace/slapos/software/slaprunner/test/software_v2/"},
assert_result_code=True,
)
self._buildAndRun()
# 2: Check that the Software Release of the instance is the 1st requested
result = self._call('inspectInstance')
root = soupparser.fromstring(result.text)
select_el = root.find(".//select[@name='software_release']")
self.assertEqual(
select_el.value_options,
[
'workspace/slapos/software/slaprunner/test/software_v1/software.cfg',
'workspace/slapos/software/slaprunner/test/software_v2/software.cfg',
]
)
result = self._call(
'getFileContent',
method="POST",
data={"file": "instance_root/slappart0/version.txt"},
assert_result_code=True,
)
self.assertEqual(json.loads(result.text)['result'], u'1')
# 3: Check that that only the unused Software Release can be deleted
delete_form_el, = root.findall(".//form[@action='/destroySoftwareRelease']")
self.assertEqual(
delete_form_el.fields['uri'],
'workspace/slapos/software/slaprunner/test/software_v2/software.cfg',
)
# 4: Request the instance with the 2nd Software Release, and check modification is registered
result = self._call(
'saveParameterXml',
method="POST",
data={
"software_release": "workspace/slapos/software/slaprunner/test/software_v2/software.cfg",
"software_type": "default",
"parameter": '<?xml version="1.0" encoding="utf-8"?>\n<instance>\n</instance>',
},
assert_result_code=True,
)
result = self._call('inspectInstance')
root = soupparser.fromstring(result.text)
select_el = root.find(".//select[@name='software_release']")
self.assertEqual(select_el.value_options[0], "workspace/slapos/software/slaprunner/test/software_v2/software.cfg")
# 5: Do build&run, and check that the instance was updated with the profile of the 2nd Software Release
self._buildAndRun()
result = self._call(
'getFileContent',
method="POST",
data={"file": "instance_root/slappart0/version.txt"},
assert_result_code=True,
)
self.assertEqual(json.loads(result.text)['result'], u'2')
# 6: Check that that only the first Software Release can be deleted, and delete it
delete_form_el, = root.findall(".//form[@action='/destroySoftwareRelease']")
self.assertEqual(
delete_form_el.fields['uri'],
'workspace/slapos/software/slaprunner/test/software_v1/software.cfg',
)
self._call('destroySoftwareRelease', method="POST", data={
"uri": "workspace/slapos/software/slaprunner/test/software_v1/software.cfg"
})
# 7: Check that the first Software Release can't be chosen anymore
# for the instance, neither is shown as deletable
result = self._call('inspectInstance')
root = soupparser.fromstring(result.text)
select_el = root.find(".//select[@name='software_release']")
self.assertEqual(
select_el.value_options,
[
'workspace/slapos/software/slaprunner/test/software_v2/software.cfg',
]
)
self.assertTrue(
len(root.findall(".//form[@action='/destroySoftwareRelease']")) == 0
)
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