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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ jobs:
CLOUDOS_URL: "https://cloudos.lifebit.ai"
PROJECT_NAME: "cloudos-cli-tests"
SESSION_NAME: "ci_test_cli"
SESSION_TYPE: "jupyter"
SESSION_TYPE: "vscode"
Comment thread
dapineyro marked this conversation as resolved.
SHUTDOWN_IN: "10m"
run: |
cloudos interactive-session create --cloudos-url $CLOUDOS_URL --apikey $CLOUDOS_TOKEN --workspace-id $CLOUDOS_WORKSPACE_ID --project-name "$PROJECT_NAME" --name $SESSION_NAME --session-type $SESSION_TYPE --shutdown-in $SHUTDOWN_IN 2>&1 | tee out.txt
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci_dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ jobs:
CLOUDOS_URL: "https://dev.sdlc.lifebit.ai"
PROJECT_NAME: "cloudos-cli-tests"
SESSION_NAME: "ci_test_cli"
SESSION_TYPE: "jupyter"
SESSION_TYPE: "vscode"
SHUTDOWN_IN: "10m"
run: |
cloudos interactive-session create --cloudos-url $CLOUDOS_URL --apikey $CLOUDOS_TOKEN --workspace-id $CLOUDOS_WORKSPACE_ID --project-name "$PROJECT_NAME" --name $SESSION_NAME --session-type $SESSION_TYPE --shutdown-in $SHUTDOWN_IN 2>&1 | tee out.txt
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## lifebit-ai/cloudos-cli: changelog

## v2.90.0 (2026-04-29)

### Feat

- Adds linking of multiple Lifebit Platform File Explorer folders or S3 paths at once. Can be used with command `cloudos link` or `cloudos interactive-session create --link`

## v2.89.2 (2026-04-22)

### Patch
Expand Down
54 changes: 43 additions & 11 deletions README.md
Comment thread
l-mansouri marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -2148,7 +2148,8 @@ cloudos interactive-session create \

**Data & Storage Management:**
- `--mount`: Mount a data file into the session. Supports both Lifebit Platform datasets and S3 files (AWS only). Format: `project_name/dataset_path` (e.g., `leila-test/Data/file.csv`) or `s3://bucket/path/to/file` (e.g., `s3://my-bucket/data/file.csv`). Can be used multiple times.
- `--link`: Link a folder into the session for read/write access (AWS only). Supports S3 folders and Lifebit Platform folders. Format: `s3://bucket/prefix` (e.g., `s3://my-bucket/data/`) or `project_name/folder_path` (e.g., `leila-test/AnalysesResults/analysis_id/results`). Can be used multiple times. **Note:** Linking is not supported on Azure. Use Lifebit Platform file explorer for data access.
- `--link`: Link a folder into the session for read/write access (AWS only). Supports S3 folders (e.g., `s3://my-bucket/data/`) and File Explorer folders (e.g., `my-project/Data/results`). Multiple folders can be specified using multiple `--link` flags or as comma-separated paths in a single `--link` argument.
**Note:** Linking is not supported on Azure. Use Lifebit Platform File Explorer for data access.

**Backend-Specific:**
- `--r-version`: R version for RStudio (options: `4.4.2`, `4.5.2`) - **optional for rstudio** (default: `4.4.2`)
Expand All @@ -2161,8 +2162,8 @@ cloudos interactive-session create \
**Data Management**

CloudOS CLI supports multiple ways to access data in interactive sessions, depending on your execution platform:
- you can load data directly into the session (i.e. files are copied into the session's mounted-data volume)
- you can link folders to your session (i.e the folders are sym-linked to the session). This works only for folders (S3-based) and only in AWS enviornments.
- **Mount files** (`--mount`): Files are copied into the session's mounted-data volume. Supports CloudOS File Explorer files and S3 files (AWS only).
- **Link folders** (`--link`): Folders are mounted as read/write accessible directories in the session (AWS only). Supports both S3 folders and Lifebit Platform File Explorer folders. Linked folders appear with unique mount names based on the folder path.


**Data Mounting Examples**
Expand All @@ -2177,7 +2178,7 @@ cloudos interactive-session create \
--mount "my_project/training_data.csv"
```

Link an S3 bucket:
Link an S3 folder:

```bash
cloudos interactive-session create \
Expand All @@ -2187,15 +2188,36 @@ cloudos interactive-session create \
--link "s3://my-results-bucket/output/"
```

Link multiple S3 buckets:
Link a File Explorer folder:

```bash
cloudos interactive-session create \
--profile my_profile \
--name "Multi-S3 Session" \
--name "File Explorer Access" \
--session-type jupyter \
--link "my-project/Data/results"
```

Link multiple folders (using multiple --link flags):

```bash
cloudos interactive-session create \
--profile my_profile \
--name "Multi-Folder Session" \
--session-type jupyter \
--link "s3://input-bucket/data/" \
--link "s3://output-bucket/results/"
--link "s3://output-bucket/results/" \
--link "my-project/AnalysesResults/analysis_123/output"
```

Link multiple folders (using comma-separated paths):

```bash
cloudos interactive-session create \
--profile my_profile \
--name "Multi-Folder Session" \
--session-type jupyter \
--link "s3://bucket-1/data/,s3://bucket-2/results/,my-project/Data/analysis"
```


Expand Down Expand Up @@ -2762,7 +2784,8 @@ Link job-related folders or custom S3 paths to your interactive analysis session
- By default, links results, workdir, and logs folders
- Use `--results`, `--workdir`, or `--logs` flags to link only specific folders

2. **Direct path linking** (PATH argument): Links a specific S3 path
2. **Direct path linking** (PATH argument): Links specific S3 or File Explorer paths. It supports a single path or comma-separated multiple paths.


**Basic usage:**

Expand All @@ -2774,16 +2797,20 @@ cloudos link --job-id <JOB_ID> --session-id <SESSION_ID> --profile my_profile
cloudos link --job-id <JOB_ID> --session-id <SESSION_ID> --results --profile my_profile
cloudos link --job-id <JOB_ID> --session-id <SESSION_ID> --workdir --logs --profile my_profile

# Link a specific S3 path
# Link a single S3 path
cloudos link s3://bucket/folder --session-id <SESSION_ID> --profile my_profile

# Link multiple S3 paths (comma-separated)
cloudos link s3://bucket1/data,s3://bucket2/results,s3://bucket3/output --session-id <SESSION_ID> --profile my_profile

# Link a File Explorer path (requires project name)
cloudos link "Data/MyFolder" --project-name my-project --session-id <SESSION_ID> --profile my_profile
```

**Command options:**

- `PATH`: S3 path to link (positional argument, required if `--job-id` is not provided)

- `PATH`: S3 or File Explorer path(s) to link (positional argument, required if `--job-id` is not provided). Supports comma-separated multiple paths for batch linking (e.g., `s3://bucket1/path1,s3://bucket2/path2`)
- `--apikey` / `-k`: Your Lifebit Platform API key (required)
- `--cloudos-url` / `-c`: The Lifebit Platform URL (default: https://cloudos.lifebit.ai)
- `--workspace-id`: The specific Lifebit Platform workspace ID (required)
Expand All @@ -2810,9 +2837,14 @@ cloudos link --job-id 62c83a1191fe06013b7ef355 --session-id abc123 --results --p
# Link workdir and logs (but not results)
cloudos link --job-id 62c83a1191fe06013b7ef355 --session-id abc123 --workdir --logs --profile my_profile

# Link an S3 bucket folder
# Link a single S3 bucket folder
cloudos link s3://my-bucket/analysis-results/2024 --session-id abc123 --profile my_profile

# Link multiple S3 folders in one command
cloudos link s3://bucket1/data,s3://bucket2/results,s3://bucket3/final-output --session-id abc123 --profile my_profile

# Mix different S3 prefixes from the same or different buckets
cloudos link s3://lifebit-datasets/pipelines/vep/,s3://lifebit-datasets/pipelines/phewas/,s3://my-results/output/ --session-id abc123 --profile my_profile
```

**Error handling:**
Expand Down
2 changes: 1 addition & 1 deletion cloudos_cli/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '2.89.2'
__version__ = '2.90.0'
67 changes: 67 additions & 0 deletions cloudos_cli/clos.py
Original file line number Diff line number Diff line change
Expand Up @@ -2548,4 +2548,71 @@ def abort_interactive_session(self, session_id, team_id, upload_on_close=True, f
# Return the status code (204 No Content is success)
return r.status_code

def mount_fuse_filesystem_v2(self, session_id, team_id, payload, verify=True):
"""Mount a FUSE filesystem into an interactive session (API v2).

Parameters
----------
session_id : string
The session ID (MongoDB ObjectId) to mount filesystem to.
team_id : string
The CloudOS team id (workspace id).
payload : dict
FuseFileSystemMount payload with dataItems array configuration.
For S3: {"dataItems": [{"type": "S3Folder", "data": {"name": str, "s3BucketName": str, "s3Prefix": str}}, ...]}
For File Explorer: {"dataItems": [{"kind": "Folder", "item": str, "name": str}, ...]}
verify: [bool|string], default=True
Whether to use SSL verification or not. Alternatively, if
a string is passed, it will be interpreted as the path to
the SSL certificate file.

Returns
-------
int
HTTP status code (204 for successful mount, no content returned).
"""
# Validate inputs
if not session_id or not isinstance(session_id, str):
raise ValueError("Invalid session_id: must be a non-empty string")
if not team_id or not isinstance(team_id, str):
raise ValueError("Invalid team_id: must be a non-empty string")

headers = {
"Content-type": "application/json",
"apikey": self.apikey
}

# Build URL with v2 endpoint and teamId query parameter
url = f"{self.cloudos_url}/api/v2/interactive-sessions/{session_id}/fuse-filesystem/mount?teamId={team_id}"

# Make the API request with POST method
try:
r = retry_requests_post(
url,
headers=headers,
json=payload,
verify=verify,
timeout=30
)
except Exception as e:
raise Exception(f"Failed to mount FUSE filesystem: {str(e)}")

if r.status_code >= 400:
if r.status_code == 404:
# Try to determine if it's a missing session or missing endpoint
try:
error_body = r.json() if r.content else {}
error_message = error_body.get("message", "").lower()
# If error mentions session, it's a session-not-found error
if "session" in error_message:
raise ValueError(f"Session not found: {session_id}")
except (json.JSONDecodeError, AttributeError):
pass
# Otherwise, likely endpoint not available - raise generic 404
raise BadRequestException(r)
raise BadRequestException(r)

# Return the status code (204 No Content is success)
return r.status_code


Loading
Loading