Metadata-Version: 2.4
Name: gcube-cli
Version: 0.3.0
Summary: Official command-line tool for the gcube AI GPU cloud platform
Author-email: Data Alliance <support@data-alliance.com>
License: Apache-2.0
Project-URL: Homepage, https://gcube.ai
Project-URL: Documentation, https://gcube.ai/docs
Project-URL: Bug Tracker, https://github.com/data-alliance/gcube-cli/issues
Keywords: gcube,gpu,cloud,ai,cli,mlops
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: System :: Distributed Computing
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: click<8.3,>=8.1
Requires-Dist: httpx>=0.27
Requires-Dist: rich>=13.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: websockets>=13.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-httpx>=0.30; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: types-PyYAML; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"

# gcube CLI

Official command-line tool for the [gcube AI GPU cloud platform](https://gcube.ai).
Manage GPU workloads, monitor resources, and stream container logs — all from your terminal.

---

## Overview

```
gcube <service> <operation> [options]
```

| Feature | Description |
|---|---|
| Easy install | `pip install gcube-cli`, Python 3.10+ |
| AWS CLI style | `gcube <service> <operation>` with `--output table\|json\|yaml` |
| Token auth | Set your token from the gcube web console once, then use all commands |
| Key dependencies | click · httpx · rich · pyyaml · websockets |

---

## Installation

```bash
pip install gcube-cli
```

---

## Quick Start

```bash
# 1. Set your API token (copy from gcube web console)
gcube configure set --token "eyJ..."

# 2. Check available GPUs and note the CODE
gcube gpu list

# 3. (Optional) Check personal storages and note the SER if mounting storage
gcube storage list

# 4. Generate a workload template, edit it, then register
gcube workload register --skeleton > workload.yaml
# edit workload.yaml
gcube workload register -f workload.yaml

# 5. Check status — SER is the workload identifier shown in the list
gcube workload list

# 6. Start the workload
gcube workload start <ser>

# 7. Stream logs
gcube workload logs <ser>
```

---

## Configuration

### Get a Token

1. Log in to the [gcube web console](https://gcube.ai)
2. Go to **API Token** menu and copy your token
3. Set it in the CLI:

```bash
gcube configure set --token "eyJ..."
```

### Config File

Generated automatically at `~/.gcube/config.yaml`:

```yaml
platform_url: https://api.gcube.ai
ws_url: wss://console.gcube.ai:61443
auth:
  access_token: "eyJ..."
  expires_at: "2026-04-03T10:00:00Z"
output: table          # table | json | yaml
```

### Configure Commands

```
gcube configure                              # Interactive setup
gcube configure set --token <token>          # Set API token
gcube configure set --platform-url <url>     # Set platform URL
gcube configure set --ws-url <url>           # Set WebSocket URL (for log streaming)
gcube configure set --output <format>        # Set default output format
gcube configure get <key>                    # Get a config value (token, platform-url, ws-url, output)
gcube configure status                       # Show current config and token validity
```

### Environment Variables

Environment variables take precedence over the config file.

| Variable | Description |
|---|---|
| `GCUBE_PLATFORM_URL` | Platform base URL |
| `GCUBE_ACCESS_TOKEN` | Bearer token (useful for CI/CD) |
| `GCUBE_OUTPUT` | Default output format (`table`\|`json`\|`yaml`) |

---

## Command Reference

### Workload

Manage the full lifecycle of GPU workloads. Each workload is identified by a **SER** (serial number) shown in `gcube workload list`.

| Command | Description |
|---|---|
| `gcube workload register --skeleton` | Print a blank YAML template to stdout |
| `gcube workload register -f <yaml>` | Register a workload from a YAML file |
| `gcube workload register --image <img> ...` | Register a workload with inline flags |
| `gcube workload update <ser> --skeleton` | Export current workload config as editable YAML |
| `gcube workload update <ser> -f <yaml>` | Update a stopped workload |
| `gcube workload list` | List workloads |
| `gcube workload describe <ser>` | Show workload details |
| `gcube workload start <ser>` | Start a workload and monitor deployment status in real time |
| `gcube workload start <ser> --no-watch` | Start a workload without monitoring |
| `gcube workload start <ser> --timeout <sec>` | Stop monitoring after N seconds if the deploy hasn't finished (exit code 124) |
| `gcube workload watch <ser>` | Re-attach to a deploying workload and monitor its status |
| `gcube workload watch <ser> --plain` | Force plain line-per-event output instead of the live dashboard |
| `gcube workload stop <ser>` | Stop a workload |
| `gcube workload delete <ser>` | Delete a workload |
| `gcube workload logs <ser>` | Stream container logs in real time |
| `gcube workload logs <ser> --pod <idx> --container <idx>` | Stream a specific container's logs |
| `gcube workload pods <ser>` | List pods |

**Key Flags**

| Flag | Description |
|---|---|
| `-f, --file <path>` | Workload YAML file path |
| `--description <text>` | Workload description (2-80 chars) |
| `--image <image>` | Container image |
| `--gpu <code>` | GPU code (from `gcube gpu list` CODE column) |
| `--cuda <version>` | CUDA version code |
| `--no-watch` | Start without monitoring deployment status (start only) |
| `--owner <email>` | Filter by owner (list only) |
| `--pod <idx>` | Pod index for log streaming (0-based) |
| `--container <idx>` | Container index for log streaming (0-based) |
| `-y, --yes` | Skip confirmation (stop/delete); register/update despite failed image verification |

**CUDA Version Codes**

| Code | CUDA |
|---|---|
| `12000` | 12.0 |
| `12020` | 12.2 |
| `12030` | 12.3 |
| `12040` | 12.4 |
| `12050` | 12.5 |
| `12060` | 12.6 |
| `12080` | 12.8 |
| `12090` | 12.9 |
| `13000` | 13.0 |

**Workload YAML Format** (for `register -f` and `update -f`)

```yaml
# workload.yaml
description: "My ML training job"  # required, 2-80 chars
cuda: "12020"                      # optional CUDA version code
sharedMemory: 1                    # GB

containers:
  - containerImage: "pytorch/pytorch:2.0"  # required
    repo: docker.io
    port: 0                        # 0 = auto-detect (falls back to 8000 if undetectable)
    maxConnection: 4
    containerCommand: "python train.py"
    isCredential: false            # set true to use a saved registry credential
    containerEnvs:                 # each entry is a single key-value object
      - EPOCHS: "100"
      - BATCH_SIZE: "32"
    userStorages: []
    # userStorages:                # SER must be quoted — it's numeric
    #   - "95": "/mnt/data"        # SER from: gcube storage list

gpuSpecs:
  - gpuCode: "029"                 # required — CODE from 'gcube gpu list'
  # add more entries for multiple replicas:
  # - gpuCode: "029"
```

> Use `gcube workload update <ser> --skeleton > workload.yaml` to export the current config before editing.

> Image verification is advisory — if it fails, you'll be asked whether to register anyway (`-y` skips the prompt). If the service port can't be determined, it defaults to **8000**.

**Optional Istio fields** (omit to use defaults):

- `isIstioProxy` (default: `true`) — injects the Istio service mesh sidecar into each pod. Disable only if your container has compatibility issues with the sidecar.
- `isIstioL7Hash` (default: `false`) — enables L7 request hashing so the same client is consistently routed to the same pod. Useful for stateful inference. Requires 2 or more replicas (multiple `gpuSpecs` entries).

**Deployment Monitoring**

`gcube workload start <ser>` monitors deployment in real time by default, showing four stages until the workload is running:

```
1. VM Provisioning   2. Node Ready   3. Image Pulling   4. Container Start
```

- Press `Ctrl+C` to stop monitoring; the deployment continues in the background.
- `gcube workload watch <ser>` re-attaches to a workload that is already deploying. If the workload is already running, stopped, or not yet deployed, it reports the status and exits without waiting.
- Use `--no-watch` to start without monitoring (e.g. in scripts).
- For deployments with more than 5 replicas, progress is shown as an aggregate counter (e.g. `Deploying...  60/100`) instead of per-stage detail.

**Non-interactive / scripting**

`start` and `watch` adapt their output for automation:

- When stdout is **not a terminal** (piped or redirected), or with `--plain`, output switches from the live dashboard to a plain line-per-event stream (`HH:MM:SS [ser] message`, server timestamps, flushed per line — safe to `tail -f` and durable even if the process is hard-killed).
- With `-o json` / `-o yaml`, only a single result object is printed: `{ser, status, startedAt, completedAt, durationSec, failReason}`. `status` is one of `success`, `failed`, `timeout`, `interrupted`, `skipped`.
- `--timeout <sec>` stops an unfinished watch after N seconds and exits `124` (GNU `timeout` convention); it also keeps `Ctrl+C` responsive on a silent stream.

---

### GPU

List available GPUs with specs and pricing.

| Command | Description |
|---|---|
| `gcube gpu list` | Available GPUs (CODE, specs, hourly price range) |
| `gcube gpu list --all` | All GPUs including unavailable ones |

> The CODE column is a zero-padded sequence number (001, 002, ...) used when registering workloads.

---

### Storage

List personal storage volumes (PVC) available for mounting into workloads.

| Command | Description |
|---|---|
| `gcube storage list` | List bound personal storages |

**SER** is the identifier used in workload YAML to mount a storage volume:

```yaml
containers:
  - containerImage: "pytorch/pytorch:2.0"
    userStorages:
      - "95": "/mnt/data"    # SER: mountPath
      - "94": "/mnt/model"
```

Only storages in `bound` state are listed.

> ⚠️ `ReadWriteOnce` storages can only be mounted to a single node — avoid them in multi-replica workloads.

---

### Resource

Monitor CPU, GPU, and memory usage of a workload.

| Command | Description |
|---|---|
| `gcube resource workload <ser>` | Workload resource usage (time average) |

---

### Point

Check point balance and spending history.

| Command | Description |
|---|---|
| `gcube point status` | Balance, total charged/spent, low-balance warning |
| `gcube point spending` | Daily spending for the current month |
| `gcube point spending --month 2026-03` | Daily spending for a specific month |
| `gcube point spending --workload <ser>` | Filter by workload |

---

### Credential

Manage container registry credentials.

| Command | Description |
|---|---|
| `gcube credential list` | List saved credentials |
| `gcube credential create --repo <type> --username <name> --token <token>` | Save a credential |
| `gcube credential delete --repo <type>` | Delete a credential |

Supported `--repo` types: `docker`, `github`, `harbor`, `aws`, `huggingface`, `quay`

To pull from a private registry, save a credential with `gcube credential create` and set `isCredential: true` in the corresponding container's workload YAML.

---

## Output Formats

```bash
gcube workload list              # table (default)
gcube -o json workload list      # JSON
gcube -o yaml workload list      # YAML
```

---

## Global Options

| Flag | Description | Default |
|---|---|---|
| `-o, --output <format>` | Output format: `table`\|`json`\|`yaml` | `table` |
| `-V, --version` | Show version | — |
| `--help` | Show help | — |

---

## Exit Codes

| Code | Meaning |
|---|---|
| `0` | Success |
| `1` | Invalid argument or state error |
| `2` | gcube API error |
| `3` | Authentication failure or token expired |
| `4` | Network error |
| `124` | `workload watch`/`start` timed out (`--timeout`) before the deploy finished |

---

## Examples

### Register and Manage Workloads

```bash
# Check available GPUs (note the CODE column)
gcube gpu list

# Generate a template, edit it, then register
gcube workload register --skeleton > workload.yaml
# edit workload.yaml
gcube workload register -f workload.yaml

# Register with inline flags
gcube workload register \
  --description "inference service" \
  --image ollama/ollama:latest \
  --gpu 029

# List and inspect
gcube workload list
gcube workload describe 2212
gcube -o json workload describe 2212

# Start and monitor deployment (default), or start without monitoring
gcube workload start 2212
gcube workload start 2212 --no-watch

# Re-attach to a deploying workload
gcube workload watch 2212

# Stop / delete
gcube workload stop 2212
gcube workload delete 2212
```

### Scripting / Batch Deployment

```bash
# Plain log to a file (auto-detected; no live dashboard). Capture stderr too so
# failure/timeout messages land in the log. Branch on the exit code.
gcube workload watch 2212 --timeout 1800 > 2212.log 2>&1
echo "exit=$?"   # 0 success · 1 failed · 124 timeout

# Machine-readable result for aggregating many deploys
gcube -o json workload watch 2212 --timeout 1800 > 2212.json
# {"ser":2212,"status":"success","startedAt":...,"completedAt":...,"durationSec":...,"failReason":null}

# Per-student burst with distinct tokens (one process each)
for ser in "${SERS[@]}"; do
  GCUBE_ACCESS_TOKEN="${TOKENS[$ser]}" \
    gcube -o json workload watch "$ser" --timeout 1800 > "$ser.json" &
done
wait
```

### Update a Workload

```bash
# Export current config, edit, and re-apply
gcube workload stop 2212
gcube workload update 2212 --skeleton > workload.yaml
# edit workload.yaml
gcube workload update 2212 -f workload.yaml
gcube workload start 2212
```

### Stream Logs

```bash
# Single container — streams immediately
gcube workload logs 2212

# Multi-container — shows selection list first
gcube workload logs 2226
gcube workload logs 2226 --pod 0 --container 1
```

### Resource Monitoring

```bash
gcube resource workload 2212
gcube -o json resource workload 2212
```

### Mount Personal Storage

```bash
# 1. Check available storages and note the SER column
gcube storage list

# 2. Add to workload YAML
#    userStorages:
#      - "95": "/mnt/data"

# 3. Register or update
gcube workload register -f workload.yaml
```

---

## License

Apache License 2.0
