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