Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion modules/app-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
"mime-types": "^2.1.35",
"moment": "^2.30.1",
"rxjs": "^7.8.1",
"sepal": "../../lib/js/shared"
"sepal": "../../lib/js/shared",
"koa-static" :"^5.0.0"


},
"devDependencies": {
},
Expand Down
34 changes: 34 additions & 0 deletions modules/app-manager/src/labextensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const fs = require('fs')
const koaStatic = require('koa-static')
const path = require('path')

function getLabextensionsDir(appName) {
const baseDir = '/usr/local/share/jupyter/current-kernels'
return path.join(baseDir, `venv-${appName}`, 'venv/share/jupyter/labextensions')
}

const staticLabextensionsMiddleware = async (ctx, next) => {

const {app_name} = ctx.params
const labextensionsDir = getLabextensionsDir(app_name)

if (!fs.existsSync(labextensionsDir)) {

ctx.throw(404, `Labextensions directory for app '${app_name}' not found`)
return
}
// Extract the original path requested
const originalPath = ctx.path
const relativePath = originalPath.split(`/labextensions/${app_name}`)[1] || '/'

if (relativePath.includes('..')) {
ctx.throw(400, 'Invalid path')
return
}

ctx.path = relativePath

return koaStatic(labextensionsDir)(ctx, next)
}

module.exports = {staticLabextensionsMiddleware}
2 changes: 2 additions & 0 deletions modules/app-manager/src/routes.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const {sendFile, sendFileNoCache} = require('./sendFile')
const {staticLabextensionsMiddleware} = require('./labextensions')

module.exports = router =>
router
.get('/list', ctx => sendFileNoCache(ctx, '/var/lib/sepal/app-manager/apps.json'))
.get('/images/:filename', ctx => sendFile(ctx, `/var/lib/sepal/app-manager/images/${ctx.params.filename}`))
.get('/labextensions/:app_name/(.*)', staticLabextensionsMiddleware)
2 changes: 2 additions & 0 deletions modules/sandbox/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ RUN chmod u+x /script/init_clojure.sh && sync && /script/init_clojure.sh

ENV USER=sepal-user

ADD modules/${MODULE_NAME}/script/voila.py /usr/local/etc/jupyter/

CMD ["/script/init_container.sh"]
10 changes: 1 addition & 9 deletions modules/sandbox/script/init_jupyter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,4 @@ git clone https://github.com/ipython-contrib/jupyter_contrib_nbextensions.git
/usr/bin/python3 /usr/local/bin/jupyter nbextensions_configurator enable
/usr/bin/python3 /usr/local/bin/jupyter nbextension enable --py --sys-prefix widgetsnbextension

/usr/bin/python3 -m pip install voila # https://github.com/trungleduc/ipecharts/issues/5
/usr/bin/python3 /usr/local/bin/jupyter nbextension install voila --sys-prefix --py
/usr/bin/python3 /usr/local/bin/jupyter nbextension enable voila --sys-prefix --py
/usr/bin/python3 /usr/local/bin/jupyter serverextension enable voila --sys-prefix

# [HACK] Manually installing de-indent, otherwise jupyter lab build fails.
/usr/bin/python3 /usr/local/bin/jupyter lab build || npm install --prefix /usr/local/share/jupyter/lab/staging de-indent
rm -f /usr/local/share/jupyter/lab/staging/package-lock.json /usr/local/share/jupyter/lab/staging/yarn.lock
/usr/bin/python3 /usr/local/bin/jupyter lab build
/usr/bin/python3 -m pip install "git+https://github.com/dfguerrerom/voila.git@custom-labextension"
2 changes: 1 addition & 1 deletion modules/sandbox/script/start-jupyter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ sudo -iu $sandbox_user PATH=$PATH PROJ_LIB=/usr/share/proj NODE_PATH=$NODE_PATH:
--ServerApp.password=''\
--ServerApp.disable_check_xsrf=True\
--ServerApp.base_url='/api/sandbox/jupyter/'\
--ServerApp.notebook_dir="/home/$sandbox_user"\
--ServerApp.root_dir="/home/$sandbox_user"\
--FileContentsManager.delete_to_trash=False\
--VoilaConfiguration.enable_nbextensions=True\
--VoilaConfiguration.show_tracebacks=True\
Expand Down
79 changes: 79 additions & 0 deletions modules/sandbox/script/voila.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""Voila configuration file for the sandbox environment"""

print("::::Voila labextensions::: Using custom sepal configuration file imported")
from copy import deepcopy
from typing import List, Tuple
from jupyter_core.paths import jupyter_path
from jupyter_server.config_manager import recursive_update
from jupyterlab_server.config import get_page_config as gpc

from voila._version import __version__
from voila.configuration import VoilaConfiguration
from voila.utils import filter_extension


def get_app_data(base_url: str, app_name: str) -> Tuple[List[str], str]:
"""Get the module data"""

# To the logic to get the app data
jupyter_url = f"/api/apps/labextensions/{app_name}/"
jupyter_paths = [
f"/usr/local/share/jupyter/kernels/venv-{app_name}/venv/share/jupyter/labextensions/"
]

print("::::Voila labextensions::: jupyter_path", jupyter_path)
print("::::Voila labextensions::: jupyter_url", jupyter_url)

return jupyter_paths, jupyter_url


def get_app_name(notebook_path: str):
"""Extract the app name from the notebook path"""

return notebook_path.split("apps/")[1].split("/")[0]


def page_config_hook(
page_config: dict,
base_url,
settings,
log,
voila_configuration: VoilaConfiguration,
notebook_path,
):
print("::::Voila labextensions::: Custom get_page_config_hook")
print("::::Voila labextensions::: notebook_path", notebook_path)

app_name = get_app_name(notebook_path)
app_extensions_paths, app_extensions_url = get_app_data(base_url, app_name)
page_config["fullLabextensionsUrl"] = app_extensions_url

recursive_update(
page_config,
gpc(app_extensions_paths, logger=log),
)
disabled_extensions = [
"@voila-dashboards/jupyterlab-preview",
"@jupyter/collaboration-extension",
"@jupyter-widgets/jupyterlab-manager",
"@jupyterhub/jupyter-server-proxy", # This was causing an error in the console
]
disabled_extensions.extend(page_config.get("disabledExtensions", []))

required_extensions = []
federated_extensions = deepcopy(page_config["federated_extensions"])

page_config["federated_extensions"] = filter_extension(
federated_extensions=federated_extensions,
disabled_extensions=disabled_extensions,
required_extensions=required_extensions,
extension_allowlist=voila_configuration.extension_allowlist,
extension_denylist=voila_configuration.extension_denylist,
)

print("::::Voila labextensions::: page_config", page_config)

return page_config


c.VoilaConfiguration.page_config_hook = page_config_hook