From 8753adc46cf09ce1370171b77279a30079091dd2 Mon Sep 17 00:00:00 2001 From: kay0u Date: Wed, 14 Aug 2019 00:07:10 +0200 Subject: [PATCH] version 1.0.4 --- README.md | 2 +- check_process | 16 -- conf/arm.src.default | 6 - conf/jupyter_notebook_config.py | 124 ++++++++++-- conf/jupyterhub_config.py | 326 +++++++++++++++++--------------- conf/systemd.service | 13 ++ conf/systemd.service.default | 14 -- conf/x86-64.src.default | 6 - conf/x86.src.default | 6 - manifest.json | 8 +- scripts/_common.sh | 175 +---------------- scripts/backup | 68 ++++--- scripts/change_url | 98 +++++----- scripts/experimental_helper.sh | 91 --------- scripts/install | 212 +++++++++++++-------- scripts/remove | 101 +++++----- scripts/restore | 115 +++++------ scripts/upgrade | 195 +++++++++++++------ scripts/upgrade.d/upgrade.sh | 12 +- 19 files changed, 793 insertions(+), 795 deletions(-) delete mode 100644 conf/arm.src.default create mode 100644 conf/systemd.service delete mode 100644 conf/systemd.service.default delete mode 100644 conf/x86-64.src.default delete mode 100644 conf/x86.src.default delete mode 100644 scripts/experimental_helper.sh diff --git a/README.md b/README.md index b79c53e..575f585 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ If you don't have YunoHost, please see [here](https://yunohost.org/#/install) to ## Overview JupyterLab is the next-generation user interface for Project Jupyter offering all the familiar building blocks of the classic Jupyter Notebook (notebook, terminal, text editor, file browser, rich outputs, etc.) in a flexible and powerful user interface. JupyterLab will eventually replace the classic Jupyter Notebook. -**Shipped version:** v0.35.4 +**Shipped version:** v1.0.4 ## Screenshots diff --git a/check_process b/check_process index 5ebabc5..4ecf7c0 100644 --- a/check_process +++ b/check_process @@ -1,13 +1,9 @@ -# See here for more informations -# https://github.com/YunoHost/package_check#syntax-check_process-file ;; Test complet ; Manifest domain="domain.tld" (DOMAIN) path="/jupyterlab" (PATH) admin="john" (USER) is_public=1 (PUBLIC|public=1|private=0) - password="pass" - port="666" (PORT) ; Checks pkg_linter=1 setup_sub_dir=1 @@ -18,22 +14,10 @@ upgrade=1 backup_restore=1 multi_instance=1 - incorrect_path=1 port_already_use=1 change_url=1 ;;; Levels - Level 1=auto - Level 2=auto - Level 3=auto -# Level 4: - Level 4=1 -# Level 5: Level 5=auto - Level 6=auto - Level 7=auto - Level 8=0 - Level 9=0 - Level 10=0 ;;; Options Email= Notification=none diff --git a/conf/arm.src.default b/conf/arm.src.default deleted file mode 100644 index 3d423d3..0000000 --- a/conf/arm.src.default +++ /dev/null @@ -1,6 +0,0 @@ -SOURCE_URL=https://github.com/jjhelmus/berryconda/releases/download/v__VERSION__/Berryconda3-__VERSION__-Linux-armv7l.sh -SOURCE_SUM=__MD5_SUM__ -SOURCE_SUM_PRG=md5sum -SOURCE_FILENAME=Berryconda3-__VERSION__-Linux-armv7l.sh -SOURCE_EXTRACT=false -SOURCE_FORMAT=sh \ No newline at end of file diff --git a/conf/jupyter_notebook_config.py b/conf/jupyter_notebook_config.py index e1f8000..8e25e1e 100644 --- a/conf/jupyter_notebook_config.py +++ b/conf/jupyter_notebook_config.py @@ -90,7 +90,7 @@ ## The base URL for the notebook server. # # Leading and trailing slashes can be omitted, and will automatically be added. -#c.NotebookApp.base_url = '' +#c.NotebookApp.base_url = '/' ## Specify what command to use to invoke a web browser when opening the notebook. # If not specified, the default browser will be determined by the `webbrowser` @@ -153,7 +153,7 @@ # completely without authentication. These services can disable all # authentication and security checks, with the full knowledge of what that # implies. -c.NotebookApp.disable_check_xsrf = True +#c.NotebookApp.disable_check_xsrf = False ## Whether to enable MathJax for typesetting math/TeX # @@ -549,6 +549,10 @@ c.NotebookApp.terminals_enabled = bool(__ENABLE_TERMINAL__) ## A KernelManager that handles notebook mapping and HTTP error handling +## White list of allowed kernel message types. When the list is empty, all +# message types are allowed. +#c.MappingKernelManager.allowed_message_types = [] + ## Whether messages from kernels whose frontends have disconnected should be # buffered in-memory. # @@ -580,14 +584,31 @@ c.NotebookApp.terminals_enabled = bool(__ENABLE_TERMINAL__) # # On starting and restarting kernels, we check whether the kernel is running and # responsive by sending kernel_info_requests. This sets the timeout in seconds -# for how long the kernel can take before being presumed dead. This affects the -# MappingKernelManager (which handles kernel restarts) and the +# for how long the kernel can take before being presumed dead. This affects the +# MappingKernelManager (which handles kernel restarts) and the # ZMQChannelsHandler (which handles the startup). #c.MappingKernelManager.kernel_info_timeout = 60 ## #c.MappingKernelManager.root_dir = '' +#------------------------------------------------------------------------------ +# KernelSpecManager(LoggingConfigurable) configuration +#------------------------------------------------------------------------------ + +## If there is no Python kernelspec registered and the IPython kernel is +# available, ensure it is added to the spec list. +#c.KernelSpecManager.ensure_native_kernel = True + +## The kernel spec class. This is configurable to allow subclassing of the +# KernelSpecManager for customized behavior. +#c.KernelSpecManager.kernel_spec_class = 'jupyter_client.kernelspec.KernelSpec' + +## Whitelist of allowed kernel names. +# +# By default, all installed kernels are allowed. +#c.KernelSpecManager.whitelist = set() + #------------------------------------------------------------------------------ # ContentsManager(LoggingConfigurable) configuration #------------------------------------------------------------------------------ @@ -686,8 +707,8 @@ c.NotebookApp.terminals_enabled = bool(__ENABLE_TERMINAL__) # log : logging.Logger ## By default notebooks are saved on disk on a temporary file and then if -# succefully written, it replaces the old ones. This procedure, namely -# 'atomic_writing', causes some bugs on file system whitout operation order +# successfully written, it replaces the old ones. This procedure, namely +# 'atomic_writing', causes some bugs on file system without operation order # enforcement (like some networked fs). If set to False, the new notebook is # written directly on the old one which could fail (eg: full filesystem or quota # ) @@ -748,18 +769,87 @@ c.NotebookApp.terminals_enabled = bool(__ENABLE_TERMINAL__) #c.NotebookNotary.store_factory = traitlets.Undefined #------------------------------------------------------------------------------ -# KernelSpecManager(LoggingConfigurable) configuration +# GatewayKernelManager(MappingKernelManager) configuration #------------------------------------------------------------------------------ -## If there is no Python kernelspec registered and the IPython kernel is -# available, ensure it is added to the spec list. -#c.KernelSpecManager.ensure_native_kernel = True +## Kernel manager that supports remote kernels hosted by Jupyter Kernel or +# Enterprise Gateway. -## The kernel spec class. This is configurable to allow subclassing of the -# KernelSpecManager for customized behavior. -#c.KernelSpecManager.kernel_spec_class = 'jupyter_client.kernelspec.KernelSpec' +#------------------------------------------------------------------------------ +# GatewayKernelSpecManager(KernelSpecManager) configuration +#------------------------------------------------------------------------------ -## Whitelist of allowed kernel names. -# -# By default, all installed kernels are allowed. -#c.KernelSpecManager.whitelist = set() +#------------------------------------------------------------------------------ +# GatewayClient(SingletonConfigurable) configuration +#------------------------------------------------------------------------------ + +## This class manages the configuration. It's its own singleton class so that we +# can share these values across all objects. It also contains some helper methods +# to build request arguments out of the various config options. + +## The authorization token used in the HTTP headers. (JUPYTER_GATEWAY_AUTH_TOKEN +# env var) +#c.GatewayClient.auth_token = None + +## The filename of CA certificates or None to use defaults. +# (JUPYTER_GATEWAY_CA_CERTS env var) +#c.GatewayClient.ca_certs = None + +## The filename for client SSL certificate, if any. (JUPYTER_GATEWAY_CLIENT_CERT +# env var) +#c.GatewayClient.client_cert = None + +## The filename for client SSL key, if any. (JUPYTER_GATEWAY_CLIENT_KEY env var) +#c.GatewayClient.client_key = None + +## The time allowed for HTTP connection establishment with the Gateway server. +# (JUPYTER_GATEWAY_CONNECT_TIMEOUT env var) +#c.GatewayClient.connect_timeout = 60.0 + +## A comma-separated list of environment variable names that will be included, +# along with their values, in the kernel startup request. The corresponding +# `env_whitelist` configuration value must also be set on the Gateway server - +# since that configuration value indicates which environmental values to make +# available to the kernel. (JUPYTER_GATEWAY_ENV_WHITELIST env var) +#c.GatewayClient.env_whitelist = '' + +## Additional HTTP headers to pass on the request. This value will be converted +# to a dict. (JUPYTER_GATEWAY_HEADERS env var) +#c.GatewayClient.headers = '{}' + +## The password for HTTP authentication. (JUPYTER_GATEWAY_HTTP_PWD env var) +#c.GatewayClient.http_pwd = None + +## The username for HTTP authentication. (JUPYTER_GATEWAY_HTTP_USER env var) +#c.GatewayClient.http_user = None + +## The gateway API endpoint for accessing kernel resources +# (JUPYTER_GATEWAY_KERNELS_ENDPOINT env var) +#c.GatewayClient.kernels_endpoint = '/api/kernels' + +## The gateway API endpoint for accessing kernelspecs +# (JUPYTER_GATEWAY_KERNELSPECS_ENDPOINT env var) +#c.GatewayClient.kernelspecs_endpoint = '/api/kernelspecs' + +## The gateway endpoint for accessing kernelspecs resources +# (JUPYTER_GATEWAY_KERNELSPECS_RESOURCE_ENDPOINT env var) +#c.GatewayClient.kernelspecs_resource_endpoint = '/kernelspecs' + +## The time allowed for HTTP request completion. (JUPYTER_GATEWAY_REQUEST_TIMEOUT +# env var) +#c.GatewayClient.request_timeout = 60.0 + +## The url of the Kernel or Enterprise Gateway server where kernel specifications +# are defined and kernel management takes place. If defined, this Notebook +# server acts as a proxy for all kernel management and kernel specification +# retrieval. (JUPYTER_GATEWAY_URL env var) +#c.GatewayClient.url = None + +## For HTTPS requests, determines if server's certificate should be validated or +# not. (JUPYTER_GATEWAY_VALIDATE_CERT env var) +#c.GatewayClient.validate_cert = True + +## The websocket url of the Kernel or Enterprise Gateway server. If not +# provided, this value will correspond to the value of the Gateway url with 'ws' +# in place of 'http'. (JUPYTER_GATEWAY_WS_URL env var) +#c.GatewayClient.ws_url = None \ No newline at end of file diff --git a/conf/jupyterhub_config.py b/conf/jupyterhub_config.py index 9377df4..e934d9f 100644 --- a/conf/jupyterhub_config.py +++ b/conf/jupyterhub_config.py @@ -64,19 +64,29 @@ # API. #c.JupyterHub.api_tokens = {} +## Authentication for prometheus metrics +#c.JupyterHub.authenticate_prometheus = True + ## Class for authenticating users. # -# This should be a class with the following form: +# This should be a subclass of :class:`jupyterhub.auth.Authenticator` # -# - constructor takes one kwarg: `config`, the IPython config object. +# with an :meth:`authenticate` method that: # -# with an authenticate method that: +# - is a coroutine (asyncio or tornado) +# - returns username on success, None on failure +# - takes two arguments: (handler, data), +# where `handler` is the calling web.RequestHandler, +# and `data` is the POST form data from the login page. # -# - is a coroutine (asyncio or tornado) -# - returns username on success, None on failure -# - takes two arguments: (handler, data), -# where `handler` is the calling web.RequestHandler, -# and `data` is the POST form data from the login page. +# .. versionchanged:: 1.0 +# authenticators may be registered via entry points, +# e.g. `c.JupyterHub.authenticator_class = 'pam'` +# +# Currently installed: +# - default: jupyterhub.auth.PAMAuthenticator +# - dummy: jupyterhub.auth.DummyAuthenticator +# - pam: jupyterhub.auth.PAMAuthenticator #c.JupyterHub.authenticator_class = 'jupyterhub.auth.PAMAuthenticator' c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator' @@ -175,6 +185,24 @@ c.JupyterHub.bind_url = 'http://:__PORT____PATH__' # By default, redirects users to their own server. #c.JupyterHub.default_url = '' +## Dict authority:dict(files). Specify the key, cert, and/or ca file for an +# authority. This is useful for externally managed proxies that wish to use +# internal_ssl. +# +# The files dict has this format (you must specify at least a cert):: +# +# { +# 'key': '/path/to/key.key', +# 'cert': '/path/to/cert.crt', +# 'ca': '/path/to/ca.crt' +# } +# +# The authorities you can override: 'hub-ca', 'notebooks-ca', 'proxy-api-ca', +# 'proxy-client-ca', and 'services-ca'. +# +# Use with internal_ssl +#c.JupyterHub.external_ssl_authorities = {} + ## Register extra tornado Handlers for jupyterhub. # # Should be of the form ``("", Handler)`` @@ -190,6 +218,9 @@ c.JupyterHub.bind_url = 'http://:__PORT____PATH__' ## Extra log handlers to set on JupyterHub logger #c.JupyterHub.extra_log_handlers = [] +## Generate certs used for internal ssl +#c.JupyterHub.generate_certs = False + ## Generate default config file #c.JupyterHub.generate_config = False @@ -254,7 +285,7 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # # See `hub_connect_ip` for cases where the bind and connect address should # differ, or `hub_bind_url` for setting the full bind URL. -#c.JupyterHub.hub_ip = '0.0.0.0' +#c.JupyterHub.hub_ip = '127.0.0.1' ## The internal port for the Hub process. # @@ -264,7 +295,19 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # conflict. # # See also `hub_ip` for the ip and `hub_bind_url` for setting the full bind URL. -#c.JupyterHub.hub_port = 80 +#c.JupyterHub.hub_port = 8081 + +## The location to store certificates automatically created by JupyterHub. +# +# Use with internal_ssl +#c.JupyterHub.internal_certs_location = 'internal-ssl' + +## Enable SSL for all internal communication +# +# This enables end-to-end encryption between all JupyterHub components. +# JupyterHub will automatically create the necessary certificate authority and +# sign notebook certificates as they're created. +#c.JupyterHub.internal_ssl = False ## The public facing ip of the whole JupyterHub application (specifically # referred to as the proxy). @@ -275,7 +318,7 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # # .. deprecated: 0.9 # Use JupyterHub.bind_url -#c.JupyterHub.ip = '0.0.0.0' +#c.JupyterHub.ip = '' ## Supply extra arguments that will be passed to Jinja environment. #c.JupyterHub.jinja_environment_options = {} @@ -295,6 +338,14 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' ## Specify path to a logo image to override the Jupyter logo in the banner. #c.JupyterHub.logo_file = '' +## Maximum number of concurrent named servers that can be created by a user at a +# time. +# +# Setting this can limit the total resources a user can consume. +# +# If set to 0, no limit is enforced. +#c.JupyterHub.named_server_limit_per_user = 0 + ## File to write PID Useful for daemonizing JupyterHub. #c.JupyterHub.pid_file = '' @@ -305,7 +356,7 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # # .. deprecated: 0.9 # Use JupyterHub.bind_url -#c.JupyterHub.port = 80 +#c.JupyterHub.port = 8000 ## DEPRECATED since version 0.8 : Use ConfigurableHTTPProxy.api_url #c.JupyterHub.proxy_api_ip = '' @@ -319,12 +370,29 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' ## Interval (in seconds) at which to check if the proxy is running. #c.JupyterHub.proxy_check_interval = 30 -## Select the Proxy API implementation. +## The class to use for configuring the JupyterHub proxy. +# +# Should be a subclass of :class:`jupyterhub.proxy.Proxy`. +# +# .. versionchanged:: 1.0 +# proxies may be registered via entry points, +# e.g. `c.JupyterHub.proxy_class = 'traefik'` +# +# Currently installed: +# - default: jupyterhub.proxy.ConfigurableHTTPProxy +# - configurable-http-proxy: jupyterhub.proxy.ConfigurableHTTPProxy #c.JupyterHub.proxy_class = 'jupyterhub.proxy.ConfigurableHTTPProxy' ## DEPRECATED since version 0.8. Use ConfigurableHTTPProxy.command #c.JupyterHub.proxy_cmd = [] +## Recreate all certificates used within JupyterHub on restart. +# +# Note: enabling this feature requires restarting all notebook servers. +# +# Use with internal_ssl +#c.JupyterHub.recreate_internal_certs = False + ## Redirect user to server (if running), instead of control panel. #c.JupyterHub.redirect_to_server = True @@ -361,9 +429,21 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # ] #c.JupyterHub.services = [] +## Shuts down all user servers on logout +#c.JupyterHub.shutdown_on_logout = False + ## The class to use for spawning single-user servers. # -# Should be a subclass of Spawner. +# Should be a subclass of :class:`jupyterhub.spawner.Spawner`. +# +# .. versionchanged:: 1.0 +# spawners may be registered via entry points, +# e.g. `c.JupyterHub.spawner_class = 'localprocess'` +# +# Currently installed: +# - simple: jupyterhub.spawner.SimpleLocalProcessSpawner +# - default: jupyterhub.spawner.LocalProcessSpawner +# - localprocess: jupyterhub.spawner.LocalProcessSpawner #c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner' ## Path to SSL certificate file for the public facing interface of the proxy @@ -430,6 +510,24 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # of checking authentication tokens. #c.JupyterHub.trust_user_provided_tokens = False +## Names to include in the subject alternative name. +# +# These names will be used for server name verification. This is useful if +# JupyterHub is being run behind a reverse proxy or services using ssl are on +# different hosts. +# +# Use with internal_ssl +#c.JupyterHub.trusted_alt_names = [] + +## Downstream proxy IP addresses to trust. +# +# This sets the list of IP addresses that are trusted and skipped when +# processing the `X-Forwarded-For` header. For example, if an external proxy is +# used for TLS termination, its IP address should be added to this list to +# ensure the correct client IP addresses are recorded in the logs instead of the +# proxy server's IP address. +#c.JupyterHub.trusted_downstream_ips = [] + ## Upgrade the database automatically on start. # # Only safe if database is regularly backed up. Only SQLite databases will be @@ -468,7 +566,7 @@ c.ConfigurableHTTPProxy.api_url = 'http://127.0.0.1:__PORT_HTTP_PROXY__' # Some spawners allow shell-style expansion here, allowing you to use # environment variables. Most, including the default, do not. Consult the # documentation for your spawner to verify! -c.Spawner.cmd = ['__FINAL_PATH__/bin/jupyter-labhub'] +#c.Spawner.cmd = ['jupyterhub-singleuser'] ## Maximum number of consecutive failures to allow before shutting down # JupyterHub. @@ -520,7 +618,7 @@ c.Spawner.cmd = ['__FINAL_PATH__/bin/jupyter-labhub'] # navigate the whole filesystem from their notebook server, but still start in their home directory. # - Start with `/notebooks` instead of `/tree` if `default_url` points to a notebook instead of a directory. # - You can set this to `/lab` to have JupyterLab start by default, rather than Jupyter Notebook. -#c.Spawner.default_url = '/user/%U/lab' +c.Spawner.default_url = '/lab' ## Disable per-user configuration of single-user servers. # @@ -675,6 +773,8 @@ c.Spawner.notebook_dir = '~/' # # This can be set independent of any concrete spawner implementation. # +# This maybe a coroutine. +# # Example:: # # from subprocess import check_call @@ -685,6 +785,15 @@ c.Spawner.notebook_dir = '~/' # c.Spawner.pre_spawn_hook = my_hook #c.Spawner.pre_spawn_hook = None +## List of SSL alt names +# +# May be set in config if all spawners should have the same value(s), or set at +# runtime by Spawner that know their names. +#c.Spawner.ssl_alt_names = [] + +## Whether to include DNS:localhost, IP:127.0.0.1 in alt names +#c.Spawner.ssl_alt_names_include_local = True + ## Timeout (in seconds) before giving up on starting of single-user server. # # This is the timeout for start to return, not the timeout for the server to @@ -693,66 +802,6 @@ c.Spawner.notebook_dir = '~/' # and its location is known. #c.Spawner.start_timeout = 60 -#------------------------------------------------------------------------------ -# LocalProcessSpawner(Spawner) configuration -#------------------------------------------------------------------------------ - -## A Spawner that uses `subprocess.Popen` to start single-user servers as local -# processes. -# -# Requires local UNIX users matching the authenticated users to exist. Does not -# work on Windows. -# -# This is the default spawner for JupyterHub. -# -# Note: This spawner does not implement CPU / memory guarantees and limits. - -## Seconds to wait for single-user server process to halt after SIGINT. -# -# If the process has not exited cleanly after this many seconds, a SIGTERM is -# sent. -#c.LocalProcessSpawner.interrupt_timeout = 10 - -## Seconds to wait for process to halt after SIGKILL before giving up. -# -# If the process does not exit cleanly after this many seconds of SIGKILL, it -# becomes a zombie process. The hub process will log a warning and then give up. -#c.LocalProcessSpawner.kill_timeout = 5 - -## Extra keyword arguments to pass to Popen -# -# when spawning single-user servers. -# -# For example:: -# -# popen_kwargs = dict(shell=True) -#c.LocalProcessSpawner.popen_kwargs = {} - -## Specify a shell command to launch. -# -# The single-user command will be appended to this list, so it sould end with -# `-c` (for bash) or equivalent. -# -# For example:: -# -# c.LocalProcessSpawner.shell_cmd = ['bash', '-l', '-c'] -# -# to launch with a bash login shell, which would set up the user's own complete -# environment. -# -# .. warning:: -# -# Using shell_cmd gives users control over PATH, etc., -# which could change what the jupyterhub-singleuser launch command does. -# Only use this for trusted users. -#c.LocalProcessSpawner.shell_cmd = [] - -## Seconds to wait for single-user server process to halt after SIGTERM. -# -# If the process does not exit cleanly after this many seconds of SIGTERM, a -# SIGKILL is sent. -#c.LocalProcessSpawner.term_timeout = 5 - #------------------------------------------------------------------------------ # Authenticator(LoggingConfigurable) configuration #------------------------------------------------------------------------------ @@ -773,6 +822,15 @@ c.Spawner.notebook_dir = '~/' # Defaults to an empty set, in which case no user has admin access. c.Authenticator.admin_users = ["__ADMIN__"] +## The max age (in seconds) of authentication info before forcing a refresh of +# user auth info. +# +# Refreshing auth info allows, e.g. requesting/re-validating auth tokens. +# +# See :meth:`.refresh_user` for what happens when user auth info is refreshed +# (nothing by default). +#c.Authenticator.auth_refresh_age = 300 + ## Automatically begin the login process # # rather than starting with a "Login with..." link at `/hub/login` @@ -812,6 +870,49 @@ c.Authenticator.admin_users = ["__ADMIN__"] # New in JupyterHub 0.8 #c.Authenticator.enable_auth_state = False +## An optional hook function that you can implement to do some bootstrapping work +# during authentication. For example, loading user account details from an +# external system. +# +# This function is called after the user has passed all authentication checks +# and is ready to successfully authenticate. This function must return the +# authentication dict reguardless of changes to it. +# +# This maybe a coroutine. +# +# .. versionadded: 1.0 +# +# Example:: +# +# import os, pwd +# def my_hook(authenticator, handler, authentication): +# user_data = pwd.getpwnam(authentication['name']) +# spawn_data = { +# 'pw_data': user_data +# 'gid_list': os.getgrouplist(authentication['name'], user_data.pw_gid) +# } +# +# if authentication['auth_state'] is None: +# authentication['auth_state'] = {} +# authentication['auth_state']['spawn_data'] = spawn_data +# +# return authentication +# +# c.Authenticator.post_auth_hook = my_hook +#c.Authenticator.post_auth_hook = None + +## Force refresh of auth prior to spawn. +# +# This forces :meth:`.refresh_user` to be called prior to launching a server, to +# ensure that auth state is up-to-date. +# +# This can be important when e.g. auth tokens that may have expired are passed +# to the spawner via environment variables from auth_state. +# +# If refresh_user cannot refresh the user auth data, launch will fail until the +# user logs in again. +#c.Authenticator.refresh_pre_spawn = False + ## Dictionary mapping authenticator usernames to JupyterHub users. # # Primarily used to normalize OAuth user names to local users. @@ -834,77 +935,6 @@ c.Authenticator.admin_users = ["__ADMIN__"] # If empty, does not perform any additional restriction. #c.Authenticator.whitelist = set() -#------------------------------------------------------------------------------ -# LocalAuthenticator(Authenticator) configuration -#------------------------------------------------------------------------------ - -## Base class for Authenticators that work with local Linux/UNIX users -# -# Checks for local users, and can attempt to create them if they exist. - -## The command to use for creating users as a list of strings -# -# For each element in the list, the string USERNAME will be replaced with the -# user's username. The username will also be appended as the final argument. -# -# For Linux, the default value is: -# -# ['adduser', '-q', '--gecos', '""', '--disabled-password'] -# -# To specify a custom home directory, set this to: -# -# ['adduser', '-q', '--gecos', '""', '--home', '/customhome/USERNAME', '-- -# disabled-password'] -# -# This will run the command: -# -# adduser -q --gecos "" --home /customhome/river --disabled-password river -# -# when the user 'river' is created. -#c.LocalAuthenticator.add_user_cmd = [] - -## If set to True, will attempt to create local system users if they do not exist -# already. -# -# Supports Linux and BSD variants only. -#c.LocalAuthenticator.create_system_users = False - -## Whitelist all users from this UNIX group. -# -# This makes the username whitelist ineffective. -#c.LocalAuthenticator.group_whitelist = set() - -#------------------------------------------------------------------------------ -# PAMAuthenticator(LocalAuthenticator) configuration -#------------------------------------------------------------------------------ - -## Authenticate local UNIX users with PAM - -## Whether to check the user's account status via PAM during authentication. -# -# The PAM account stack performs non-authentication based account management. -# It is typically used to restrict/permit access to a service and this step is -# needed to access the host's user access control. -# -# Disabling this can be dangerous as authenticated but unauthorized users may be -# granted access and, therefore, arbitrary execution on the system. -#c.PAMAuthenticator.check_account = True - -## The text encoding to use when communicating with PAM -#c.PAMAuthenticator.encoding = 'utf8' - -## Whether to open a new PAM session when spawners are started. -# -# This may trigger things like mounting shared filsystems, loading credentials, -# etc. depending on system configuration, but it does not always work. -# -# If any errors are encountered when opening/closing PAM sessions, this is -# automatically set to False. -#c.PAMAuthenticator.open_sessions = True - -## The name of the PAM service to use for authentication -#c.PAMAuthenticator.service = 'login' - #------------------------------------------------------------------------------ # CryptKeeper(SingletonConfigurable) configuration #------------------------------------------------------------------------------ @@ -917,7 +947,7 @@ c.Authenticator.admin_users = ["__ADMIN__"] #c.CryptKeeper.keys = [] ## The number of threads to allocate for encryption -#c.CryptKeeper.n_threads = 4 +#c.CryptKeeper.n_threads = 8 c.LDAPAuthenticator.bind_dn_template = [ "uid={username},ou=users,dc=yunohost,dc=org" ] c.LDAPAuthenticator.server_address = 'localhost' diff --git a/conf/systemd.service b/conf/systemd.service new file mode 100644 index 0000000..ee8b08f --- /dev/null +++ b/conf/systemd.service @@ -0,0 +1,13 @@ +[Unit] +Description=Jupyterlab +After=syslog.target network.target + +[Service] +Environment="PATH=__NODE_PATH__:__FINALPATH__/.venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin;JUPYTER_CONFIG_DIR=__FINALPATH__/config" +ExecStart=/usr/local/bin/pipenv run jupyterhub -f __FINALPATH__/config/jupyterhub_config.py +Restart=always +RestartSec=10 +WorkingDirectory=__FINALPATH__ + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/conf/systemd.service.default b/conf/systemd.service.default deleted file mode 100644 index 1e36a5a..0000000 --- a/conf/systemd.service.default +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Jupyterlab -After=syslog.target network.target - -[Service] -Environment="PATH=__FINALPATH__/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -ExecStart=__FINALPATH__/bin/jupyterhub -f __CONFIGPATH__/jupyterhub_config.py -Restart=always -RestartSec=10 -WorkingDirectory=__FINALPATH__ -LimitNOFILE=49152 - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/conf/x86-64.src.default b/conf/x86-64.src.default deleted file mode 100644 index 45961e6..0000000 --- a/conf/x86-64.src.default +++ /dev/null @@ -1,6 +0,0 @@ -SOURCE_URL=https://repo.continuum.io/miniconda/Miniconda3-__VERSION__-Linux-x86_64.sh -SOURCE_SUM=__MD5_SUM__ -SOURCE_SUM_PRG=md5sum -SOURCE_FILENAME=Miniconda3-__VERSION__-Linux-x86_64.sh -SOURCE_EXTRACT=false -SOURCE_FORMAT=sh \ No newline at end of file diff --git a/conf/x86.src.default b/conf/x86.src.default deleted file mode 100644 index d4d390a..0000000 --- a/conf/x86.src.default +++ /dev/null @@ -1,6 +0,0 @@ -SOURCE_URL=https://repo.continuum.io/miniconda/Miniconda3-__VERSION__-Linux-x86.sh -SOURCE_SUM=__MD5_SUM__ -SOURCE_SUM_PRG=md5sum -SOURCE_FILENAME=Miniconda3-__VERSION__-Linux-x86.sh -SOURCE_EXTRACT=false -SOURCE_FORMAT=sh \ No newline at end of file diff --git a/manifest.json b/manifest.json index 0cb2f57..7893bfe 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "name": "JupyterLab", "id": "jupyterlab", "packaging_format": 1, - "version": "0.35.4~ynh4", + "version": "1.0.4~ynh1", "description": { "en": "JupyterLab for Yunohost, an extensible environment for interactive and reproducible computing (notebook, terminal, text editor, file browser, rich outputs, etc.)", "fr": "JupyterLab pour YunoHost, un environnement informatique extensible, interactif et reproductible (bloc-notes, terminal, éditeur de texte, explorateur de fichiers, texte enrichi, etc.)" @@ -14,7 +14,7 @@ "email": "" }, "requirements": { - "yunohost": ">> 3.0.0" + "yunohost": ">= 3.5" }, "multi_instance": true, "services": [ @@ -38,8 +38,8 @@ "en": "Choose a path for JupyterLab", "fr": "Choisissez un chemin pour JupyterLab" }, - "example": "/", - "default": "/" + "example": "/jupyterlab", + "default": "/jupyterlab" }, { "name": "admin", diff --git a/scripts/_common.sh b/scripts/_common.sh index fc7bd6f..d53d870 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,179 +1,20 @@ -#================================================= -# SET ALL CONSTANTS -#================================================= - -app=$YNH_APP_INSTANCE_NAME -config_path="/etc/$app" -final_path="/opt/$app" +#!/bin/bash #================================================= -# DETECT THE SYSTEM ARCHITECTURE +# COMMON VARIABLES #================================================= -# Detect the system architecture to download the right file -# NOTE: `uname -m` is more accurate and universal than `arch` -# See https://en.wikipedia.org/wiki/Uname -if [ -n "$(uname -m | grep 64)" ]; then - miniconda_architecture="x86-64" -elif [ -n "$(uname -m | grep 86)" ]; then - miniconda_architecture="x86" -elif [ -n "$(uname -m | grep arm)" ]; then - miniconda_architecture="arm" -else - ynh_die "Unable to detect your achitecture, please open a bug describing \ - your hardware and the result of the command \"uname -m\"." 1 -fi + +# dependencies used by the app +pkg_dependencies="python3-pip" #================================================= -# CREATE FOLDERS +# PERSONAL HELPERS #================================================= -create_dir() { - mkdir -p "$config_path" -} #================================================= -# CONFIGURATION FILES FOR JUPYTERLAB +# EXPERIMENTAL HELPERS #================================================= -config_jupyterlab() { - ynh_print_info "Configuring JupyterLab..." - - create_dir - - jupyterlab_conf_path="$config_path/jupyterhub_config.py" - - ynh_backup_if_checksum_is_different $jupyterlab_conf_path - - # JupyterLab configuration - cp -f ../conf/jupyterhub_config.py $jupyterlab_conf_path - - ynh_replace_string "__URL__" "https://$domain" $jupyterlab_conf_path - ynh_replace_string "__PATH__" "${path_url%/}" $jupyterlab_conf_path - ynh_replace_string "__PORT__" "$port" $jupyterlab_conf_path - ynh_replace_string "__PORT_HUB__" "$port_hub" $jupyterlab_conf_path - ynh_replace_string "__PORT_HTTP_PROXY__" "$port_http_proxy" $jupyterlab_conf_path - ynh_replace_string "__FINAL_PATH__" "$final_path" $jupyterlab_conf_path - ynh_replace_string "__ADMIN__" "$admin" $jupyterlab_conf_path - - ynh_store_file_checksum $jupyterlab_conf_path -} - -config_jupyter_notebook() { - ynh_print_info "Configuring Jupyter Notebook..." - - jupyter_notebook_conf_path="$final_path/etc/jupyter/jupyter_notebook_config.py" - - ynh_backup_if_checksum_is_different $jupyter_notebook_conf_path - - # Jupyter notebook configuration - cp -f ../conf/jupyter_notebook_config.py $jupyter_notebook_conf_path - - ynh_replace_string "__ENABLE_TERMINAL__" "$enable_terminal" $jupyter_notebook_conf_path - - ynh_store_file_checksum $jupyter_notebook_conf_path -} #================================================= -# CREATE A DEDICATED SYSTEMD CONFIG +# FUTURE OFFICIAL HELPERS #================================================= -add_systemd_config() { - ynh_print_info "Adding Jupyterlab as a service..." - - sudo cp ../conf/systemd.service.default ../conf/systemd.service - tempsystemdconf="../conf/systemd.service" - - if test -n "${config_path:-}"; then - ynh_replace_string "__CONFIGPATH__" "$config_path" "$tempsystemdconf" - fi - - ynh_add_systemd_config -} - -#================================================= -# REMOVE THE CONFIGURATION FILE FOR JUPYTERLAB -#================================================= -remove_config_jupyterlab() { - ynh_print_info "Removing the configuration file..." - - ynh_secure_remove "$config_path/jupyterhub_config.py" -} - -#================================================= -# UPDATE SOURCES FILES -#================================================= -update_src_version() { - source ./upgrade.d/upgrade.sh - cp ../conf/arm.src.default ../conf/arm.src - ynh_replace_string "__VERSION__" "$berryconda3_version" "../conf/arm.src" - ynh_replace_string "__MD5_SUM__" "$berryconda3_arm_source_md5" "../conf/arm.src" - - cp ../conf/x86-64.src.default ../conf/x86-64.src - ynh_replace_string "__VERSION__" "$miniconda3_version" "../conf/x86-64.src" - ynh_replace_string "__MD5_SUM__" "$miniconda3_x86_64_source_md5" "../conf/x86-64.src" - - cp ../conf/x86.src.default ../conf/x86.src - ynh_replace_string "__VERSION__" "$miniconda3_version" "../conf/x86.src" - ynh_replace_string "__MD5_SUM__" "$miniconda3_x86_source_md5" "../conf/x86.src" -} - -#================================================= -# INSTALL JUPYTERLAB -#================================================= -# This function is inspired by the ynh_setup_source function, adapted to deal with .sh files -setup_source() { - local src_id=${1:-app} # If the argument is not given, source_id equals "app" - - update_src_version # Update source file - - # Load value from configuration file (see above for a small doc about this file - # format) - local src_url=$(grep 'SOURCE_URL=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - local src_sum=$(grep 'SOURCE_SUM=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - local src_format=$(grep 'SOURCE_FORMAT=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - local src_extract=$(grep 'SOURCE_EXTRACT=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - local src_filename=$(grep 'SOURCE_FILENAME=' "$YNH_CWD/../conf/${src_id}.src" | cut -d= -f2-) - - # Default value - src_sumprg=${src_sumprg:-sha256sum} - src_in_subdir=${src_in_subdir:-true} - src_format=${src_format:-tar.gz} - src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]') - src_extract=${src_extract:-true} - if [ "$src_filename" = "" ]; then - src_filename="${src_id}.${src_format}" - fi - - if ! test -e "$final_path"; then - - local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${src_filename}" - - ynh_print_info "Downloading anaconda files (used by JupyterLab)..." - - if test -e "$local_src"; then # Use the local source file if it is present - cp $local_src $src_filename - else # If not, download the source - wget -q --show-progress -O $src_filename $src_url - fi - - # Check the control sum - echo "${src_sum} ${src_filename}" | ${src_sumprg} -c --status || - ynh_die "Corrupt source" - - ynh_print_info "Installing anaconda (used by JupyterLab)..." - - bash $src_filename -b -p $final_path - fi - - export "PATH=$final_path/bin/:$PATH" - - ynh_print_info "Installing JupyterLab..." - - if [ "$src_id" = "arm" ]; then - conda install jupyterlab=$jupyterlab_version notebook nodejs pyyaml -y - pip install jupyterhub jupyterhub-ldapauthenticator - else - conda install -c conda-forge jupyterlab=$jupyterlab_version jupyterhub notebook jupyterhub-ldapauthenticator nodejs pyyaml -y - fi - - npm install -g configurable-http-proxy -} diff --git a/scripts/backup b/scripts/backup index 41c96f8..442a455 100644 --- a/scripts/backup +++ b/scripts/backup @@ -6,59 +6,71 @@ # IMPORT GENERIC HELPERS #================================================= -# Source YunoHost helpers -source /usr/share/yunohost/helpers - -# Load common variables and helpers +#Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers #================================================= # MANAGE SCRIPT FAILURE #================================================= -ynh_clean_setup() { - - true +ynh_clean_setup () { + ynh_clean_check_starting } - # Exit if an error occurs during the execution of the script ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 -# Copy NGINX configuration -domain=$(ynh_app_setting_get "$app" domain) +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) #================================================= # STANDARD BACKUP STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" + +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Backing up the main app directory..." --time --weight=1 + +ynh_backup --src_path="$final_path" + #================================================= # BACKUP THE NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Backing up nginx web server configuration..." --time --weight=1 -ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= -# BACKUP JUPYTERLAB -#================================================= - -ynh_print_info "Backuping of JupyterLab..." - -ynh_backup "$final_path/jupyterhub.sqlite" - -#================================================= -# BACKUP CONF FILES -#================================================= - -ynh_print_info "Backuping configuration files of JupyterLab..." - -ynh_backup "$config_path/jupyterhub_config.py" -ynh_backup "$final_path/etc/jupyter/jupyter_notebook_config.py" - +# SPECIFIC BACKUP #================================================= # BACKUP SYSTEMD #================================================= +ynh_script_progression --message="Backing up systemd configuration..." --time --weight=1 -ynh_backup "/etc/systemd/system/$app.service" +ynh_backup --src_path="/etc/systemd/system/$app.service" +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --line_match="JupyterHub is now running at" --log_path="systemd" + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." --time --last diff --git a/scripts/change_url b/scripts/change_url index f7d221b..a1047af 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -1,20 +1,13 @@ #!/bin/bash #================================================= -# GENERIC START +# GENERIC STARTING #================================================= # IMPORT GENERIC HELPERS #================================================= -# IMPORT GENERIC HELPERS +source _common.sh source /usr/share/yunohost/helpers -source ./experimental_helper.sh - -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - -# Import common cmd -source ./_common.sh #================================================= # RETRIEVE ARGUMENTS @@ -31,56 +24,52 @@ app=$YNH_APP_INSTANCE_NAME #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 -admin=$(ynh_app_setting_get "$app" admin) -port=$(ynh_app_setting_get "$app" port) -port_hub=$(ynh_app_setting_get "$app" port_hub) -port_http_proxy=$(ynh_app_setting_get "$app" port_http_proxy) - -#================================================= -# CHECK PATHS SYNTAX -#================================================= - -test -n "$old_path" || old_path="/" -test -n "$new_path" || new_path="/" -new_path=$(ynh_normalize_url_path $new_path) -old_path=$(ynh_normalize_url_path $old_path) - -domain="$new_domain" -path_url="$new_path" +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) +port_hub=$(ynh_app_setting_get --app=$app --key=port_hub) +port_http_proxy=$(ynh_app_setting_get --app=$app --key=port_http_proxy) +admin=$(ynh_app_setting_get --app=$app --key=admin) #================================================= # CHECK WHICH PARTS SHOULD BE CHANGED #================================================= change_domain=0 -if [ "$old_domain" != "$new_domain" ]; then +if [ "$old_domain" != "$new_domain" ] +then change_domain=1 fi change_path=0 -if [ "$old_path" != "$new_path" ]; then +if [ "$old_path" != "$new_path" ] +then change_path=1 fi #================================================= # STANDARD MODIFICATIONS #================================================= -# STOP SERVICE +# STOP SYSTEMD SERVICE #================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 -yunohost service stop jupyterlab +ynh_systemd_action --service_name=$app --action="stop" #================================================= -# MODIFY URL IN NGINX +# MODIFY URL IN NGINX CONF #================================================= +ynh_script_progression --message="Updating nginx web server configuration..." --time --weight=1 + nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf -if [ $change_path -eq 1 ]; then - ynh_print_info "Changing path..." - +# Change the path in the nginx config file +if [ $change_path -eq 1 ] +then # Make a backup of the original nginx config file if modified - ynh_backup_if_checksum_is_different "$nginx_conf_path" + ynh_backup_if_checksum_is_different --file="$nginx_conf_path" # Set global variables for nginx helper domain="$old_domain" path_url="$new_path" @@ -89,32 +78,55 @@ if [ $change_path -eq 1 ]; then fi # Change the domain for nginx -if [ $change_domain -eq 1 ]; then - ynh_print_info "Changing domain..." - +if [ $change_domain -eq 1 ] +then # Delete file checksum for the old conf file location - ynh_delete_file_checksum "$nginx_conf_path" + ynh_delete_file_checksum --file="$nginx_conf_path" mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf # Store file checksum for the new config file location - ynh_store_file_checksum "/etc/nginx/conf.d/$new_domain.d/$app.conf" + ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" fi +#================================================= +# SPECIFIC MODIFICATIONS #================================================= # CONFIGURE JUPYTERLAB #================================================= -config_jupyterlab +ynh_backup_if_checksum_is_different --file="$final_path/config/jupyterhub_config.py" + +domain=$new_domain +path_url=$new_path + +cp -f ../conf/jupyterhub_config.py $final_path/config/jupyterhub_config.py +ynh_replace_string --match_string="__URL__" --replace_string="https://$domain" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PATH__" --replace_string="${path_url%/}" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT_HUB__" --replace_string="$port_hub" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT_HTTP_PROXY__" --replace_string="$port_http_proxy" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__FINAL_PATH__" --replace_string="$final_path" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$final_path/config/jupyterhub_config.py" + +ynh_store_file_checksum --file="$final_path/config/jupyterhub_config.py" #================================================= # GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --line_match="JupyterHub is now running at" --log_path="systemd" + #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading nginx web server..." --time --weight=1 -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload #================================================= -# START SERVICE +# END OF SCRIPT #================================================= -ynh_systemd_action -n $app -a restart -l "JupyterHub is now running at" -p "systemd" +ynh_script_progression --message="Change of URL completed for $app" --time --last diff --git a/scripts/experimental_helper.sh b/scripts/experimental_helper.sh deleted file mode 100644 index 3aea7c4..0000000 --- a/scripts/experimental_helper.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash - -# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started -# -# usage: ynh_systemd_action [-n service_name] [-a action] [ [-l "line to match"] [-p log_path] [-t timeout] [-e length] ] -# | arg: -n, --service_name= - Name of the service to reload. Default : $app -# | arg: -a, --action= - Action to perform with systemctl. Default: start -# | arg: -l, --line_match= - Line to match - The line to find in the log to attest the service have finished to boot. -# If not defined it don't wait until the service is completely started. -# | arg: -p, --log_path= - Log file - Path to the log file. Default : /var/log/$app/$app.log -# | arg: -t, --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 300 seconds. -# | arg: -e, --length= - Length of the error log : Default : 20 -ynh_systemd_action() { - - # Declare an array to define the options of this helper. - declare -Ar args_array=([n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length=) - local service_name - local action - local line_match - local length - local log_path - local timeout - - # Manage arguments with getopts - ynh_handle_getopts_args "$@" - - local service_name="${service_name:-$app}" - local action=${action:-start} - local log_path="${log_path:-/var/log/$service_name/$service_name.log}" - local length=${length:-20} - local timeout=${timeout:-300} - - ynh_print_info "Waiting for a response from $service_name..." - - # Start to read the log - if [[ -n "${line_match:-}" ]]; then - local templog="$(mktemp)" - # Following the starting of the app in its log - if [ "$log_path" == "systemd" ]; then - # Read the systemd journal - journalctl -u $service_name -f -n0 >"$templog" & - else - # Read the specified log file - tail -F -n0 "$log_path" >"$templog" & - fi - # Get the PID of the tail command - local pid_tail=$! - fi - - echo "${action^} the service $service_name" >&2 - systemctl $action $service_name || - ( - journalctl --lines=$length -u $service_name >&2 \ - ; - test -n "$log_path" && echo "--" && tail --lines=$length "$log_path" >&2 \ - ; - false - ) - - # Start the timeout and try to find line_match - if [[ -n "${line_match:-}" ]]; then - local i=0 - for i in $(seq 1 $timeout); do - # Read the log until the sentence is found, that means the app finished to start. Or run until the timeout - if grep --quiet "$line_match" "$templog"; then - echo "The service $service_name has correctly started." >&2 - break - fi - echo -n "." >&2 - sleep 1 - done - if [ $i -eq $timeout ]; then - echo "The service $service_name didn't fully started before the timeout." >&2 - journalctl --lines=$length -u $service_name >&2 - test -n "$log_path" && echo "--" && tail --lines=$length "$log_path" >&2 - fi - - echo "" - ynh_clean_check_starting - fi -} - -# Clean temporary process and file used by ynh_check_starting -# (usually used in ynh_clean_setup scripts) -# -# usage: ynh_clean_check_starting -ynh_clean_check_starting() { - # Stop the execution of tail. - kill -s 15 $pid_tail 2>&1 - ynh_secure_remove "$templog" 2>&1 -} diff --git a/scripts/install b/scripts/install index 1a548c1..5756cd7 100644 --- a/scripts/install +++ b/scripts/install @@ -6,144 +6,200 @@ # IMPORT GENERIC HELPERS #================================================= +source _common.sh source /usr/share/yunohost/helpers -source ./experimental_helper.sh +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting +} # Exit if an error occurs during the execution of the script ynh_abort_if_errors -# Load common variables and helpers -source ./_common.sh - #================================================= -# RETRIEVE ARGUMENTS +# RETRIEVE ARGUMENTS FROM THE MANIFEST #================================================= -# Retrieve arguments domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH is_public=$YNH_APP_ARG_IS_PUBLIC admin=$YNH_APP_ARG_ADMIN enable_terminal=$YNH_APP_ARG_ENABLE_TERMINAL -#================================================= -# REGISTER DOMAIN -#================================================= - -# Normalize the url path syntax -test -n "$path_url" || path_url="/" -path_url=$(ynh_normalize_url_path $path_url) - -# This function check also the availability of this one -ynh_webpath_register $app $domain $path_url +app=$YNH_APP_INSTANCE_NAME #================================================= -# REGISTER DOMAIN +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= +ynh_script_progression --message="Validating installation parameters..." --weight=1 -# Check user parameter -ynh_user_exists "$admin" || - ynh_die "The chosen admin user does not exist." +final_path=/opt/$app +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" + +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url #================================================= # STORE SETTINGS FROM MANIFEST #================================================= +ynh_script_progression --message="Storing installation settings..." --weight=1 -ynh_app_setting_set $app admin $admin -ynh_app_setting_set $app domain $domain -ynh_app_setting_set $app path_url $path_url -ynh_app_setting_set $app is_public $is_public -ynh_app_setting_set $app enable_terminal $enable_terminal +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url +ynh_app_setting_set --app=$app --key=admin --value=$admin +ynh_app_setting_set --app=$app --key=is_public --value=$is_public +ynh_app_setting_set --app=$app --key=enable_terminal --value=$enable_terminal #================================================= # STANDARD MODIFICATIONS #================================================= -# FIND AND OPEN PORTS +# FIND AND OPEN A PORT #================================================= +ynh_script_progression --message="Configuring firewall..." --weight=1 -ynh_print_info "Getting ports..." +# Find a free port +port=$(ynh_find_port --port=8080) +port_hub=$(ynh_find_port --port=$(($port + 1))) +port_http_proxy=$(ynh_find_port --port=$(($port_hub + 1))) -# Find free ports -port=$(ynh_find_port 8080) -port_hub=$(ynh_find_port $(($port + 1))) -port_http_proxy=$(ynh_find_port $(($port_hub + 1))) +# Open this port +#ynh_exec_warn_less yunohost firewall allow --no-upnp TCP $port +#ynh_exec_warn_less yunohost firewall allow --no-upnp TCP $port_hub +#ynh_exec_warn_less yunohost firewall allow --no-upnp TCP $port_http_proxy +ynh_app_setting_set --app=$app --key=port --value=$port +ynh_app_setting_set --app=$app --key=port_hub --value=$port_hub +ynh_app_setting_set --app=$app --key=port_http_proxy --value=$port_http_proxy -yunohost firewall allow --no-upnp TCP $port 2>&1 -yunohost firewall allow --no-upnp TCP $port_hub 2>&1 -yunohost firewall allow --no-upnp TCP $port_http_proxy 2>&1 -ynh_app_setting_set $app port $port -ynh_app_setting_set $app port_hub $port_hub -ynh_app_setting_set $app port_http_proxy $port_http_proxy +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=23 + +ynh_install_app_dependencies $pkg_dependencies + +ynh_exec_warn_less ynh_install_nodejs --nodejs_version=8 + +pip3 install pipenv + +npm install -g configurable-http-proxy + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_script_progression --message="Setting up source files..." --weight=64 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path + +source ./upgrade.d/upgrade.sh + +mkdir -p $final_path + +pushd $final_path + +export PIPENV_VENV_IN_PROJECT="enabled" + +ynh_exec_warn_less pipenv install jupyterlab==$jupyterlab_version jupyterhub notebook jupyterhub-ldapauthenticator --three + +popd #================================================= # NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Configuring nginx web server..." --weight=1 # Create a dedicated nginx config ynh_add_nginx_config -#================================================= -# CONFIGURE JUPYTERLAB -#================================================= - -# Configure jupyterlab with jupyterhub_config.py file -config_jupyterlab - -#================================================= -# DOWNLOAD, CHECK AND INSTALL JUPYTERLAB -#================================================= - -setup_source $miniconda_architecture - #================================================= # SPECIFIC SETUP -#================================================= -# ADD HUB EXTENSION -#================================================= - -jupyter labextension install @jupyterlab/hub-extension -jupyter lab build - -chown $admin -R $final_path/share/jupyter - -#================================================= -# CONFIGURE JUPYTER NOTEBOOK -#================================================= -config_jupyter_notebook - #================================================= # SETUP SYSTEMD #================================================= +ynh_script_progression --message="Configuring a systemd service..." --weight=3 # Create a dedicated systemd config -add_systemd_config +ynh_replace_string --match_string="__NODE_PATH__" --replace_string="$nodejs_path" --target_file="../conf/systemd.service" + +ynh_add_systemd_config #================================================= -# SETUP SSOWAT +# MODIFY A CONFIG FILE #================================================= -# If app is public, add url to SSOWat conf as skipped_uris -if [[ $is_public -eq 1 ]]; then - # unprotected_uris allows SSO credentials to be passed anyway. - ynh_app_setting_set "$app" unprotected_uris "/" -fi +mkdir -p "$final_path/config" + +# JupyterHub configuration +cp -f ../conf/jupyterhub_config.py $final_path/config/jupyterhub_config.py + +ynh_replace_string --match_string="__URL__" --replace_string="https://$domain" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PATH__" --replace_string="${path_url%/}" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT_HUB__" --replace_string="$port_hub" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT_HTTP_PROXY__" --replace_string="$port_http_proxy" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__FINAL_PATH__" --replace_string="$final_path" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$final_path/config/jupyterhub_config.py" + +# Jupyter notebook configuration +cp -f ../conf/jupyter_notebook_config.py $final_path/config/jupyter_notebook_config.py + +ynh_replace_string --match_string="__ENABLE_TERMINAL__" --replace_string="$enable_terminal" --target_file="$final_path/config/jupyter_notebook_config.py" #================================================= -# GENERIC FINALISATION -#================================================= -# RELOAD NGINX +# STORE THE CONFIG FILE CHECKSUM #================================================= -systemctl reload nginx +# Calculate and store the config file checksum into the app settings +ynh_store_file_checksum --file="$final_path/config/jupyterhub_config.py" +ynh_store_file_checksum --file="$final_path/config/jupyter_notebook_config.py" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions to app files +chown -R root: $final_path +chown -R $admin: $final_path/.venv/share #================================================= # ADVERTISE SERVICE IN ADMIN PANEL #================================================= -yunohost service add $app --log "systemd" +yunohost service add $app --description "$app daemon" --log_type "systemd" --log "$app" #================================================= -# START SERVICE +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=3 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --line_match="JupyterHub is now running at" --log_path="systemd" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring SSOwat..." --weight=4 + +# Make app public if necessary +if [ $is_public -eq 1 ] +then + # unprotected_uris allows SSO credentials to be passed anyway. + ynh_app_setting_set --app=$app --key=unprotected_uris --value="/" +fi + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading nginx web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT #================================================= -ynh_systemd_action -n $app -a start -l "JupyterHub is now running at" -p "systemd" +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/remove b/scripts/remove index f45d177..9da7481 100644 --- a/scripts/remove +++ b/scripts/remove @@ -6,86 +6,93 @@ # IMPORT GENERIC HELPERS #================================================= -# Source YunoHost helpers +source _common.sh source /usr/share/yunohost/helpers -# Load common variables and helpers -source ./_common.sh - #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 -# See comments in install script app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get "$app" domain) -port=$(ynh_app_setting_get "$app" port) -port_hub=$(ynh_app_setting_get "$app" port_hub) -port_http_proxy=$(ynh_app_setting_get "$app" port_http_proxy) + +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +port_hub=$(ynh_app_setting_get --app=$app --key=port_hub) +port_http_proxy=$(ynh_app_setting_get --app=$app --key=port_http_proxy) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # STANDARD REMOVE -#================================================= -# STOP AND REMOVE SERVICE -#================================================= - -# Remove the dedicated systemd config -ynh_remove_systemd_config - #================================================= # REMOVE SERVICE FROM ADMIN PANEL #================================================= # Remove a service from the admin panel, added by `yunohost service add` -if yunohost service status | grep -q $app; then - echo "Remove $app service" +if ynh_exec_warn_less yunohost service status $app >/dev/null +then + ynh_script_progression --message="Removing $app service..." --weight=2 yunohost service remove $app fi #================================================= -# REMOVE CONF FILE +# STOP AND REMOVE SERVICE #================================================= +ynh_script_progression --message="Stopping and removing the systemd service..." --weight=2 -# Remove Config -remove_config_jupyterlab +# Remove the dedicated systemd config +ynh_remove_systemd_config + +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." --weight=4 + +# Remove metapackage and its dependencies +ynh_remove_app_dependencies + +ynh_remove_nodejs #================================================= # REMOVE APP MAIN DIR #================================================= +ynh_script_progression --message="Removing app main directory..." --weight=1 -ynh_print_info "Removing JupyterLab..." - -ynh_secure_remove "$final_path" -ynh_secure_remove "$config_path" - -# Remove the log files -ynh_secure_remove "/var/log/$app.log" - -#================================================= -# CLOSE PORTS -#================================================= - -if yunohost firewall list | grep -q "\- $port$"; then - echo "Close port $port" >&2 - yunohost firewall disallow TCP $port 2>&1 -fi -if yunohost firewall list | grep -q "\- $port_hub$"; then - echo "Close port $port_hub" >&2 - yunohost firewall disallow TCP $port_hub 2>&1 -fi -if yunohost firewall list | grep -q "\- $port_http_proxy$"; then - echo "Close port $port_http_proxy" >&2 - yunohost firewall disallow TCP $port_http_proxy 2>&1 -fi +# Remove the app directory securely +ynh_secure_remove --file="$final_path" #================================================= # REMOVE NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Removing nginx web server configuration..." --weight=1 +# Remove the dedicated nginx config ynh_remove_nginx_config #================================================= -# REMOVE LOGROTATE CONFIGURATION +# CLOSE A PORT #================================================= -#ynh_remove_logrotate +if yunohost firewall list | grep -q "\- $port$" +then + ynh_script_progression --message="Closing port $port..." + ynh_exec_warn_less yunohost firewall disallow TCP $port +fi + +if yunohost firewall list | grep -q "\- $port_hub$" +then + ynh_script_progression --message="Closing port $port_hub..." + ynh_exec_warn_less yunohost firewall disallow TCP $port_hub +fi + +if yunohost firewall list | grep -q "\- $port_http_proxy$" +then + ynh_script_progression --message="Closing port $port_http_proxy..." + ynh_exec_warn_less yunohost firewall disallow TCP $port_http_proxy +fi + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" --last diff --git a/scripts/restore b/scripts/restore index e2048de..c124805 100644 --- a/scripts/restore +++ b/scripts/restore @@ -6,52 +6,41 @@ # IMPORT GENERIC HELPERS #================================================= -# Source YunoHost helpers +#Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - -if [ ! -e _common.sh ]; then - # Get the _common.sh file if it's not in the current directory - cp ../settings/scripts/_common.sh ./_common.sh - cp ../settings/scripts/experimental_helper.sh ./experimental_helper.sh - mkdir ./upgrade.d - mkdir ../conf - cp ../settings/scripts/upgrade.d/*.sh ./upgrade.d/ - cp ../settings/conf/*.default ../conf/ - chmod a+rx _common.sh experimental_helper.sh upgrade.d/* -fi - -# Load common variables and helpers -source _common.sh -source experimental_helper.sh - #================================================= # MANAGE SCRIPT FAILURE #================================================= -ynh_clean_setup() { - - true +ynh_clean_setup () { + ynh_clean_check_starting } +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading settings..." --time --weight=1 -# Copy NGINX configuration -domain=$(ynh_app_setting_get "$app" domain) -path_url=$(ynh_app_setting_get "$app" path_url) +app=$YNH_APP_INSTANCE_NAME + +admin=$(ynh_app_setting_get --app=$app --key=admin) +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= +ynh_script_progression --message="Validating restoration parameters..." --time --weight=1 -ynh_webpath_available $domain $path_url || - ynh_die "Path not available: ${domain}${path_url}" -test ! -d $final_path || - ynh_die "There is already a directory: $final_path " +ynh_webpath_available --domain=$domain --path_url=$path_url \ + || ynh_die --message="Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " #================================================= # STANDARD RESTORATION STEPS @@ -59,51 +48,71 @@ test ! -d $final_path || # RESTORE THE NGINX CONFIGURATION #================================================= -ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf" - -#================================================= -# REINSTALL DEPENDENCIES -#================================================= - -ynh_install_app_dependencies openssh-server - -#================================================= -# RESTORE CONF FILES -#================================================= - -ynh_print_info "Restoring configuration files of JupyerLab..." - -create_dir - -ynh_restore_file "$config_path/jupyterhub_config.py" +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= # RESTORE THE APP MAIN DIR #================================================= +ynh_script_progression --message="Restoring the app main directory..." --time --weight=1 -ynh_print_info "Restoring JupyterLab..." +ynh_restore_file --origin_path="$final_path" -setup_source $miniconda_architecture +#================================================= +# RESTORE USER RIGHTS +#================================================= -ynh_restore_file "$final_path/etc/jupyter/jupyter_notebook_config.py" +# Restore permissions on app files +chown -R root: $final_path +chown -R $admin: $final_path/.venv/share #================================================= # SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --time --weight=1 + +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies + +ynh_exec_warn_less ynh_install_nodejs --nodejs_version=8 + +pip3 install pipenv + +npm install -g configurable-http-proxy + #================================================= # RESTORE SYSTEMD #================================================= +ynh_script_progression --message="Restoring the systemd configuration..." --time --weight=1 -ynh_restore_file "/etc/systemd/system/$app.service" +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl enable $app.service -yunohost service add $app --log "systemd" +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= + +yunohost service add $app --description "$app daemon" --log_type "systemd" --log "$app" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --line_match="JupyterHub is now running at" --log_path="systemd" #================================================= # GENERIC FINALIZATION #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading nginx web server..." --time --weight=1 -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload -ynh_systemd_action -n $app -a start -l "JupyterHub is now running at" -p "systemd" +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" --time --last diff --git a/scripts/upgrade b/scripts/upgrade index 0a4c80f..b37dae6 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -6,124 +6,201 @@ # IMPORT GENERIC HELPERS #================================================= -# IMPORT GENERIC HELPERS +source _common.sh source /usr/share/yunohost/helpers -source ./experimental_helper.sh - -# Load common variables and helpers -source ./_common.sh #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 app=$YNH_APP_INSTANCE_NAME -# Retrieve app settings -domain=$(ynh_app_setting_get "$app" domain) -path_url=$(ynh_app_setting_get "$app" path_url) -admin=$(ynh_app_setting_get "$app" admin) -is_public=$(ynh_app_setting_get "$app" is_public) -port=$(ynh_app_setting_get "$app" port) -port_hub=$(ynh_app_setting_get "$app" port_hub) -port_http_proxy=$(ynh_app_setting_get "$app" port_http_proxy) -enable_terminal=$(ynh_app_setting_get "$app" enable_terminal) +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +admin=$(ynh_app_setting_get --app=$app --key=admin) +is_public=$(ynh_app_setting_get --app=$app --key=is_public) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) +port_hub=$(ynh_app_setting_get --app=$app --key=port_hub) +port_http_proxy=$(ynh_app_setting_get --app=$app --key=port_http_proxy) +enable_terminal=$(ynh_app_setting_get --app=$app --key=enable_terminal) + +#================================================= +# CHECK VERSION +#================================================= + +upgrade_type=$(ynh_check_app_version_changed) + +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." --time --weight=1 + +# Fix is_public as a boolean value +if [ "$is_public" = "Yes" ]; then + ynh_app_setting_set --app=$app --key=is_public --value=1 + is_public=1 +elif [ "$is_public" = "No" ]; then + ynh_app_setting_set --app=$app --key=is_public --value=0 + is_public=0 +fi + +# If final_path doesn't exist, create it +if [ -z "$final_path" ]; then + final_path=/opt/$app + + mkdir -p $final_path + + ynh_app_setting_set --app=$app --key=final_path --value=$final_path +fi #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --time --weight=1 -# TODO Add backup/restore scripts -## Backup the current version of the app -#ynh_backup_before_upgrade -#ynh_clean_setup () { -# # restore it if the upgrade fails -# ynh_restore_upgradebackup -#} +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + ynh_clean_check_starting + # restore it if the upgrade fails + ynh_restore_upgradebackup +} # Exit if an error occurs during the execution of the script ynh_abort_if_errors -#================================================= -# CHECK THE PATH -#================================================= - -# Normalize the URL path syntax -path_url=$(ynh_normalize_url_path $path_url) - #================================================= # STANDARD UPGRADE STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" + #================================================= # NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Upgrading nginx web server configuration..." --time --weight=1 -# Modify Nginx configuration file and copy it to Nginx conf directory +# Create a dedicated nginx config ynh_add_nginx_config #================================================= -# CONFIGURE JUPYTERLAB +# UPGRADE DEPENDENCIES #================================================= +ynh_script_progression --message="Upgrading dependencies..." --time --weight=1 -# Configure jupyterlab with jupyterhub_config.py file -config_jupyterlab +ynh_install_app_dependencies $pkg_dependencies + +ynh_exec_warn_less ynh_install_nodejs --nodejs_version=8 + +npm install -g configurable-http-proxy + +pip3 install pipenv #================================================= -# DOWNLOAD, CHECK AND INSTALL JUPYTERLAB +# DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= -setup_source $miniconda_architecture +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." --time --weight=1 + + # Download, check integrity, uncompress and patch the source from app.src + source ./upgrade.d/upgrade.sh + + mkdir -p $final_path + + pushd $final_path + + export PIPENV_VENV_IN_PROJECT="enabled" + + ynh_exec_warn_less pipenv install jupyterlab==$jupyterlab_version jupyterhub notebook jupyterhub-ldapauthenticator --three + + ynh_exec_warn_less pipenv run jupyterhub upgrade-db + + popd +fi #================================================= -# SPECIFIC SETUP +# SPECIFIC UPGRADE #================================================= -# ADD HUB EXTENSION +# STORE THE CONFIG FILE CHECKSUM #================================================= -jupyter labextension install @jupyterlab/hub-extension -jupyter lab build +ynh_backup_if_checksum_is_different --file="$final_path/config/jupyterhub_config.py" -jupyterhub upgrade-db +cp -f ../conf/jupyterhub_config.py $final_path/config/jupyterhub_config.py +ynh_replace_string --match_string="__URL__" --replace_string="https://$domain" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PATH__" --replace_string="${path_url%/}" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT_HUB__" --replace_string="$port_hub" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__PORT_HTTP_PROXY__" --replace_string="$port_http_proxy" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__FINAL_PATH__" --replace_string="$final_path" --target_file="$final_path/config/jupyterhub_config.py" +ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$final_path/config/jupyterhub_config.py" -chown $admin -R $final_path/share/jupyter +# Recalculate and store the checksum of the file for the next upgrade. +ynh_store_file_checksum --file="$final_path/config/jupyterhub_config.py" -#================================================= -# CONFIGURE JUPYTER NOTEBOOK -#================================================= -config_jupyter_notebook +ynh_backup_if_checksum_is_different --file="$final_path/config/jupyter_notebook_config.py" + +cp -f ../conf/jupyter_notebook_config.py $final_path/config/jupyter_notebook_config.py + +ynh_replace_string --match_string="__ENABLE_TERMINAL__" --replace_string="$enable_terminal" --target_file="$final_path/config/jupyter_notebook_config.py" + +ynh_store_file_checksum --file="$final_path/config/jupyter_notebook_config.py" #================================================= # SETUP SYSTEMD #================================================= +ynh_script_progression --message="Upgrading systemd configuration..." --time --weight=1 # Create a dedicated systemd config -add_systemd_config +ynh_replace_string --match_string="__NODE_PATH__" --replace_string="$nodejs_path" --target_file="../conf/systemd.service" + +ynh_add_systemd_config #================================================= # GENERIC FINALIZATION #================================================= -# SETUP SSOWAT +# SECURE FILES AND DIRECTORIES #================================================= -# If app is public, add url to SSOWat conf as skipped_uris -if [[ $is_public -eq 1 ]]; then - # See install script - ynh_app_setting_set "$app" unprotected_uris "/" +# Set permissions on app files +chown -R root: $final_path +chown -R $admin: $final_path/.venv/share + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Upgrading SSOwat configuration..." --time --weight=1 + +# Make app public if necessary +if [ $is_public -eq 1 ] +then + # unprotected_uris allows SSO credentials to be passed anyway + ynh_app_setting_set --app=$app --key=unprotected_uris --value="/" fi +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --line_match="JupyterHub is now running at" --log_path="systemd" + #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading nginx web server..." --time --weight=1 -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload #================================================= -# ADVERTISE SERVICE IN ADMIN PANEL +# END OF SCRIPT #================================================= -yunohost service add $app --log "systemd" - -#================================================= -# START SERVICE -#================================================= - -ynh_systemd_action -n $app -a restart -l "JupyterHub is now running at" -p "systemd" +ynh_script_progression --message="Upgrade of $app completed" --time --last diff --git a/scripts/upgrade.d/upgrade.sh b/scripts/upgrade.d/upgrade.sh index 394fee4..a996562 100644 --- a/scripts/upgrade.d/upgrade.sh +++ b/scripts/upgrade.d/upgrade.sh @@ -1,11 +1 @@ -jupyterlab_version="0.35.4" - -miniconda3_version="4.5.11" - -miniconda3_x86_64_source_md5="e1045ee415162f944b6aebfe560b8fee" - -miniconda3_x86_source_md5="d8c3ea1bd25cf02c4ea92df4d31ef652" - -#For ARM -berryconda3_version="2.0.0" -berryconda3_arm_source_md5="1d8a60a9e201e3c30d927b5bf93b441d" +jupyterlab_version="1.0.4"