Commit 49d511f4 authored by Nirina Malard's avatar Nirina Malard

software/html5as:update front tutorial

parent b63c96b0
# To learn more about how to generate this file read
# To learn more about how to generate this file read
# ../../README.update-hash.rst
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
......@@ -15,13 +16,14 @@
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[template-cfg]
filename = instance.cfg.in
md5sum = 23c15a579b66cef866b30a2f53b1b737
md5sum = 9e486efe4ab1aba8cb72b04f6c6da8ad
[instance_html5as]
_update_hash_filename_ = instance_html5as.cfg.in
md5sum = d1b5747c064a752d7a6b09060604aa0a
md5sum = f8d1777c43b173a900cfbdf104dec990
[template_nginx_conf]
_update_hash_filename_ = templates/nginx_conf.in
......@@ -45,4 +47,4 @@ md5sum = 1c0ee16966e1fcdb3fd11c09f12ee2b2
[template_instance_replicate]
_update_hash_filename_ = instance_replicate.cfg.in
md5sum = d7071867625070c27dbd6456c761f9f0
md5sum = 7ff7e11d05145115f53564ec1af205ef
......@@ -10,7 +10,7 @@ offline = true
nginx_location = {{ nginx_location }}
dash_location = {{ dash_location }}
template_nginx_conf = {{ template_nginx_conf_target }}
template_mime_types = {{ template_mime_types_target }}
template_mime_types = {{ template_mime_types_target }}
template_launcher = {{ template_launcher_target }}
template_index_html = {{ template_index_html_target }}
template_graceful = {{ template_graceful_target }}
......@@ -37,6 +37,7 @@ default-parameters =
"monitor-httpd-port": 8197
}
[instance-replicate]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
......@@ -48,6 +49,7 @@ context =
section parameter_list profile-common
key slapparameter_dict slap-configuration:configuration
jsonkey default_parameter_dict :default-parameters
# User can specify parameter for any of the two instances
default-parameters =
{
"download_url": null,
......@@ -60,8 +62,9 @@ RootSoftwareInstance = ${:default}
default = instance-html5as:output
replicate = instance-replicate:output
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
recipe = slapos.cookbook:slapconfiguration
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
......
......@@ -90,7 +90,7 @@ path_access_log = ${basedirectory:log}/nginx.access.log
path_error_log = ${basedirectory:log}/nginx.error.log
path_tmp = ${tempdirectory:tmp}
# Docroot
docroot = ${docroot:location}
docroot = ${downloader:location}
default_index = ${:docroot}/index.html
# Config files
path_nginx_conf = ${directory:etc}/nginx.conf
......@@ -98,9 +98,11 @@ path_mime_types = ${directory:etc}/mime_types
# Binaries
path_shell = {{ parameter_list['dash_location'] }}/bin/dash
# Executables
bin_launcher = ${basedirectory:service}/launcher
# Utils
path_nginx = {{ parameter_list['nginx_location'] }}/sbin/nginx
......@@ -127,44 +129,51 @@ output = ${html5as:bin_launcher}
context =
section param_html5as html5as
# Command to download archive from provided url
[downloader]
recipe = slapos.recipe.build:download
# We add: or '', otherwise jinja2 will render a 'None' string
url = {{ parameter_dict['download_url'] or '' }}
# Allow to use slapos.recipe.build:download which can only be used in "online" mode
offline = false
# Command to put content in the docroot
[docroot]
[downloader]
recipe = slapos.recipe.build
# Path where the recipe stores any produced file,
# it will be automatically removed at the beginning of "install".
location = ${directory:srv}/html5as
# All the keys in this section will be available as a dict called "self.options"
archive = {{ '${downloader:target}' if parameter_dict['download_url'] else '' }}
default_index_html = ${default_index_html:output}
# We add: or '', otherwise jinja2 will render a 'None' string
url = {{ parameter_dict['download_url'] or '' }}
default_index_html = ${default_index_html:rendered}
# If a tarball is passed as a parameter in download url
# it's content will be served by the instance.
# If the parameter is not provided it fallback to the default template
install =
import os, shutil
if self.options['archive']:
# Create a directory and extract the file that are compressed inside
extract_dir = self.extract(self.options['archive'])
# Return the right directory path
workdir = guessworkdir(extract_dir)
# Recursively copy directory
self.copyTree(workdir, location)
else:
# Create directory and copy the default template inside
os.makedirs(location)
shutil.copy(self.options['default_index_html'], location)
buildout_offline = self.buildout['buildout']['offline']
try:
# Allow to do self.download() which can only be used in "online" mode
self.buildout['buildout']['offline'] = 'false'
if self.options['url']:
# Use fonctions from the slapos.recipe.build repository
# Download a file from a URL to a temporary path
file = self.download(self.options['url'])
# Create a directory and extract the file that are compressed inside
extract_dir = self.extract(file)
# Return the right directory path
workdir = guessworkdir(extract_dir)
# Recursively copy directory
self.copyTree(workdir, location)
else:
# Create directory and copy the default template inside
os.makedirs(location)
shutil.copy(self.options['default_index_html'], location)
finally:
# reset the parameter
self.buildout['buildout']['offline'] = buildout_offline
[downloader]
recipe = plone.recipe.command
command = rm -r ${html5as:docroot}/*; cp ${default_index_html:rendered} ${html5as:docroot}/
[default_index_html]
recipe = slapos.recipe.template:jinja2
url = {{ parameter_list['template_index_html'] }}
output = ${directory:srv}/index.html
template = {{ parameter_list['template_index_html'] }}
rendered = ${directory:srv}/index.html
title = {{ parameter_dict['title'] }}
context =
key title :title
......@@ -172,8 +181,8 @@ context =
### Nginx Graceful
[nginx-graceful]
recipe = slapos.recipe.template:jinja2
url = {{ parameter_list['template_graceful'] }}
output = ${basedirectory:script}/nginx-graceful
template = {{ parameter_list['template_graceful'] }}
rendered = ${basedirectory:script}/nginx-graceful
context =
section param_html5as html5as
......@@ -201,7 +210,7 @@ post = kill -USR1 $(cat ${html5as:path_pid})
# Publish nginx address
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
recipe = slapos.cookbook:publish
# By extending monitor publish, all the section deploying monitoring will
# be deployed. The parameters needed for accessing monitoring will be published
<= monitor-publish
......@@ -211,6 +220,8 @@ title = Title {{ parameter_dict['title'] }}!
# and there is no need to declare the new part in buildout:parts
server-cdn-url = ${html5as-frontend-promise:url}
# Request a CDN entry to master
[html5as-frontend]
# Extend slap-connnection to get the credentials for the request
......@@ -234,3 +245,4 @@ promise = check_url_available
name = html5as-http-frontend.py
url = ${html5as-frontend:connection-secure_access}
config-url = ${:url}
config-check-secure = 1
......@@ -7,7 +7,6 @@
{%- do parameter_dict.setdefault("monitor-httpd-port-%d" % i, 8197 + i) %}
{%- endfor %}
# Standard buildout section
[buildout]
parts =
publish-connection-information
......@@ -23,7 +22,7 @@ offline = true
# Macro section sharing request parameters
[instance-request-base]
<= slap-connection
recipe = slapos.cookbook:request.serialised
recipe = slapos.cookbook:request
# It is the same software as the current one
software-url = ${slap-connection:software-release-url}
# We want the default behaviour
......@@ -34,6 +33,9 @@ return = server_url server-cdn-url monitor-setup-url
# We add: or '', otherwise jinja2 will render a 'None' string
config-download_url = {{ parameter_dict['download_url'] or '' }}
# Create request section in a loop.
{% for i in range(1, replicate_quantity + 1) %}
# Request a normal html5as instance
......@@ -49,9 +51,10 @@ sla-computer_guid = {{ parameter_dict["sla-%s-computer-guid" % i] }}
{% endif -%}
{% endfor %}
# Publish information to connect to the two instances
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
recipe = slapos.cookbook:publish
{% for i in range(1, replicate_quantity + 1) %}
instance-{{ i }}-server_url = ${instance-{{ i }}:connection-server_url}
instance-{{ i }}-server-cdn-url = ${instance-{{ i }}:connection-server-cdn-url}
......
[buildout]
extends =
# buildout.hash.cfg is used for automated hash calculation of managed
# instance files by calling update-hash
buildout.hash.cfg
# "slapos" stack describes basic things needed for 99.9% of SlapOS Software
# Releases
../../stack/slapos.cfg
# Extend monitoring stack to provide necessary tools for monitoring
../../stack/monitor/buildout.cfg
# Extend here component profiles, like openssl, apache, mariadb, curl...
# Or/and extend a stack (lamp, tomcat) that does most of the work for you
......@@ -14,6 +11,8 @@ extends =
../../component/nginx/buildout.cfg
../../component/dash/buildout.cfg
parts =
# Call installation of slapos.cookbook egg defined in stack/slapos.cfg (needed
# in 99,9% of Slapos Software Releases)
......@@ -21,6 +20,8 @@ parts =
# Call creation of instance.cfg file that will be called for deployment of
# instance
template-cfg
# Add extra egg
extra-eggs
# Download instance.cfg.in (buildout profile used to deployment of instance),
# replace all {{ foo_bar }} parameters by real values
......@@ -29,6 +30,7 @@ parts =
recipe = slapos.recipe.template:jinja2
output = ${buildout:directory}/template.cfg
url = ${:_profile_base_location_}/${:filename}
filename = instance.cfg.in
context =
section buildout buildout
key nginx_location nginx:location
......@@ -40,21 +42,15 @@ context =
key template_index_html_target template_index_html:target
key template_graceful_target template_graceful:target
key template_instance_replicate template_instance_replicate:target
# Monitor stack also provides a template for the instance
key template_monitor monitor2-template:output
# Have one shared section to define the default behaviour to download
# templates. Sections inheriting from this one won't need to redefine
# shared parameters
[download-base]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_update_hash_filename_}
# Download instance_html5as.cfg.in
[instance_html5as]
# This section inherit from download-base
<= download-base
# Filename and md5sum is defined in buildout.hash.cfg
[template_nginx_conf]
<= download-base
......@@ -65,6 +61,7 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[template_mime_types]
<= download-base
[template_index_html]
<= download-base
......@@ -73,3 +70,9 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[template_instance_replicate]
<= download-base
[extra-eggs]
recipe = zc.recipe.egg
eggs =
plone.recipe.command
Tests for html5as software release
Tests for html5as-base software release
......@@ -27,14 +27,14 @@
from setuptools import setup, find_packages
version = '0.0.1.dev0'
name = 'slapos.test.html5as'
name = 'slapos.test.html5asbase'
with open("README.md") as f:
long_description = f.read()
setup(
name=name,
version=version,
description="Test for SlapOS' HTML5AS",
description="Test for SlapOS' HTML5AS Base",
long_description=long_description,
long_description_content_type='text/markdown',
maintainer="Nexedi",
......
......@@ -25,28 +25,25 @@
#
##############################################################################
import json
import os
import requests
from urllib.parse import urlparse
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
setUpModule, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class HTML5ASTestCase(SlapOSInstanceTestCase):
class HTML5ASBaseTestCase(SlapOSInstanceTestCase):
"""
Common class for testing html5as.
Common class for testing html5as base.
It inherit from SlapOSInstanceTestCase which:
* Install the software release.
* Checks it compile without issue.
* Deploy the instance
* Check deployment works and promise pass
For testing the deployment a different testing class will need to be set up
* Check deployement works and promise pass
For testing the deployement a different testing class will need to be set up
per each variation of parameters the instance needs to be given.
"""
......@@ -59,140 +56,16 @@ class HTML5ASTestCase(SlapOSInstanceTestCase):
return response
class TestEmptyDeploy(HTML5ASTestCase):
class TestEmptyDeploy(HTML5ASBaseTestCase):
"""
This class test the instance with no parameters.
"""
def test_deploy_with_no_paramater(self):
url = json.loads(self.computer_partition.getConnectionParameterDict()['_'])['server_url']
response = self.checkUrlAndGetResponse(url)
result = response.text
self.assertNotIn("<h1>", result)
self.assertIn("<p>Hello World</p>", result)
class TestDeployWithTitle(HTML5ASTestCase):
"""
This class test an instance with the parameter "title"
"""
@classmethod
def getInstanceParameterDict(cls):
return {
'_': json.dumps(
{
'title': 'Test1',
}
)
}
def test_deploy_with_title_parameter(self):
connection_parameter_dict = json.loads(self.computer_partition.getConnectionParameterDict()['_'])
self.assertEqual(connection_parameter_dict["title"], "Title Test1!")
url = connection_parameter_dict['server_url']
response = self.checkUrlAndGetResponse(url)
result = response.text
self.assertIn("<h1>Test1</h1>", result)
self.assertIn("<p>Hello World</p>", result)
class TestGracefulWithPortChange(HTML5ASTestCase):
"""
This class test the instance with the parameter "port"
"""
instance_parameter_dict = {
'_': json.dumps({
'port': 8087
})
}
@classmethod
def getInstanceParameterDict(cls):
return cls.instance_parameter_dict
def test_change_port_parameter(self):
"""
This test test port change and its application with graceful restart
Get the connection URL and check it is accessible
"""
# Check initial connection parameter match expected port
url = json.loads(self.computer_partition.getConnectionParameterDict()['_'])['server_url']
self.assertEqual(urlparse(url).port, 8087)
# Check port is listening even thought it is duplicated with the promise:
# "port-listening-promise"
self.checkUrlAndGetResponse(url)
# Update port parameter
self.instance_parameter_dict['_'] = json.dumps({
'port': 8086
})
# Request instance with the new port parameter
self.requestDefaultInstance()
# Reprocess the instance to apply new port and run promises
self.slap.waitForInstance(self.instance_max_retry)
# Re-request instance to get update connection parameter
url = json.loads(self.requestDefaultInstance().getConnectionParameterDict()['_'])['server_url']
# Make sure the new port is the one being used
self.assertEqual(urlparse(url).port, 8086)
# Check port is listening even thought it is duplicated with the promise:
# "port-listening-promise"
self.checkUrlAndGetResponse(url)
class TestReplicateHTML5AS(HTML5ASTestCase):
"""
This class test the instance with the parameter "port"
"""
instance_parameter_dict = {
'_': json.dumps({
"port-1": 8088,
"title-1": "Title 1",
})
}
@classmethod
def getInstanceSoftwareType(cls):
return 'replicate'
@classmethod
def getInstanceParameterDict(cls):
return cls.instance_parameter_dict
def test_replicate_instance(self):
# Check First instance is deployed with proper parameters
connection_parameter_dict = json.loads(self.computer_partition.getConnectionParameterDict()['_'])
url = connection_parameter_dict['instance-1-server_url']
self.assertEqual(urlparse(url).port, 8088)
response = self.checkUrlAndGetResponse(url)
result = response.text
self.assertIn("<h1>Title 1</h1>", result)
# Check only one instance is deployed by default
self.assertNotIn("instance-2-server_url", connection_parameter_dict)
# Update replicate quantity parameter
self.instance_parameter_dict['_'] = json.dumps(
dict(
json.loads(self.instance_parameter_dict['_']),
**{
'replicate-quantity': 2,
'port-2': 8089,
'sla-2-computer_guid': self.slap._computer_id,
"title-2": "Title 314",
}
)
)
# Request instance with the one more replicate
self.requestDefaultInstance()
self.slap.waitForInstance(self.instance_max_retry)
# Check the second replicate
connection_parameter_dict = json.loads(self.requestDefaultInstance().getConnectionParameterDict()['_'])
url = connection_parameter_dict['instance-2-server_url']
self.assertEqual(urlparse(url).port, 8089)
url = self.requestDefaultInstance().getConnectionParameterDict()['server_url']
response = self.checkUrlAndGetResponse(url)
result = response.text
self.assertIn("<h1>Title 314</h1>", result)
self.assertEqual("Hello World!\n", result)
\ No newline at end of file
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