This is an automated email from the ASF dual-hosted git repository.
yasithdev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata.git
The following commit(s) were added to refs/heads/master by this push:
new 69b5cf1551 Remove airavata-jupyterhub (moved to
apache/airavata-portals) (#631)
69b5cf1551 is described below
commit 69b5cf15514814a3cdc26375d676eac845f3b111
Author: Yasith Jayawardana <[email protected]>
AuthorDate: Sun Jun 7 17:24:01 2026 -0400
Remove airavata-jupyterhub (moved to apache/airavata-portals) (#631)
The JupyterHub deployment directory has no Maven or build coupling to the
middleware and belongs with the gateway-facing portals; it has been moved to
apache/airavata-portals, so this removes it here along with its CLAUDE.md
section and the stale .dockerignore comment.
---
.dockerignore | 4 +-
CLAUDE.md | 4 -
airavata-jupyterhub/Dockerfile | 14 ---
airavata-jupyterhub/custom_templates/login.html | 52 ---------
airavata-jupyterhub/docker-compose.yaml | 24 ----
airavata-jupyterhub/jupyterhub_config.py | 139 ------------------------
airavata-jupyterhub/user-container/Dockerfile | 12 --
airavata-jupyterhub/user-container/Makefile | 3 -
airavata-jupyterhub/user-container/init.sh | 28 -----
9 files changed, 2 insertions(+), 278 deletions(-)
diff --git a/.dockerignore b/.dockerignore
index b3542f6780..37e6571ac8 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,7 +1,7 @@
# The airavata-server image build context is the repo root, but the image only
needs
# the prebuilt fat JAR. Whitelist just that (+ the Dockerfile) so the in-DinD
build
-# does not ship the entire tree. (Only root-context builds use this file; the
agent /
-# jupyterhub images use their own subdirectory contexts.)
+# does not ship the entire tree. (Only root-context builds use this file; the
agent
+# image uses its own subdirectory context.)
*
!Dockerfile
!airavata-server
diff --git a/CLAUDE.md b/CLAUDE.md
index 35079a0d17..5c0496ed6c 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -103,10 +103,6 @@ Go-based remote agent binary. Handles job execution,
Jupyter sessions, tunnels o
Python gRPC client. `airavata/` has generated stubs, `airavata_sdk/clients/`
has integration wrappers, `airavata_experiments/` has experiment workflow APIs.
-### `airavata-jupyterhub`
-
-JupyterHub authenticator and spawner plugins.
-
## Architecture Patterns
### Request Flow
diff --git a/airavata-jupyterhub/Dockerfile b/airavata-jupyterhub/Dockerfile
deleted file mode 100644
index d0f9300781..0000000000
--- a/airavata-jupyterhub/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-FROM jupyterhub/jupyterhub:latest
-
-RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
-RUN pip install oauthenticator requests pyjwt dockerspawner
jupyterhub-idle-culler ipywidgets
-
-COPY jupyterhub_config.py /srv/jupyterhub/jupyterhub_config.py
-COPY custom_templates /srv/jupyterhub/custom_templates
-
-ENV JUPYTERHUB_CONFIG=/srv/jupyterhub/jupyterhub_config.py
-ENV PYTHONPATH=/srv/jupyterhub
-
-EXPOSE 20000
-
-CMD ["jupyterhub"]
\ No newline at end of file
diff --git a/airavata-jupyterhub/custom_templates/login.html
b/airavata-jupyterhub/custom_templates/login.html
deleted file mode 100644
index d7834044c8..0000000000
--- a/airavata-jupyterhub/custom_templates/login.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="utf-8">
- <title>CyberShuttle Hub Login</title>
- <link rel="icon" href="{{ static_url('images/airavata-logo.png') }}">
- <link rel="stylesheet" href="{{ static_url('css/style.min.css') }}">
- <style>
- body {
- font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
- background-color: #f7f9fc;
- color: #333;
- text-align: center;
- padding-top: 80px;
- }
- .container {
- display: inline-block;
- padding: 50px;
- border-radius: 8px;
- background-color: #ffffff;
- box-shadow: 0 3px 8px rgba(0,0,0,0.1);
- }
- img {
- width: 70px;
- margin-bottom: 20px;
- }
- h1 {
- font-size: 26px;
- margin-bottom: 20px;
- }
- a.btn-login {
- display: inline-block;
- background-color: #0d6efd;
- color: #ffffff;
- padding: 10px 20px;
- border-radius: 5px;
- text-decoration: none;
- font-size: 16px;
- }
- a.btn-login:hover {
- background-color: #0b5ed7;
- }
- </style>
-</head>
-<body>
-<div class="container">
- <img src="https://airavata.host:8009/static/images/airavata-logo.png"
alt="CyberShuttle Logo"/>
- <h1>Welcome to Dev CyberShuttle Hub</h1>
- <a class="btn-login" href="{{ authenticator_login_url }}">Login with OAuth
2.0</a>
-</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/airavata-jupyterhub/docker-compose.yaml
b/airavata-jupyterhub/docker-compose.yaml
deleted file mode 100644
index 568cf97028..0000000000
--- a/airavata-jupyterhub/docker-compose.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-services:
- jupyterhub:
- build: .
- container_name: jupyterhub
- ports:
- - "8000:20000"
- environment:
- OAUTH_CLIENT_ID: "cs-jupyterlab"
- OAUTH_CLIENT_SECRET: "DxeMtfiWU1qkDEmaGHf13RDahCujzhy1"
- JUPYTERHUB_CRYPT_KEY:
"a99323294a5d6f9b1d0e7e33450dff44db664264231b985e069c6eba8f9a3e09"
- DOCKER_NETWORK_NAME: jupyterhub_network
- DOCKER_NOTEBOOK_IMAGE: cybershuttle/dev_jupyterlab-base
- volumes:
- - ./jupyterlab:/home/jovyan
- - ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py
- - ./custom_templates:/srv/jupyterhub/custom_templates
- - /var/run/docker.sock:/var/run/docker.sock
- restart: always
- networks:
- - jupyterhub_network
-
-networks:
- jupyterhub_network:
- name: jupyterhub_network
\ No newline at end of file
diff --git a/airavata-jupyterhub/jupyterhub_config.py
b/airavata-jupyterhub/jupyterhub_config.py
deleted file mode 100644
index ec39584752..0000000000
--- a/airavata-jupyterhub/jupyterhub_config.py
+++ /dev/null
@@ -1,139 +0,0 @@
-import os
-import re
-import sys
-from dockerspawner import DockerSpawner
-from oauthenticator.generic import GenericOAuthenticator
-from traitlets.config import Config
-
-c: Config
-
-# Authenticator Configuration
-c.JupyterHub.authenticator_class = GenericOAuthenticator
-c.GenericOAuthenticator.client_id = os.getenv('OAUTH_CLIENT_ID')
-c.GenericOAuthenticator.client_secret = os.getenv('OAUTH_CLIENT_SECRET')
-c.GenericOAuthenticator.oauth_callback_url =
'http://airavata.host:20000/hub/oauth_callback'
-c.GenericOAuthenticator.authorize_url =
'http://airavata.host:18080/realms/default/protocol/openid-connect/auth'
-c.GenericOAuthenticator.token_url =
'http://airavata.host:18080/realms/default/protocol/openid-connect/token'
-c.GenericOAuthenticator.userdata_url =
'http://airavata.host:18080/realms/default/protocol/openid-connect/userinfo'
-c.GenericOAuthenticator.scope = ['openid', 'profile', 'email']
-c.GenericOAuthenticator.username_claim = 'email'
-
-# User Permissions
-c.Authenticator.enable_auth_state = True
-c.GenericOAuthenticator.allow_all = True
-c.Authenticator.admin_users = {'[email protected]'}
-
-
-# Custom Spawner
-class CustomDockerSpawner(DockerSpawner):
-
- def _options_form_default(self):
- return ""
-
- def options_from_form(self, formdata):
- options = {}
-
- if hasattr(self, 'handler') and self.handler:
- qs_args = self.handler.request.arguments # eg. {'git':
[b'https://github...'], 'dataPath': [b'bmtk']}
- if 'git' in qs_args:
- options['git'] = qs_args['git'][0].decode('utf-8')
- if 'dataPath' in qs_args:
- # decode ALL dataPath values into a list of strings
- options['dataPath'] = [v.decode('utf-8') for v in
qs_args['dataPath']]
-
- return options
-
- def sanitize_name(self, name):
- """Docker safe volume/container names."""
- return re.sub(r"[^a-zA-Z0-9_.-]", "_", name)
-
- async def start(self):
- # Create a unique volume name keyed by (username + servername).
- # If the user spawns again with the same (servername), it will reuse
the same volume.
- safe_user = self.sanitize_name(self.user.name)
- safe_srv = self.sanitize_name(self.name or "default")
- reference_git_url =
"https://github.com/cyber-shuttle/cybershuttle-reference.git"
- git_url = self.user_options.get("git") or reference_git_url
- data_subfolders = self.user_options.get("dataPath", [])
- print("THE DATA PATH IS: ", data_subfolders)
-
- self.image = "cybershuttle/jupyterlab-base"
- if not hasattr(self, "environment"):
- self.environment = {}
- self.environment["GIT_URL"] = git_url
- self.post_start_cmd = "/usr/local/bin/init.sh"
- self.volumes = {}
-
- # register the home directory as volume (rw)
- vol_name = f"jupyterhub-vol-{safe_user}-{safe_srv}"
- self.volumes[vol_name] = "/home/jovyan/work"
-
- # register given datasets as volumes (ro)
- for subfolder in data_subfolders:
- host_data_path = f"/mnt/{subfolder}"
- container_path = f"/cybershuttle_data/{subfolder}"
- self.volumes[host_data_path] = {
- 'bind': container_path,
- 'mode': 'ro'
- }
-
- return await super().start()
-
-
-# Spawner Configuration
-c.JupyterHub.allow_named_servers = True
-c.JupyterHub.named_server_limit_per_user = 10
-c.JupyterHub.spawner_class = CustomDockerSpawner
-c.DockerSpawner.notebook_dir = '/home/jovyan/work'
-c.DockerSpawner.default_url = "/lab"
-c.DockerSpawner.start_timeout = 600
-
-c.DockerSpawner.environment = {
- 'CHOWN_HOME': 'no',
- 'CHOWN_HOME_OPTS': '',
-}
-c.DockerSpawner.extra_create_kwargs = {'user': 'root'}
-c.DockerSpawner.use_internal_ip = True
-c.DockerSpawner.network_name = os.getenv('DOCKER_NETWORK_NAME',
'jupyterhub_network')
-
-# Hub Configuration
-c.JupyterHub.hub_ip = '0.0.0.0'
-c.JupyterHub.hub_port = 8081
-c.JupyterHub.hub_connect_ip = 'jupyterhub'
-c.JupyterHub.shutdown_on_logout = True
-
-# External URL
-c.JupyterHub.external_url = 'http://airavata.host:20000'
-
-# Logging
-c.JupyterHub.log_level = 'DEBUG'
-
-# Terminate idle notebook containers
-c.JupyterHub.services = [
- {
- "name": "jupyterhub-idle-culler-service",
- "admin": True,
- "command": [sys.executable, "-m", "jupyterhub_idle_culler",
"--timeout=3600"],
- }
-]
-
-c.JupyterHub.load_roles = [
- {
- "name": "jupyterhub-idle-culler-role",
- "scopes": [
- "list:users",
- "read:users:activity",
- "read:servers",
- "delete:servers",
- ],
- "services": ["jupyterhub-idle-culler-service"],
- }
-]
-
-# SSL Termination
-c.JupyterHub.bind_url = 'http://0.0.0.0:20000'
-c.JupyterHub.external_ssl = True
-
-# Custom templates - Login
-c.JupyterHub.template_paths = ['/srv/jupyterhub/custom_templates']
-c.OAuthenticator.login_service = "Sign in with Existing Institution
Credentials"
diff --git a/airavata-jupyterhub/user-container/Dockerfile
b/airavata-jupyterhub/user-container/Dockerfile
deleted file mode 100644
index 26bf413f90..0000000000
--- a/airavata-jupyterhub/user-container/Dockerfile
+++ /dev/null
@@ -1,12 +0,0 @@
-FROM quay.io/jupyter/base-notebook:latest
-
-COPY init.sh /usr/local/bin/init.sh
-
-USER root
-RUN chmod +x /usr/local/bin/init.sh
-RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
-
-USER $NB_USER
-RUN pip install ipywidgets jupyterlab-git
-
-CMD ["start-notebook.py"]
\ No newline at end of file
diff --git a/airavata-jupyterhub/user-container/Makefile
b/airavata-jupyterhub/user-container/Makefile
deleted file mode 100755
index 4f74d1c5f0..0000000000
--- a/airavata-jupyterhub/user-container/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-deploy:
- docker build --platform linux/x86_64 -t cybershuttle/jupyterlab-base .
&& \
- docker push cybershuttle/jupyterlab-base
\ No newline at end of file
diff --git a/airavata-jupyterhub/user-container/init.sh
b/airavata-jupyterhub/user-container/init.sh
deleted file mode 100755
index 9eb18ec391..0000000000
--- a/airavata-jupyterhub/user-container/init.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-
-TARGET_DIR="/home/jovyan/work"
-SHARED_TMP="/cybershuttle_data"
-
-mkdir -p "$TARGET_DIR"
-
-if [ ! -f "$TARGET_DIR/.initialized" ]; then
- chown -R jovyan:users "$TARGET_DIR"
-
- # If $GIT_URL is set, clone the repo into the workspace
- if [ -n "$GIT_URL" ]; then
- echo "Cloning repo from $GIT_URL..."
- cd "$TARGET_DIR"
- git clone "$GIT_URL" .
- chown -R jovyan:users .
- fi
- touch "$TARGET_DIR/.initialized"
-else
- echo "Docker default files already exist, skipping copy."
-fi
-
-if [ -d "$SHARED_TMP" ]; then
- echo "Linking shared data to workspace..."
- ln -s "$SHARED_TMP" "$TARGET_DIR/cybershuttle_data"
-fi
-
-exec "$@"