JupyterHub extension for ContainDS Dashboards

Overview

ContainDS Dashboards for JupyterHub

A Dashboard publishing solution for Data Science teams to share results with decision makers.

Run a private on-premise or cloud-based JupyterHub with extensions to instantly publish apps and notebooks as user-friendly interactive dashboards to share with non-technical colleagues.

Currently supported frameworks:

This open source package allows data scientists to instantly and reliably publish interactive notebooks or other scripts as secure interactive web apps.

Source files can be pulled from a Git repo or from the user's Jupyter tree.

Any authorised JupyterHub user can view the dashboard, or choose to give permission only to named users.

See full documentation

How it works

  • Data scientist creates a Jupyter Notebook as normal or uploads Python/R files etc
  • Data scientist creates a new Dashboard to clone their Jupyter server
  • Other logged-in JupyterHub users see the dashboard in their list
  • Click to launch as a server, using OAuth to gain access
  • User sees a safe user-friendly version of the original notebook - served by Voilà, Streamlit, Dash, Bokeh, Panel, R Shiny etc.

All of this works through a new Dashboards menu item added to JupyterHub's header.

Data scientist creates a Jupyter Notebook as normal

Original Jupyter Notebook

Data scientist creates a new Dashboard to clone their Jupyter server

Create New Dashboard

Other logged-in JupyterHub users see the dashboard in their list

Other User sees dashboard

Uses OAuth to gain access

Other user OAuths

Other user sees a safe user-friendly Voilà version of the original notebook

Voilà Dashboard

Or other app frameworks

App Collage

Requirements

Basic requirements:

  • JupyterHub 1.x
  • Python 3.6+

Note that JupyterHub 2.x is not supported. You will need to install a version 1.x (e.g. 1.5).

You should be able to use any authenticator for users to login - for example, corporate Google email sign in, or LDAP.

Any JupyterHub distribution should be suitable, depending on configuration. See requirements.

Installation

Full Setup and Installation details are in the documentation.

Contact and Support

Please see LICENSE for details.

Please do get in touch if you try out the package, or would like to but need some support. I would be very interested to find out how it can be used, and to work (without charge) to help you get it running. The project needs feedback in order to develop further!

Contact [email protected] with any comments or questions at all.

There is a Gitter room for general chat with other community members, e.g. for confguration and use case tips.

Join the chat at https://gitter.im/ideonate/ContainDS Documentation Status Latest release Latest release

Comments
  • Obtain user info for fastapi-served dashboard

    Obtain user info for fastapi-served dashboard

    Hi,

    I'm experimenting with fastapi (https://fastapi.tiangolo.com/) as a dashboard served with a uvicorn, and it works as expected.

    I'm curious if we could use cdsdashboards for authentication in this case.

    I was wondering what would be the best approach with cdsdashboards, to obtain the user-info, once authenticated, programmatically ?

    I was trying from /hub/dashboards-api/hub-info/user, unfortunately it gives error during redirection on the browser. INFO:tornado.application:b'INFO: 10.42.0.166:0 - "GET /user/ril/dash-biotools-api/whoami HTTP/1.1" 307 Temporary Redirect\n' user-fastapi

    Below is my current setup.

    # uvicorn to serve the main.py
    c.VariableMixin.extra_presentation_launchers = {
            'uvicorn': {
                    'cmd': ['start.sh', 'python3', '-m', 'jhsingle_native_proxy.main', '--logs', '--debug'],
                    'args': ['--destport=0', 'python3',
                             '{presentation_path}',
                             '{--}root-path={base_url}',
                             '{--}port={port}',
                    ],
            },
    }
    
    # main.py
    
    import typer
    import uvicorn
    from fastapi import FastAPI
    from starlette.responses import RedirectResponse
    
    
    api = FastAPI()
    
    
    @api.get('/foo')
    def foo():
        return 'bar'
    
    
    @api.get('/whoami')
    async def get_user():
        return RedirectResponse('/hub/dashboards-api/hub-info/user')
    
    
    def main(root_path: str = typer.Option(...), port: int = typer.Option(...)):
        uvicorn.run(api, host='0.0.0.0', root_path=root_path, port=port, access_log=True)
    
    
    if __name__ == '__main__':
        typer.run(main)
    

    Describe the solution you'd like A user json, such as {"kind": "user", "name": "ril"}

    Describe alternatives you've considered

    • Creating a service at jupyterhub to call the 'whoami' api, https://github.com/jupyterhub/jupyterhub/blob/master/examples/service-whoami-flask/whoami-oauth.py Unfortunately I could not make this example to work.

    Configuration Using Zero to jupyterhub

    • helm: 0.9.0
    • jhsingle-native-proxy==0.6.1
    • cdsdashboard==0.4.1

    Thank you in advance and cheers

    enhancement 
    opened by ricky-lim 22
  • dashboard creation yields 404

    dashboard creation yields 404

    Describe the bug

    During starting up a dashboard, it yields 404

    To Reproduce

    Local jupyterhub setup with minikube: https://github.com/ricky-lim/jupyterhub-minikube/tree/fastapi main.py: https://github.com/ricky-lim/jupyterhub-minikube/blob/fastapi/examples/main.py

    Screenshots https://drive.google.com/file/d/13u8ZBx7nADi-nJI3Z9k6dIF8vaWaQLFh/view?usp=sharing

    Any tweaks could you advise to avoid 404 during the start-up ?

    Thanks in advance. I look forward to hearing from you

    bug 
    opened by ricky-lim 15
  • Obtain authenticated username inside a dashboard

    Obtain authenticated username inside a dashboard

    Once authenticated into a dashboard, provide a way for dashboard apps to obtain the viewer's username from JupyterHub.

    This would most likely be via a cookie.

    Env vars aren't going to help here because each dashboard can have multiple visitors at the same time.

    From @ricky-lim on issue 24 : With relation to the singleuser docker image, I have a question regarding how could streamlit uses the authenticated state of a user ? Within the singleuser image, the NB_USER env is set into jovyan and JUPYTERHUB_USER is set to the creator of the dashboard, instead of the authenticated user. I was wondering what is your advice for a dashboard creator to use the authenticated state, such as a username following the dashboard authentication?

    enhancement 
    opened by danlester 13
  • Error when opening a dashboard behind secured reverse-proxy

    Error when opening a dashboard behind secured reverse-proxy

    Describe the bug A clear and concise description of what the bug is.

    Best is to understand the problem is to look at the gif below.

    To Reproduce Clear steps to reproduce the behavior, including any of your own ipynb or py files if they led to the error.

    • userA creates a dashboard (with All Users authorization)
    • userB tries to open it

    Screenshots Please add screenshots to help explain your problem. cdsdash_auth_error

    The failure raises from https://github.com/jupyterhub/jupyterhub/blob/e5a6119505f89a293447ce4e727c4bd15e86b145/jupyterhub/apihandlers/auth.py#L277-282

    But from the web dev tools, the Referer header matches the page URL.

    Configuration Include as much jupyterhub_config information as you can - at least enough to understand which Spawner type you are using, and how your JupyterHub is deployed (e.g. The Littlest JupyterHub, or Zero to JupyterHub).

    cdsdashboards 0.3.0 ldapauthenticator 1.3.0 jupyterhub 1.1.0 jupyterhub-base 1.1.0

    spawner_class = ( "cdsdashboards.hubextension.spawners.VariableLocalProcessSpawner" )

    bug 
    opened by fcollonval 13
  • Error encountered, when the user is set other than `jovyan`, while executing voila

    Error encountered, when the user is set other than `jovyan`, while executing voila

    Hi Dan,

    In my setup, the user of the jupyter is set with her/his username coupled to the permissions from an active directory.

    With each user has its own homedir, such as '/home/ril' instead of home/jovyan

    Unfortunately while trying to execute voila, I encountered the following error, which I think might be caused by trying to set username to jovyan.

    I was wondering if you have encountered this issue before and I'll be very grateful if you could help, please.

    Thank you in advance for your time and consideration.

    The log with its error messages

    Set username to: jovyan
    usermod: no changes
    Executing the command: python3 -m jhsingle_native_proxy.main --destport=0 python3 {-}m voila {presentation_path} {--}port={port} {--}no-browser {--}Voila.base_url={base_url}/ {--}Voila.server_url=/ --presentation-path=./gaussian_process_regression.ipynb --ip=0.0.0.0 --port=8888 --request-timeout=600 --last-activity-interval=600 --allow-root
    sudo: setrlimit(RLIMIT_CORE): Operation not permitted
    
    opened by ricky-lim 12
  • Streamlit runs on a different conda environment

    Streamlit runs on a different conda environment

    Is your feature request related to a problem? Please describe. Nope

    Describe the solution you'd like A dashboard creation form that could show user-specific conda environments that runs a streamlit dashboarding server.

    Describe alternatives you've considered Using the global conda environments, however streamlit does not run within a specified environment. It stills runs with base python, instead of the specified python environment.

    Below is the error, in which I tried to use a conda env that installed bqplot package.

    File "/opt/conda/lib/python3.8/site-packages/streamlit/ScriptRunner.py", line 319, in _run_script
        exec(code, module.__dict__)
    File "/home/jovyan/test_streamlit.py", line 2, in <module>
        import bqplot as bq
    

    The solution, that I thought that a user could create her/his own environment, for instance with miniconda to run streamlit server.

    Background context I like to explore streamlit as a dashboarding framework for a project and every project has a specific set of dependencies.

    Configuration The setup is using zero to kubernetes.

    Thanks in advance. I look forward to hearing from you.

    enhancement 
    opened by ricky-lim 12
  • 403 : Forbidden You do not have permission to access Server

    403 : Forbidden You do not have permission to access Server

    I have a strange behaviour when trying to share dashboards with other users on my jupyterhub instance, this does only seem to work between Admin users.

    If a non-admin is trying to access a shared dashboard via the Dashboards tab the following happens:

    • Server is starting up
    • Authorize page does not appear, instead we get a 403 : Forbidden You do not have permission to access Server

    This is the error log for a non-admin user

    [I 2022-02-24 18:03:06.433 JupyterHub log:189] 302 GET /hub/dashboards/dashboard-test -> /user/julius/dash-dashboard-test (julius-test@[secret]) 7.92ms
    INFO:tornado.application:SuperviseAndProxyHandler http_get 56595 
    DEBUG:tornado.application:No user identified
    WARNING:tornado.application:Detected unused OAuth state cookies
    DEBUG:tornado.application:Redirecting to login url: /hub/api/oauth2/authorize?client_id=jupyterhub-user-julius-dash-dashboard-test&redirect_uri=%2Fuser%2Fjulius%2Fdash-dashboard-test%2Foauth_callback&response_type=code&state=[secret]
    ERROR:tornado.application:Uncaught exception GET /user/julius/dash-dashboard-test/ ([secret])
    HTTPServerRequest(protocol='http', host=[secret], method='GET', uri='/user/julius/dash-dashboard-test/', version='HTTP/1.1', remote_ip=[secret])
    Traceback (most recent call last):
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/tornado/web.py", line 1704, in _execute
        result = await result
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/websocket.py", line 102, in get
        return await self.http_get(*args, **kwargs)
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/proxyhandlers.py", line 849, in http_get
        return await self.proxy(self.port, path)
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/proxyhandlers.py", line 843, in proxy
        return await self.oauth_proxy(port, path)
    TypeError: object NoneType can't be used in 'await' expression
    [E 2022-02-24 18:03:06.622 JupyterHub auth:280] User <User(julius-test 0/1 running)> not allowed to access Server at /user/julius/dash-dashboard-test/
    [W 2022-02-24 18:03:06.623 JupyterHub web:1787] 403 GET /hub/api/oauth2/authorize?client_id=jupyterhub-user-julius-dash-dashboard-test&redirect_uri=%2Fuser%2Fjulius%2Fdash-dashboard-test%2Foauth_callback&response_type=code&state=[secret] ([secret]): You do not have permission to access Server at /user/julius/dash-dashboard-test/
    [W 2022-02-24 18:03:06.660 JupyterHub log:189] 403 GET /hub/api/oauth2/authorize?client_id=jupyterhub-user-julius-dash-dashboard-test&redirect_uri=%2Fuser%2Fjulius%2Fdash-dashboard-test%2Foauth_callback&response_type=code&state=[secret] (julius-test@[secret]) 48.27ms
    

    vs once I made user julius-test an admin via the jupyterhub admin panel

    [I 2022-02-24 18:01:02.364 JupyterHub log:189] 200 GET /hub/dashboards/dashboard-test (julius-test@[secret]) 49.53ms
    [I 2022-02-24 18:01:02.365 JupyterHub spawner:1526] Spawning python3 -m jhsingle_native_proxy.main --destport=0 python3 '{-}m' voila '{presentation_path}' '{--}port={port}' '{--}no-browser' '{--}Voila.base_url={base_url}/' '{--}Voila.server_url=/' --progressive --presentation-path=./Dashboards/Dashboard.ipynb --ip=127.0.0.1 --port=56588 '{--}debug' --debug
    Setting debug
    Starting jhsingle-native-proxy server on address 127.0.0.1 port 56588, proxying to port 0
    URL Prefix: /user/julius/dash-dashboard-test
    Auth Type: oauth
    Command: ('python3', '{-}m', 'voila', '{presentation_path}', '{--}port={port}', '{--}no-browser', '{--}Voila.base_url={base_url}/', '{--}Voila.server_url=/', '{--}debug')
    INFO:tornado.application:SuperviseAndProxyHandler http_get 56595 
    DEBUG:tornado.application:No user identified
    DEBUG:tornado.application:Redirecting to login url: /hub/api/oauth2/authorize?client_id=jupyterhub-user-julius-dash-dashboard-test&redirect_uri=%2Fuser%2Fjulius%2Fdash-dashboard-test%2Foauth_callback&response_type=code&state=[secret]
    [I 2022-02-24 18:01:02.770 JupyterHub base:944] User julius:dash-dashboard-test took 0.427 seconds to start
    [I 2022-02-24 18:01:02.770 JupyterHub proxy:286] Adding user julius to proxy /user/julius/dash-dashboard-test/ => http://127.0.0.1:56588
    18:01:02.771 [ConfigProxy] info: Adding route /user/julius/dash-dashboard-test -> http://127.0.0.1:56588
    18:01:02.771 [ConfigProxy] info: Route added /user/julius/dash-dashboard-test -> http://127.0.0.1:56588
    18:01:02.771 [ConfigProxy] info: 201 POST /api/routes/user/julius/dash-dashboard-test 
    ERROR:tornado.application:Uncaught exception GET /user/julius/dash-dashboard-test/ (127.0.0.1)
    HTTPServerRequest(protocol='http', host='127.0.0.1:56588', method='GET', uri='/user/julius/dash-dashboard-test/', version='HTTP/1.1', remote_ip='127.0.0.1')
    Traceback (most recent call last):
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/tornado/web.py", line 1704, in _execute
        result = await result
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/websocket.py", line 102, in get
        return await self.http_get(*args, **kwargs)
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/proxyhandlers.py", line 849, in http_get
        return await self.proxy(self.port, path)
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/proxyhandlers.py", line 843, in proxy
        return await self.oauth_proxy(port, path)
    TypeError: object NoneType can't be used in 'await' expression
    [I 2022-02-24 18:01:02.774 JupyterHub events:107] Server julius:dashboard-test is ready
    [I 2022-02-24 18:01:02.774 JupyterHub log:189] 200 GET /hub/dashboards-api/dashboard-test/progress (julius-test@[secret]) 145.21ms
    INFO:tornado.application:SuperviseAndProxyHandler http_get 56595 
    DEBUG:tornado.application:No user identified
    WARNING:tornado.application:Detected unused OAuth state cookies
    DEBUG:tornado.application:Redirecting to login url: /hub/api/oauth2/authorize?client_id=jupyterhub-user-julius-dash-dashboard-test&redirect_uri=%2Fuser%2Fjulius%2Fdash-dashboard-test%2Foauth_callback&response_type=code&state=[secret]
    ERROR:tornado.application:Uncaught exception GET /user/julius/dash-dashboard-test/ ([secret])
    HTTPServerRequest(protocol='http', host=[secret], method='GET', uri='/user/julius/dash-dashboard-test/', version='HTTP/1.1', remote_ip=[secret])
    Traceback (most recent call last):
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/tornado/web.py", line 1704, in _execute
        result = await result
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/websocket.py", line 102, in get
        return await self.http_get(*args, **kwargs)
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/proxyhandlers.py", line 849, in http_get
        return await self.proxy(self.port, path)
      File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/site-packages/jhsingle_native_proxy/proxyhandlers.py", line 843, in proxy
        return await self.oauth_proxy(port, path)
    TypeError: object NoneType can't be used in 'await' expression
    [I 2022-02-24 18:01:02.974 JupyterHub log:189] 200 GET /hub/api/oauth2/authorize?client_id=jupyterhub-user-julius-dash-dashboard-test&redirect_uri=%2Fuser%2Fjulius%2Fdash-dashboard-test%2Foauth_callback&response_type=code&state=[secret] (julius-test@[secret]) 17.32ms
    

    Configuration

    • Installed jupyterhub via pip
    • jupyterhub_config: Basic config from here
    • Using GenericOAuthenticator to sign in via a self-hosted Keycloak Instance using openid-connect
    bug 
    opened by jhannink 6
  • sudospawner voila issue

    sudospawner voila issue

    Describe the bug Trying to save a dashboard with voila and the call to voila is not quite right. python3 should be full path to jupyterhub environment, and --progressive needs an argument, it appears.

    To Reproduce This was set up as a sudospawner jupyterhub install and conda environments. Everything works as expected, in use for months on this particular server. Added cdsdashboards to the jupyterhub environment and cdsdashboards[user] to each conda data science environments (registered through ipykernel).

    Screenshots

    Log shows:

    [I 210628 22:55:14 mediator:89] Spawning /usr/bin/jupyterhub-singleuser --destport=0 python3 '{-}m' voila '{presentation_path}' '{--}port={port}' '{--}no-browser' '{--}Voila.base_url={base_url}/' '{--}Voila.server_url=/' --progressive --presentation-path=./notebooks/testing/dash --port=53703
    usage: jupyterhub-singleuser [-h] [--debug] [--generate-config] [-y]
                                 [--no-browser] [--no-mathjax] [--allow-root]
                                 [--autoreload] [--script] [--no-script]
                                 [--disable-user-config]
                                 [--log-level Application.log_level]
                                 [--config JupyterApp.config_file]
                                 [--ip SingleUserNotebookApp.ip]
                                 [--port SingleUserNotebookApp.port]
                                 [--port-retries SingleUserNotebookApp.port_retries]
                                 [--sock SingleUserNotebookApp.sock]
                                 [--sock-mode SingleUserNotebookApp.sock_mode]
                                 [--transport KernelManager.transport]
                                 [--keyfile SingleUserNotebookApp.keyfile]
                                 [--certfile SingleUserNotebookApp.certfile]
                                 [--client-ca SingleUserNotebookApp.client_ca]
                                 [--notebook-dir SingleUserNotebookApp.notebook_dir]
                                 [--browser SingleUserNotebookApp.browser]
                                 [--pylab [SingleUserNotebookApp.pylab]]
                                 [--gateway-url GatewayClient.url]
                                 [--user SingleUserNotebookApp.user]
                                 [--group SingleUserNotebookApp.group]
                                 [--cookie-name HubOAuth.cookie_name]
                                 [--hub-prefix SingleUserNotebookApp.hub_prefix]
                                 [--hub-host SingleUserNotebookApp.hub_host]
                                 [--hub-api-url SingleUserNotebookApp.hub_api_url]
                                 [--base-url SingleUserNotebookApp.base_url]
                                 [extra_args ...]
    jupyterhub-singleuser: error: argument --progressive: expected one argument
    

    Configuration

    c.JupyterHub.spawner_class = 'cdsdashboards.hubextension.spawners.variablesudospawner.VariableSudoSpawner'
    
    c.JupyterHub.allow_named_servers = True
    
    c.CDSDashboardsConfig.builder_class = 'cdsdashboards.builder.processbuilder.ProcessBuilder'
    
    from cdsdashboards.app import CDS_TEMPLATE_PATHS
    from cdsdashboards.hubextension import cds_extra_handlers
    
    c.JupyterHub.template_paths = CDS_TEMPLATE_PATHS
    c.JupyterHub.extra_handlers = cds_extra_handlers
    
    bug 
    opened by fdion 6
  • Dashboard is using wrong image

    Dashboard is using wrong image

    Describe the bug If I insert ideonate/containds-allr-datascience:0.5.6 as second option in my singleuser.profile list, my dashboard will be launched with the wrong image. To Reproduce hub.config.image.name=ideonate/cdsdashboards-jupyter-k8s-hub hub.config.image.tag="0.11.1-0.5.6"

    singleuser.profileList: - display_name: "Default" description: "Default" kubespawner_override: image: myimage:mytag - display_name: "ContainDS Dashboards enabled image" description: "Demo" kubespawner_override: image: ideonate/containds-allr-datascience:0.5.6

    Screenshots

    Configuration Zero to JupyterHub, helm chart jupyterhub/jupyterhub version 0.11.1-n349.he14d686f

    bug 
    opened by stefanmeisner 5
  • Wrong path for static files if jupyterhub is under a subpath

    Wrong path for static files if jupyterhub is under a subpath

    Describe the bug

    We have Jupyterhub under /notebook/jupyter in our MLOps platfor https://iko.ai/notebook/jupyter which causes this relative URL to point to a wrong URL and results in select elements not rendered properly, see the screenshot below https://github.com/ideonate/cdsdashboards/blob/8cb741f8bdd5cf143e95d004e9ece211ae1be479/share/cdsdashboards/templates-common/editdashboard.html#L238

    This only happens in the new dashboard page but not the edit page because the edit page URL is notebook/jupyter/hub/dashboards/[APP_NAME]/edit whereas the new page URL is notebook/jupyter/hub/dashboards-new

    ../../dashboards-static/xxxxx in the edit page will point to notebook/jupyter/hub/dashboards-static/xxxxx but it'll point to notebook/dashboards-static/xxxxx in the new dashboard page.

    To Reproduce

    1. Put Jupyterhub under a subpath using a reverse proxy like nginx, say /notebook/jupyter
    2. Go to the new dashboard page

    Screenshots

    Screenshot from 2021-04-11 14-04-46

    Configuration

    from cdsdashboards.app import CDS_TEMPLATE_PATHS
    from cdsdashboards.hubextension import cds_extra_handlers
    
    c.JupyterHub.template_paths = CDS_TEMPLATE_PATHS
    c.JupyterHub.extra_handlers = cds_extra_handlers
    
    c.JupyterHub.allow_named_servers = True
    c.CDSDashboardsConfig.builder_class = 'cdsdashboards.builder.kubebuilder.KubeBuilder'
    
    # # Add `start.sh` to switch to NB_USER before running the command
    c.VariableMixin.default_presentation_cmd = ['start.sh', 'python3', '-m', 'jhsingle_native_proxy.main']
    
    # Options to remove Named Server / Dashboard sections for users on their home page. 
    # You can remove the named server section and/or the new bottom section where 
    # servers started to act as dashboards are hidden.
    c.JupyterHub.template_vars = {
        'cds_hide_user_named_servers': True,
        'cds_hide_user_dashboard_servers': False,
    }
    
    # Specify how to name dashbaord servers
    c.CDSDashboardsConfig.server_name_template = 'iko-{urlname}'
    
    # Control whether ‘All Users’ or ‘Selected Users’ is selected by default on the ‘New Dashboard’ page.
    c.CDSDashboardsConfig.default_allow_all = False
    
    # Show Spawner User Options Form before creating a dashboard
    c.CDSDashboardsConfig.spawn_default_options = False
    
    c.CDSDashboardsConfig.presentation_types = ['voila', 'streamlit', 'plotlydash', 'bokeh']
    
    from cdsdashboards.hubextension.spawners.variablekube import VariableKubeSpawner
    
    class CustomKubeSpawner(VariableKubeSpawner):
        "Our custom KubeSpawner implementation"
        pass
    
    c.JupyterHub.spawner_class = CustomKubeSpawner
    
    bug 
    opened by mohammedi-haroune 5
  • Relative Path Git root is not relative

    Relative Path Git root is not relative

    Describe the bug Relative path for git root is not relative

    FileNotFoundError: [Errno 2] No such file or directory: '/home/jupyter-xxx/github-com-ideonate-cdsdashboards/./github-com-ideonate-cdsdashboards/examples/sample-source-code/plotlydash'

    To Reproduce User guide example produces the error.

    Configuration Using The Littlest JupyterHub

    bug 
    opened by olivmarcel 5
  • ZTJH presentation path defaults to jovyan when using Voila

    ZTJH presentation path defaults to jovyan when using Voila

    Describe the bug When setting up ContainDS with a Kubernetes cluster and a Voila presentation, the presentation_path variable uses /home/jovyan instead of the user-specific path. Related issue: ideonate/cdsdashboards#43.

    To Reproduce Follow instructions to install ContainDS Kubernetes. Edit the configuration file to include

    ...
        cds-kube: |
          c.JupyterHub.spawner_class = 'cdsdashboards.hubextension.spawners.variablekube.VariableKubeSpawner'
          c.CDSDashboardsConfig.builder_class = 'cdsdashboards.builder.kubebuilder.KubeBuilder'
          c.VariableMixin.default_presentation_cmd = ['start.sh', 'python3', '-m', 'jhsingle_native_proxy.main']
          c.VariableMixin.extra_presentation_launchers = {
            'voila': {
              'args': [
                '--destport=0', 'python', '{-}m','voila', '{presentation_path}',
                '{--}port={port}',
                '{--}no-browser',
                '{--}Voila.base_url={base_url}/',
                '{--}Voila.server_url=/',
                '{--}Voila.ip=0.0.0.0',
                ....
              ]
            }
          }
    ...
    

    Create a new dashboard using a defined notebook. Upon visiting the dashboard, note 400 Bad Request error message in browser and the following error in the log:

    ERROR:tornado.application:b'WARNING:tornado.general:400 GET / (127.0.0.1): Unreadable Notebook: /home/jovyan/HubbleDS.ipynb TypeError("__init__() got an unexpected keyword argument \'capture_validation_error\'")\n'
    WARNING:tornado.access:400 GET /user/admin/dash-hubbleds/ (::ffff:192.168.126.246) 1352.61ms
    

    Screenshots

    Configuration

    hub:
      config:
        Authenticator:
          admin_users:
            - admin
      allowNamedServers: true
      image:
        name: ideonate/cdsdashboards-jupyter-k8s-hub
        tag: 1.2.0-0.6.3
      extraConfig:
        cds-handlers: |
          from cdsdashboards.hubextension import cds_extra_handlers
          c.JupyterHub.extra_handlers = cds_extra_handlers
        cds-templates: |
          from cdsdashboards.app import CDS_TEMPLATE_PATHS
          c.JupyterHub.template_paths = CDS_TEMPLATE_PATHS
        cds-kube: |
          c.JupyterHub.spawner_class = 'cdsdashboards.hubextension.spawners.variablekube.VariableKubeSpawner'
          c.CDSDashboardsConfig.builder_class = 'cdsdashboards.builder.kubebuilder.KubeBuilder'
          c.VariableMixin.extra_presentation_launchers = {
            'voila': {
              'args': [
                '--destport=0', 'python', '{-}m','voila', '{presentation_path}',
                '{--}port={port}',
                '{--}no-browser',
                '{--}Voila.base_url={base_url}/',
                '{--}Voila.server_url=/',
                '{--}Voila.ip=0.0.0.0',
                '--ready-check-path=/voila/static/',
              ]
            }
          }
    singleuser:
      image:
        name: ideonate/containds-allr-datascience
        tag: 0.6.3
      storage:
        type: dynamic
        capacity: 10Gi
        dynamic:
          pvcNameTemplate: claim-{username}
          volumeNameTemplate: volume-{username}
          storageAccessModes: [ReadWriteMany]
    
    bug 
    opened by nmearl 0
  • Icons to indicate which dashboards are running

    Icons to indicate which dashboards are running

    Is your feature request related to a problem? Please describe.

    When I go to the Dashboards home screen, I see Your own dashboards and Dashboards from others. If I want to visit a dashboard from someone else, I click on their link. It is only then I see the message "this dashboard isn't running".

    Describe the solution you'd like

    I'd like to have an indicator icon next to each dashboard listed to indicate whether the dashboard is currently running.

    I think just refreshing what's running when the page is loaded is sufficient without needing to keep a constant watch on which ones are running.

    Describe alternatives you've considered

    Background context

    I'm using CDS Dashboards as an extension on our QHub/Nebari JHub service. As a software engineer, my team and I share dashboards with each other regularly. Its somewhat annoying to click on 8 different dashboards, all of which show up as "not running" after it tries to load.

    As an admin of our cloud-based JHub deployment, I'm interested in providing users some visual feedback on their resource consumption. Did you mean to leave that dashboard running for weeks?? A little icon could go a long way in catching things like this.

    Configuration

    QHub/Nebari

    enhancement 
    opened by kcpevey 0
  • pythonic example for User-info API

    pythonic example for User-info API

    Hi Ideonate team, This is a great product! I'm really enjoying it... but to make it even easier for streamlit users who don't want to be web-developers, could you please add a complete (python) example of how to use the user info api described at https://cdsdashboards.readthedocs.io/en/stable/chapters/userguide/userinfoapi.html

    with streamlit, cdsdashboard, tornado, and a reverse-proxy on K8s, I'm really struggling to actually get the client user info... and I don't see how to embed the JS code in python as the example is for Voila with ipywidgets.

    Many thanks!

    enhancement 
    opened by kla240 1
  • How to make the dashboard work with jupyterlab collaborative flag

    How to make the dashboard work with jupyterlab collaborative flag

    Describe the bug

    When deployed with jupyterhub, if I put the following line in jupyterhub config to enable the latest collaboration feature of jupyterlab

    c.KubeSpawner.args = ['--collaborative']
    

    This will append additional arg when starting the single user server.

    However, CDSdashbaord will also pick up the additional arg. When the default_presentation_cmd is set as

    c.VariableMixin.default_presentation_cmd = ['python3', '-m', 'jhsingle_native_proxy.main']
    

    The command will become

    python3 -m jhsingle_native_proxy.main xxxx.py --collabrative
    

    However, since --collabrative is not compatible with the presentation command, the single user server will fail to start

    To Reproduce

    In jupyterhub_config.py put

    c.KubeSpawner.args = ['--collaborative']
    c.VariableMixin.default_presentation_cmd = ['python3', '-m', 'jhsingle_native_proxy.main']
    

    Then start a dashboard

    Screenshots

    Configuration

    Zero to JupyterHub on AWS EKS

    bug 
    opened by yuhuishi-convect 1
  • Openshift images for JupyterHub with cdsdashboards installed

    Openshift images for JupyterHub with cdsdashboards installed

    Here are links to openshift images based on the z2jh images already available with cdsdashboards installed:

    Hub: https://github.com/tdeneke/jupyterhub-quickstart/blob/5f08ae8ab9756f994962e5d500aff22f70d18856/Dockerfile

    Notebook: https://github.com/tdeneke/jupyter-notebooks/blob/354fc8e4373cae9408dec00198763e3de14679d1/minimal-notebook/Dockerfile-py36

    enhancement 
    opened by danlester 0
  • support jupyterhub 2.0

    support jupyterhub 2.0

    I don't believe there's an issue open to add support for jupyterhub > 2

    I believe cdsdashboards is currently pinned at <2 (https://github.com/ideonate/cdsdashboards/commit/e1d3ddb1999e7c77d4ef3c659c948e923825d6d2)

    enhancement 
    opened by raybellwaves 5
Owner
Ideonate
Ideonate
Getting started with Python, Dash and Plot.ly for the Data Dashboards team

data_dashboards Getting started with Python, Dash and Plot.ly for the Data Dashboards team Getting started MacOS users: # Install the pyenv version ma

Department for Levelling Up, Housing and Communities 1 Nov 8, 2021
Visual Python is a GUI-based Python code generator, developed on the Jupyter Notebook environment as an extension.

Visual Python is a GUI-based Python code generator, developed on the Jupyter Notebook environment as an extension.

Visual Python 564 Jan 3, 2023
Altair extension for saving charts in a variety of formats.

Altair Saver This packge provides extensions to Altair for saving charts to a variety of output types. Supported output formats are: .json/.vl.json: V

Altair 85 Dec 9, 2022
🐞 📊 Ladybug extension to generate 2D charts

ladybug-charts Ladybug extension to generate 2D charts. Installation pip install ladybug-charts QuickStart import ladybug_charts API Documentation Loc

Ladybug Tools 3 Dec 30, 2022
Time series visualizer is a flexible extension that provides filling world map by country from real data.

Time-series-visualizer Time series visualizer is a flexible extension that provides filling world map by country from csv or json file. You can know d

Long Ng 3 Jul 9, 2021
A Python Binder that merge 2 files with any extension by creating a new python file and compiling it to exe which runs both payloads.

Update ! ANONFILE MIGHT NOT WORK ! About A Python Binder that merge 2 files with any extension by creating a new python file and compiling it to exe w

Vesper 15 Oct 12, 2022
Django app for building dashboards using raw SQL queries

django-sql-dashboard Django app for building dashboards using raw SQL queries Brings a useful subset of Datasette to Django. Currently only works with

Simon Willison 383 Jan 6, 2023
Data Visualization Guide for Presentations, Reports, and Dashboards

This is a highly practical and example-based guide on visually representing data in reports and dashboards.

Anton Zhiyanov 395 Dec 29, 2022
Lumen provides a framework for visual analytics, which allows users to build data-driven dashboards from a simple yaml specification

Lumen project provides a framework for visual analytics, which allows users to build data-driven dashboards from a simple yaml specification

HoloViz 120 Jan 4, 2023
Getting started with Python, Dash and Plot.ly for the Data Dashboards team

data_dashboards Getting started with Python, Dash and Plot.ly for the Data Dashboards team Getting started MacOS users: # Install the pyenv version ma

Department for Levelling Up, Housing and Communities 1 Nov 8, 2021
Python: Wrangled and unpivoted gaming datasets. Tableau: created dashboards - Market Beacon and Player’s Shopping Guide.

Created two information products for GameStop. Using Python, wrangled and unpivoted datasets, and created Tableau dashboards.

Zinaida Dvoskina 2 Jan 29, 2022
The scope of this project will be to build a data ware house on Google Cloud Platform that will help answer common business questions as well as powering dashboards

The scope of this project will be to build a data ware house on Google Cloud Platform that will help answer common business questions as well as powering dashboards.

Shweta_kumawat 2 Jan 20, 2022
This is a file deletion program that asks you for an extension of a file (.mp3, .pdf, .docx, etc.) to delete all of the files in a dir that have that extension.

FileBulk This is a file deletion program that asks you for an extension of a file (.mp3, .pdf, .docx, etc.) to delete all of the files in a dir that h

Enoc Mena 1 Jun 26, 2022
A Temporal Extension Library for PyTorch Geometric

Documentation | External Resources | Datasets PyTorch Geometric Temporal is a temporal (dynamic) extension library for PyTorch Geometric. The library

Benedek Rozemberczki 1.9k Jan 7, 2023
Little Ball of Fur - A graph sampling extension library for NetworKit and NetworkX (CIKM 2020)

Little Ball of Fur is a graph sampling extension library for Python. Please look at the Documentation, relevant Paper, Promo video and External Resour

Benedek Rozemberczki 619 Dec 14, 2022
A library of extension and helper modules for Python's data analysis and machine learning libraries.

Mlxtend (machine learning extensions) is a Python library of useful tools for the day-to-day data science tasks. Sebastian Raschka 2014-2020 Links Doc

Sebastian Raschka 4.2k Jan 2, 2023
A Python implementation of John Gruber’s Markdown with Extension support.

Python-Markdown This is a Python implementation of John Gruber's Markdown. It is almost completely compliant with the reference implementation, though

Python-Markdown 3.1k Dec 30, 2022
The Levenshtein Python C extension module contains functions for fast computation of Levenshtein distance and string similarity

Contents Maintainer wanted Introduction Installation Documentation License History Source code Authors Maintainer wanted I am looking for a new mainta

Antti Haapala 1.2k Dec 16, 2022
Example python package with pybind11 cpp extension

Developing C++ extension in Python using pybind11 This is a summary of the commands used in the tutorial.

null 55 Sep 4, 2022