Commit e190bda9 authored by Xavier Thompson's avatar Xavier Thompson

software/jupyter: fix parameters

See merge request nexedi/slapos!892
parents 1b38f8df 1b4653ad
Pipeline #13756 failed with stage
...@@ -19,7 +19,7 @@ md5sum = de37ec3d4adb0be4c67bcc7397f27c91 ...@@ -19,7 +19,7 @@ md5sum = de37ec3d4adb0be4c67bcc7397f27c91
[instance-jupyter] [instance-jupyter]
filename = instance-jupyter.cfg.in filename = instance-jupyter.cfg.in
md5sum = 9340498841caa5771f40f8c9e561eacd md5sum = cbc90e517ae3680ab8bef04c6f503af5
[jupyter-notebook-config] [jupyter-notebook-config]
filename = jupyter_notebook_config.py.jinja filename = jupyter_notebook_config.py.jinja
......
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Parameters to instantiate Jupyter",
"properties": {
"frontend-instance-guid": {
"title": "Frontend Instance ID",
"description": "Unique identifier of the frontend instance, like \"SOFTINST-11031\".",
"type": "string"
},
"frontend-software-type": {
"title": "Frontend Software Type",
"description": "Type of the frontend instance, like \"frontend\".",
"type": "string",
"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": "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"
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Connection parameters for the Jupyter Notebook",
"properties": {
"url": {
"description": "Jupyter Notebook URL",
"type": "string"
},
"jupyterlab-url": {
"description": "JupyterLab URL",
"type": "string"
},
"password": {
"description": "Password",
"type": "string"
}
}
}
...@@ -51,6 +51,10 @@ frontend-additional-software-url = http://git.erp5.org/gitweb/slapos.git/blob_pl ...@@ -51,6 +51,10 @@ frontend-additional-software-url = http://git.erp5.org/gitweb/slapos.git/blob_pl
frontend-additional-instance-guid = frontend-additional-instance-guid =
frontend-additional-instance-name = Jupyter Frontend Additional frontend-additional-instance-name = Jupyter Frontend Additional
{% for k, v in slapparameter_dict.items() -%}
{{ k }} = {{ v }}
{% endfor -%}
[dynamic-jinja2-template-base] [dynamic-jinja2-template-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
mode = 0644 mode = 0644
...@@ -171,7 +175,7 @@ instance-configuration = ...@@ -171,7 +175,7 @@ instance-configuration =
raw jupyter-password ${jupyter-password:passwd} raw jupyter-password ${jupyter-password:passwd}
[publish-connection-parameter] [publish-connection-parameter]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish
jupyter-classic-url = ${request-slave-frontend:connection-secure_access}/tree jupyter-classic-url = ${request-slave-frontend:connection-secure_access}/tree
url = ${:jupyter-classic-url} url = ${:jupyter-classic-url}
jupyterlab-url = ${request-slave-frontend:connection-secure_access}/lab jupyterlab-url = ${request-slave-frontend:connection-secure_access}/lab
......
{
"name": "Jupyter",
"description": "Jupyter Notebook",
"serialisation": "json-in-xml",
"software-type": {
"default": {
"title": "Default",
"software-type": "default",
"description": "Default",
"request": "instance-jupyter-input-schema.json",
"response": "instance-jupyter-ouput-schema.json",
"index": 1
}
}
}
...@@ -30,6 +30,8 @@ import http.client ...@@ -30,6 +30,8 @@ import http.client
import json import json
import os import os
import requests import requests
import sqlite3
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
...@@ -41,12 +43,7 @@ setUpModule, InstanceTestCase = makeModuleSetUpAndTestCaseClass( ...@@ -41,12 +43,7 @@ setUpModule, InstanceTestCase = makeModuleSetUpAndTestCaseClass(
class TestJupyter(InstanceTestCase): class TestJupyter(InstanceTestCase):
def test(self): def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict() connection_dict = self.computer_partition.getConnectionParameterDict()
self.assertTrue('_' in parameter_dict)
try:
connection_dict = json.loads(parameter_dict['_'])
except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
self.assertTrue('password' in connection_dict) self.assertTrue('password' in connection_dict)
password = connection_dict['password'] password = connection_dict['password']
...@@ -85,29 +82,6 @@ class TestJupyter(InstanceTestCase): ...@@ -85,29 +82,6 @@ class TestJupyter(InstanceTestCase):
) )
class TestJupyterPassword(InstanceTestCase):
def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
self.assertTrue('_' in parameter_dict)
try:
connection_dict = json.loads(parameter_dict['_'])
except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
url = connection_dict['url']
with requests.Session() as s:
resp = s.get(url, verify=False)
result = s.post(
resp.url,
verify = False,
data={"_xsrf": s.cookies["_xsrf"], "password": connection_dict['password']}
)
self.assertEqual(
[http.client.OK, url],
[result.status_code, result.url]
)
class TestJupyterAdditional(InstanceTestCase): class TestJupyterAdditional(InstanceTestCase):
@classmethod @classmethod
...@@ -117,12 +91,7 @@ class TestJupyterAdditional(InstanceTestCase): ...@@ -117,12 +91,7 @@ class TestJupyterAdditional(InstanceTestCase):
} }
def test(self): def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict() connection_dict = self.computer_partition.getConnectionParameterDict()
self.assertTrue('_' in parameter_dict)
try:
connection_dict = json.loads(parameter_dict['_'])
except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
result = requests.get( result = requests.get(
connection_dict['url'], verify=False, allow_redirects=False) connection_dict['url'], verify=False, allow_redirects=False)
...@@ -169,3 +138,139 @@ class TestJupyterAdditional(InstanceTestCase): ...@@ -169,3 +138,139 @@ class TestJupyterAdditional(InstanceTestCase):
[http.client.FOUND, True, '/login?next=%2Flab'], [http.client.FOUND, True, '/login?next=%2Flab'],
[result.status_code, result.is_redirect, result.headers['Location']] [result.status_code, result.is_redirect, result.headers['Location']]
) )
class TestJupyterPassword(InstanceTestCase):
def test(self):
connection_dict = self.computer_partition.getConnectionParameterDict()
url = connection_dict['url']
with requests.Session() as s:
resp = s.get(url, verify=False)
result = s.post(
resp.url,
verify = False,
data={"_xsrf": s.cookies["_xsrf"], "password": connection_dict['password']}
)
self.assertEqual(
[http.client.OK, url],
[result.status_code, result.url]
)
class SelectMixin(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 select(self, fields, table, where={}):
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()
condition = " AND ".join("%s='%s'" % (k, v) for k, v in where.items())
cursor.execute(
"SELECT %s FROM %s%s"
% (
", ".join(fields),
table,
" WHERE %s" % condition if where else "",
)
)
return cursor.fetchall()
class TestJupyterCustomFrontend(SelectMixin, InstanceTestCase):
instance_parameter_dict = {}
frontend_software_url = 'hello://frontend.url'
frontend_software_type = 'hello-type'
frontend_instance_name = 'Hello Frontend'
@classmethod
def getInstanceParameterDict(cls):
return cls.instance_parameter_dict
def test(self):
# create a fake master instance for the frontend slave request
r = self.slap.request(
software_release=self.frontend_software_url,
software_type=self.frontend_software_type,
partition_reference= "Fake master instance",
)
# update the request parameters of the test instance
self.instance_parameter_dict.update({
'frontend-software-url': self.frontend_software_url,
'frontend-software-type': self.frontend_software_type,
'frontend-instance-name': self.frontend_instance_name,
'frontend-instance-guid': r._partition_id,
})
self.requestDefaultInstance()
# wait for the instance to converge to the new state
try:
self.slap.waitForInstance()
except Exception:
pass
selection = self.select(fields=["*"], table = "slave14", where = {"hosted_by": r._partition_id})
self.assertEqual(len(selection), 1)
# clean up the fake master
r.destroyed()
class TestJupyterCustomAdditional(SelectMixin, InstanceTestCase):
instance_parameter_dict = {}
frontend_additional_software_url = 'hello://frontend.url'
frontend_additional_software_type = 'hello-type'
frontend_additional_instance_name = 'Hello Frontend'
@classmethod
def getInstanceParameterDict(cls):
return cls.instance_parameter_dict
def test(self):
# create a fake master instance for the frontend slave request
r = self.slap.request(
software_release=self.frontend_additional_software_url,
software_type=self.frontend_additional_software_type,
partition_reference= "Fake master instance",
)
# update the request parameters of the test instance
self.instance_parameter_dict.update({
'frontend-additional-software-url': self.frontend_additional_software_url,
'frontend-additional-software-type': self.frontend_additional_software_type,
'frontend-additional-instance-name': self.frontend_additional_instance_name,
'frontend-additional-instance-guid': r._partition_id,
})
self.requestDefaultInstance()
# wait for the instance to converge to the new state
try:
self.slap.waitForInstance()
except Exception:
pass
selection = self.select(fields=["*"], table = "slave14", where = {"hosted_by": r._partition_id})
self.assertEqual(len(selection), 1)
# clean up the fake master
r.destroyed()
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