vantage-cli 0.1.3__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/.github/workflows/pages.yml +22 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/PKG-INFO +29 -1
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/README.md +28 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/pyproject.toml +1 -1
- vantage_cli-0.1.4/scripts/README.md +55 -0
- vantage_cli-0.1.4/scripts/update_docs_version.py +150 -0
- vantage_cli-0.1.4/scripts/update_docs_version.sh +44 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/uv.lock +1 -1
- vantage_cli-0.1.4/vantage_cli/apps/__init__.py +19 -0
- vantage_cli-0.1.4/vantage_cli/apps/slurm_juju_localhost/__init__.py +5 -0
- vantage_cli-0.1.4/vantage_cli/apps/slurm_multipass_localhost/__init__.py +5 -0
- vantage_cli-0.1.4/vantage_cli/commands/apps/__init__.py +22 -0
- vantage_cli-0.1.4/vantage_cli/commands/apps/deploy.py +72 -0
- vantage_cli-0.1.4/vantage_cli/commands/apps/list.py +97 -0
- vantage_cli-0.1.3/vantage_cli/apps/__init__.py +0 -19
- vantage_cli-0.1.3/vantage_cli/apps/juju_localhost/__init__.py +0 -14
- vantage_cli-0.1.3/vantage_cli/apps/multipass_singlenode/__init__.py +0 -14
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/.commitlintrc.yml +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/.github/workflows/ci.yml +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/.github/workflows/publish.yml +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/.gitignore +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/__init__.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/apps/common.py +0 -0
- {vantage_cli-0.1.3/vantage_cli/apps/juju_localhost → vantage_cli-0.1.4/vantage_cli/apps/slurm_juju_localhost}/app.py +0 -0
- {vantage_cli-0.1.3/vantage_cli/apps/juju_localhost → vantage_cli-0.1.4/vantage_cli/apps/slurm_juju_localhost}/bundle_yaml.py +0 -0
- {vantage_cli-0.1.3/vantage_cli/apps/microk8s → vantage_cli-0.1.4/vantage_cli/apps/slurm_microk8s_localhost}/README.md +0 -0
- {vantage_cli-0.1.3/vantage_cli/apps/microk8s → vantage_cli-0.1.4/vantage_cli/apps/slurm_microk8s_localhost}/__init__.py +0 -0
- {vantage_cli-0.1.3/vantage_cli/apps/microk8s → vantage_cli-0.1.4/vantage_cli/apps/slurm_microk8s_localhost}/app.py +0 -0
- {vantage_cli-0.1.3/vantage_cli/apps/multipass_singlenode → vantage_cli-0.1.4/vantage_cli/apps/slurm_multipass_localhost}/app.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/apps/templates.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/auth.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/cache.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/client.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/command_base.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/__init__.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clouds/__init__.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clouds/add.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clouds/delete.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clouds/render.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clouds/update.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/__init__.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/create.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/delete.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/get.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/list.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/render.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/schema.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/clusters/utils.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/profile/__init__.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/profile/crud.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/commands/profile/render.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/config.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/constants.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/exceptions.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/format.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/gql_client.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/main.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/render.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/schemas.py +0 -0
- {vantage_cli-0.1.3 → vantage_cli-0.1.4}/vantage_cli/time_loop.py +0 -0
|
@@ -28,6 +28,28 @@ jobs:
|
|
|
28
28
|
steps:
|
|
29
29
|
- name: Checkout
|
|
30
30
|
uses: actions/checkout@v4
|
|
31
|
+
- name: Update documentation version
|
|
32
|
+
run: |
|
|
33
|
+
# Extract version from pyproject.toml and update docs
|
|
34
|
+
VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
|
35
|
+
TODAY=$(date +%Y-%m-%d)
|
|
36
|
+
echo "📝 Updating docs with version: $VERSION"
|
|
37
|
+
|
|
38
|
+
# Update all documentation files
|
|
39
|
+
sed -i "s/^version: .*/version: \"$VERSION\"/" docs/_data/project.yml
|
|
40
|
+
sed -i "s/^updated: .*/updated: \"$TODAY\"/" docs/_data/project.yml
|
|
41
|
+
|
|
42
|
+
if grep -q "^version:" docs/_config.yml; then
|
|
43
|
+
sed -i "s/^version: .*/version: \"$VERSION\"/" docs/_config.yml
|
|
44
|
+
else
|
|
45
|
+
sed -i "/^description:/a version: \"$VERSION\"" docs/_config.yml
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
if grep -q "^version:" docs/index.md; then
|
|
49
|
+
sed -i "s/^version: .*/version: \"$VERSION\"/" docs/index.md
|
|
50
|
+
else
|
|
51
|
+
sed -i "/^permalink:/a version: \"$VERSION\"" docs/index.md
|
|
52
|
+
fi
|
|
31
53
|
- name: Setup Pages
|
|
32
54
|
uses: actions/configure-pages@v5
|
|
33
55
|
- name: Build with Jekyll
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vantage-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: The Vantage Compute CLI.
|
|
5
5
|
Author-email: jamesbeedy <james@vantagecompute.ai>
|
|
6
6
|
License: MIT
|
|
@@ -78,6 +78,34 @@ cd vantage-cli && uv sync
|
|
|
78
78
|
uv run vantage login
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
## Deploy a Slurm Cluster
|
|
82
|
+
|
|
83
|
+
### Localhost
|
|
84
|
+
|
|
85
|
+
#### Create a Singlenode Slurm Cluster using Multipass
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
vantage clusters create my-slurm-multipass-cluster \
|
|
89
|
+
--cloud localhost \
|
|
90
|
+
--deploy slurm-multipass-localhost
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Create a Slurm Cluster on LXD
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
vantage clusters create my-slurm-lxd-cluster \
|
|
97
|
+
--cloud localhost \
|
|
98
|
+
--deploy slurm-juju-localhost
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### Create a Slurm Cluster on MicroK8S
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
vantage clusters create my-slurm-microk8s-cluster \
|
|
105
|
+
--cloud localhost \
|
|
106
|
+
--deploy slurm-microk8s-locahost
|
|
107
|
+
```
|
|
108
|
+
|
|
81
109
|
## 📚 Documentation
|
|
82
110
|
|
|
83
111
|
Visit our comprehensive documentation site:
|
|
@@ -46,6 +46,34 @@ cd vantage-cli && uv sync
|
|
|
46
46
|
uv run vantage login
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
## Deploy a Slurm Cluster
|
|
50
|
+
|
|
51
|
+
### Localhost
|
|
52
|
+
|
|
53
|
+
#### Create a Singlenode Slurm Cluster using Multipass
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
vantage clusters create my-slurm-multipass-cluster \
|
|
57
|
+
--cloud localhost \
|
|
58
|
+
--deploy slurm-multipass-localhost
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Create a Slurm Cluster on LXD
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
vantage clusters create my-slurm-lxd-cluster \
|
|
65
|
+
--cloud localhost \
|
|
66
|
+
--deploy slurm-juju-localhost
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Create a Slurm Cluster on MicroK8S
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
vantage clusters create my-slurm-microk8s-cluster \
|
|
73
|
+
--cloud localhost \
|
|
74
|
+
--deploy slurm-microk8s-locahost
|
|
75
|
+
```
|
|
76
|
+
|
|
49
77
|
## 📚 Documentation
|
|
50
78
|
|
|
51
79
|
Visit our comprehensive documentation site:
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Scripts Directory
|
|
2
|
+
|
|
3
|
+
This directory contains utility scripts for the Vantage CLI project.
|
|
4
|
+
|
|
5
|
+
## update_docs_version.py
|
|
6
|
+
|
|
7
|
+
**Purpose**: Automatically updates documentation files with the current version from `pyproject.toml`.
|
|
8
|
+
|
|
9
|
+
**Files Updated**:
|
|
10
|
+
- `docs/_data/project.yml` - Updates version and date fields
|
|
11
|
+
- `docs/_config.yml` - Adds/updates version field
|
|
12
|
+
- `docs/index.md` - Adds version to front matter
|
|
13
|
+
|
|
14
|
+
**Usage**:
|
|
15
|
+
```bash
|
|
16
|
+
# Using justfile (recommended)
|
|
17
|
+
just update-docs-version
|
|
18
|
+
|
|
19
|
+
# Direct execution
|
|
20
|
+
python scripts/update_docs_version.py
|
|
21
|
+
|
|
22
|
+
# Using shell wrapper
|
|
23
|
+
./scripts/update_docs_version.sh
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Dependencies**:
|
|
27
|
+
- Python 3.7+ with `tomllib` (Python 3.11+) or `tomli` package
|
|
28
|
+
|
|
29
|
+
## update_docs_version.sh
|
|
30
|
+
|
|
31
|
+
**Purpose**: Shell wrapper for `update_docs_version.py` that handles dependency installation.
|
|
32
|
+
|
|
33
|
+
**Usage**:
|
|
34
|
+
```bash
|
|
35
|
+
./scripts/update_docs_version.sh
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Integration
|
|
39
|
+
|
|
40
|
+
### Local Development
|
|
41
|
+
Use `just update-docs-version` before building documentation locally.
|
|
42
|
+
|
|
43
|
+
### CI/CD (GitHub Pages)
|
|
44
|
+
The version update is automatically integrated into the GitHub Pages workflow in `.github/workflows/pages.yml`.
|
|
45
|
+
|
|
46
|
+
### Manual Execution
|
|
47
|
+
Both Python script and shell wrapper can be run independently for custom build processes.
|
|
48
|
+
|
|
49
|
+
## When to Use
|
|
50
|
+
|
|
51
|
+
- **Before releasing**: Ensure documentation reflects the current version
|
|
52
|
+
- **Before building docs**: Keep documentation in sync with package version
|
|
53
|
+
- **In CI/CD**: Automatically update version during deployment
|
|
54
|
+
|
|
55
|
+
The scripts are designed to be idempotent - running them multiple times with the same version will not cause issues.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Update documentation files with version from pyproject.toml
|
|
4
|
+
|
|
5
|
+
This script reads the version from pyproject.toml and updates:
|
|
6
|
+
1. docs/_data/project.yml (replaces __VERSION__ placeholder)
|
|
7
|
+
2. docs/_config.yml (adds version field)
|
|
8
|
+
3. Any other documentation files that need version updates
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
import sys
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, Dict
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import tomllib
|
|
19
|
+
except ImportError:
|
|
20
|
+
# Python < 3.11 fallback
|
|
21
|
+
try:
|
|
22
|
+
import tomli as tomllib
|
|
23
|
+
except ImportError:
|
|
24
|
+
print("Error: tomllib (Python 3.11+) or tomli package required")
|
|
25
|
+
sys.exit(1)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def load_pyproject_version() -> str:
|
|
29
|
+
"""Load version from pyproject.toml"""
|
|
30
|
+
pyproject_path = Path(__file__).parent.parent / "pyproject.toml"
|
|
31
|
+
|
|
32
|
+
if not pyproject_path.exists():
|
|
33
|
+
raise FileNotFoundError(f"pyproject.toml not found at {pyproject_path}")
|
|
34
|
+
|
|
35
|
+
with open(pyproject_path, "rb") as f:
|
|
36
|
+
data = tomllib.load(f)
|
|
37
|
+
|
|
38
|
+
version = data.get("project", {}).get("version")
|
|
39
|
+
if not version:
|
|
40
|
+
raise ValueError("Version not found in pyproject.toml")
|
|
41
|
+
|
|
42
|
+
return version
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def update_project_yml(version: str) -> None:
|
|
46
|
+
"""Update docs/_data/project.yml with the current version"""
|
|
47
|
+
project_yml_path = Path(__file__).parent.parent / "docs" / "_data" / "project.yml"
|
|
48
|
+
|
|
49
|
+
if not project_yml_path.exists():
|
|
50
|
+
print(f"Warning: {project_yml_path} not found, skipping")
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
content = project_yml_path.read_text(encoding="utf-8")
|
|
54
|
+
|
|
55
|
+
# Replace version placeholder
|
|
56
|
+
updated_content = re.sub(
|
|
57
|
+
r'version:\s*["\']?__VERSION__["\']?',
|
|
58
|
+
f'version: "{version}"',
|
|
59
|
+
content
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Update the date as well
|
|
63
|
+
today = datetime.now().strftime("%Y-%m-%d")
|
|
64
|
+
updated_content = re.sub(
|
|
65
|
+
r'updated:\s*["\']?[\d-]+["\']?',
|
|
66
|
+
f'updated: "{today}"',
|
|
67
|
+
updated_content
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
project_yml_path.write_text(updated_content, encoding="utf-8")
|
|
71
|
+
print(f"✓ Updated {project_yml_path} with version {version}")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def update_config_yml(version: str) -> None:
|
|
75
|
+
"""Update docs/_config.yml with the current version"""
|
|
76
|
+
config_yml_path = Path(__file__).parent.parent / "docs" / "_config.yml"
|
|
77
|
+
|
|
78
|
+
if not config_yml_path.exists():
|
|
79
|
+
print(f"Warning: {config_yml_path} not found, skipping")
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
content = config_yml_path.read_text(encoding="utf-8")
|
|
83
|
+
|
|
84
|
+
# Check if version field already exists
|
|
85
|
+
if re.search(r'^version:\s*', content, re.MULTILINE):
|
|
86
|
+
# Update existing version
|
|
87
|
+
updated_content = re.sub(
|
|
88
|
+
r'^version:\s*.*$',
|
|
89
|
+
f'version: "{version}"',
|
|
90
|
+
content,
|
|
91
|
+
flags=re.MULTILINE
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
# Add version field after description
|
|
95
|
+
updated_content = re.sub(
|
|
96
|
+
r'(description:.*?\n)',
|
|
97
|
+
f'\\1version: "{version}"\n',
|
|
98
|
+
content,
|
|
99
|
+
flags=re.DOTALL
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
config_yml_path.write_text(updated_content, encoding="utf-8")
|
|
103
|
+
print(f"✓ Updated {config_yml_path} with version {version}")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def update_index_md(version: str) -> None:
|
|
107
|
+
"""Update docs/index.md with version information if needed"""
|
|
108
|
+
index_md_path = Path(__file__).parent.parent / "docs" / "index.md"
|
|
109
|
+
|
|
110
|
+
if not index_md_path.exists():
|
|
111
|
+
print(f"Warning: {index_md_path} not found, skipping")
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
content = index_md_path.read_text(encoding="utf-8")
|
|
115
|
+
|
|
116
|
+
# Add version to the front matter if it doesn't exist
|
|
117
|
+
if "version:" not in content and "---" in content:
|
|
118
|
+
# Insert version into front matter
|
|
119
|
+
updated_content = re.sub(
|
|
120
|
+
r'(---\n.*?)\n(---)',
|
|
121
|
+
f'\\1\nversion: "{version}"\n\\2',
|
|
122
|
+
content,
|
|
123
|
+
flags=re.DOTALL
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
if updated_content != content:
|
|
127
|
+
index_md_path.write_text(updated_content, encoding="utf-8")
|
|
128
|
+
print(f"✓ Updated {index_md_path} with version {version}")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def main() -> None:
|
|
132
|
+
"""Main function to update all documentation files with version"""
|
|
133
|
+
try:
|
|
134
|
+
version = load_pyproject_version()
|
|
135
|
+
print(f"📝 Updating documentation with version: {version}")
|
|
136
|
+
|
|
137
|
+
# Update all documentation files
|
|
138
|
+
update_project_yml(version)
|
|
139
|
+
update_config_yml(version)
|
|
140
|
+
update_index_md(version)
|
|
141
|
+
|
|
142
|
+
print(f"🎉 Successfully updated documentation files with version {version}")
|
|
143
|
+
|
|
144
|
+
except Exception as e:
|
|
145
|
+
print(f"❌ Error updating documentation version: {e}")
|
|
146
|
+
sys.exit(1)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
main()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Update documentation version from pyproject.toml
|
|
3
|
+
# This script can be run locally or in CI/CD
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Get the directory where this script is located
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
10
|
+
|
|
11
|
+
echo "🔄 Updating documentation version..."
|
|
12
|
+
|
|
13
|
+
# Check if we're in a Python environment with the required packages
|
|
14
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
15
|
+
PYTHON_CMD="python3"
|
|
16
|
+
elif command -v python >/dev/null 2>&1; then
|
|
17
|
+
PYTHON_CMD="python"
|
|
18
|
+
else
|
|
19
|
+
echo "❌ Error: Python not found"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Try to run the update script
|
|
24
|
+
cd "$PROJECT_ROOT"
|
|
25
|
+
|
|
26
|
+
# Check if tomli/tomllib is available
|
|
27
|
+
if ! $PYTHON_CMD -c "import sys; import tomllib if sys.version_info >= (3, 11) else __import__('tomli')" 2>/dev/null; then
|
|
28
|
+
echo "📦 Installing tomli for Python < 3.11..."
|
|
29
|
+
# Try different installation methods
|
|
30
|
+
if command -v pip >/dev/null 2>&1; then
|
|
31
|
+
pip install --quiet tomli
|
|
32
|
+
elif command -v pip3 >/dev/null 2>&1; then
|
|
33
|
+
pip3 install --quiet tomli
|
|
34
|
+
elif $PYTHON_CMD -m pip --version >/dev/null 2>&1; then
|
|
35
|
+
$PYTHON_CMD -m pip install --quiet tomli
|
|
36
|
+
else
|
|
37
|
+
echo "⚠️ Warning: Could not install tomli. Script may fail for Python < 3.11"
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Run the update script
|
|
42
|
+
$PYTHON_CMD scripts/update_docs_version.py
|
|
43
|
+
|
|
44
|
+
echo "✅ Documentation version update complete!"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# © 2025 Vantage Compute, Inc. All rights reserved.
|
|
2
|
+
# Confidential and proprietary. Unauthorized use prohibited.
|
|
3
|
+
"""Applications management commands for Vantage CLI."""
|
|
4
|
+
|
|
5
|
+
from vantage_cli import AsyncTyper
|
|
6
|
+
from vantage_cli.commands.apps.deploy import deploy_app
|
|
7
|
+
from vantage_cli.commands.apps.list import list_apps
|
|
8
|
+
|
|
9
|
+
# Create the apps command group
|
|
10
|
+
apps_app = AsyncTyper(
|
|
11
|
+
name="apps",
|
|
12
|
+
help="Deploy and manage applications on Vantage compute clusters.",
|
|
13
|
+
invoke_without_command=True,
|
|
14
|
+
no_args_is_help=True,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Register commands
|
|
18
|
+
apps_app.command("list")(list_apps)
|
|
19
|
+
apps_app.command("deploy")(deploy_app)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# © 2025 Vantage Compute, Inc. All rights reserved.
|
|
2
|
+
# Confidential and proprietary. Unauthorized use prohibited.
|
|
3
|
+
"""Application deployment commands for Vantage CLI."""
|
|
4
|
+
|
|
5
|
+
from vantage_cli import AsyncTyper
|
|
6
|
+
|
|
7
|
+
from .deploy import deploy_app
|
|
8
|
+
from .list import list_apps
|
|
9
|
+
|
|
10
|
+
# Create the apps command group
|
|
11
|
+
apps_app = AsyncTyper(
|
|
12
|
+
name="apps",
|
|
13
|
+
help="Deploy and manage applications on Vantage compute clusters.",
|
|
14
|
+
invoke_without_command=True,
|
|
15
|
+
no_args_is_help=True,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# Register subcommands directly
|
|
19
|
+
apps_app.command("list")(list_apps)
|
|
20
|
+
apps_app.command("deploy")(deploy_app)
|
|
21
|
+
|
|
22
|
+
__all__ = ["apps_app"]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# © 2025 Vantage Compute, Inc. All rights reserved.
|
|
2
|
+
# Confidential and proprietary. Unauthorized use prohibited.
|
|
3
|
+
"""Deploy and register clusters."""
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from vantage_cli.commands.clusters.utils import get_available_apps, get_cluster_by_name
|
|
11
|
+
from vantage_cli.config import attach_settings
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@attach_settings
|
|
17
|
+
async def deploy_app(
|
|
18
|
+
ctx: typer.Context,
|
|
19
|
+
app_name: Annotated[
|
|
20
|
+
str, typer.Argument(help="Name of the cluster infrastructure application to deploy")
|
|
21
|
+
],
|
|
22
|
+
cluster_name: Annotated[
|
|
23
|
+
str, typer.Argument(help="Name of the cluster in Vantage you would like to link to")
|
|
24
|
+
],
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Deploy a slurm cluster and link it to a cluster entity in Vantage."""
|
|
27
|
+
try:
|
|
28
|
+
# Get available apps
|
|
29
|
+
available_apps = get_available_apps()
|
|
30
|
+
|
|
31
|
+
if app_name not in available_apps:
|
|
32
|
+
console.print(f"[bold red]✗ App '{app_name}' not found[/bold red]")
|
|
33
|
+
console.print(f"\nAvailable apps: {', '.join(available_apps.keys())}")
|
|
34
|
+
console.print("Use [cyan]vantage apps list[/cyan] to see all available applications.")
|
|
35
|
+
raise typer.Exit(1)
|
|
36
|
+
|
|
37
|
+
console.print(
|
|
38
|
+
f"[bold blue]Deploying app '{app_name}' to cluster '{cluster_name}'...[/bold blue]"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Get cluster data
|
|
42
|
+
cluster_data = await get_cluster_by_name(ctx, cluster_name)
|
|
43
|
+
if not cluster_data:
|
|
44
|
+
console.print(f"[bold red]✗ Cluster '{cluster_name}' not found[/bold red]")
|
|
45
|
+
raise typer.Exit(1)
|
|
46
|
+
|
|
47
|
+
# Get the app info
|
|
48
|
+
app_info = available_apps[app_name]
|
|
49
|
+
|
|
50
|
+
# Check if this is a function-based app
|
|
51
|
+
if "deploy_function" in app_info:
|
|
52
|
+
# Function-based app
|
|
53
|
+
deploy_function = app_info["deploy_function"]
|
|
54
|
+
|
|
55
|
+
# Call the deploy function with cluster data
|
|
56
|
+
await deploy_function(ctx, cluster_data)
|
|
57
|
+
|
|
58
|
+
console.print(
|
|
59
|
+
f"[bold green]✓ App '{app_name}' deployed successfully to cluster '{cluster_name}'![/bold green]"
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
console.print(
|
|
63
|
+
f"[bold red]✗ App '{app_name}' does not have a deploy function[/bold red]"
|
|
64
|
+
)
|
|
65
|
+
raise typer.Exit(1)
|
|
66
|
+
|
|
67
|
+
except typer.Exit:
|
|
68
|
+
# Re-raise typer.Exit to maintain exit codes
|
|
69
|
+
raise
|
|
70
|
+
except Exception as e:
|
|
71
|
+
console.print(f"[bold red]✗ Error deploying app '{app_name}': {e}[/bold red]")
|
|
72
|
+
raise typer.Exit(1)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# © 2025 Vantage Compute, Inc. All rights reserved.
|
|
2
|
+
# Confidential and proprietary. Unauthorized use prohibited.
|
|
3
|
+
"""List available applications for deployment."""
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.table import Table
|
|
10
|
+
|
|
11
|
+
from vantage_cli.commands.clusters.utils import get_available_apps
|
|
12
|
+
from vantage_cli.config import attach_settings
|
|
13
|
+
from vantage_cli.format import render_json
|
|
14
|
+
|
|
15
|
+
console = Console()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@attach_settings
|
|
19
|
+
async def list_apps(
|
|
20
|
+
ctx: typer.Context,
|
|
21
|
+
json_output: Annotated[
|
|
22
|
+
bool, typer.Option("--json", "-j", help="Output in JSON format")
|
|
23
|
+
] = False,
|
|
24
|
+
) -> None:
|
|
25
|
+
"""List all available applications for deployment."""
|
|
26
|
+
try:
|
|
27
|
+
# Get available apps
|
|
28
|
+
available_apps = get_available_apps()
|
|
29
|
+
|
|
30
|
+
if json_output:
|
|
31
|
+
# Format for JSON output
|
|
32
|
+
apps_data = []
|
|
33
|
+
for app_name, app_info in available_apps.items():
|
|
34
|
+
app_data = {
|
|
35
|
+
"name": app_name,
|
|
36
|
+
"module": app_info["module"].__name__
|
|
37
|
+
if "module" in app_info and hasattr(app_info["module"], "__name__")
|
|
38
|
+
else "unknown",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Try to get description from docstring if available
|
|
42
|
+
if "deploy_function" in app_info:
|
|
43
|
+
func = app_info["deploy_function"]
|
|
44
|
+
if hasattr(func, "__doc__") and func.__doc__:
|
|
45
|
+
app_data["description"] = func.__doc__.strip().split("\n")[0]
|
|
46
|
+
else:
|
|
47
|
+
app_data["description"] = "No description available"
|
|
48
|
+
else:
|
|
49
|
+
app_data["description"] = "No deploy function available"
|
|
50
|
+
|
|
51
|
+
apps_data.append(app_data)
|
|
52
|
+
|
|
53
|
+
render_json({"apps": apps_data})
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
# Rich table output
|
|
57
|
+
if not available_apps:
|
|
58
|
+
console.print("[yellow]No applications found.[/yellow]")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
table = Table(
|
|
62
|
+
title="Available Applications", show_header=True, header_style="bold magenta"
|
|
63
|
+
)
|
|
64
|
+
table.add_column("App Name", style="cyan", width=20)
|
|
65
|
+
table.add_column("Module", style="green", width=30)
|
|
66
|
+
table.add_column("Description", style="white", width=50)
|
|
67
|
+
|
|
68
|
+
for app_name, app_info in available_apps.items():
|
|
69
|
+
# Get module name
|
|
70
|
+
module_name = "unknown"
|
|
71
|
+
if "module" in app_info:
|
|
72
|
+
module_name = (
|
|
73
|
+
app_info["module"].__name__
|
|
74
|
+
if hasattr(app_info["module"], "__name__")
|
|
75
|
+
else "unknown"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Get description from docstring
|
|
79
|
+
description = "No description available"
|
|
80
|
+
if "deploy_function" in app_info:
|
|
81
|
+
func = app_info["deploy_function"]
|
|
82
|
+
if hasattr(func, "__doc__") and func.__doc__:
|
|
83
|
+
# Get first line of docstring
|
|
84
|
+
description = func.__doc__.strip().split("\n")[0]
|
|
85
|
+
else:
|
|
86
|
+
description = "No description available"
|
|
87
|
+
else:
|
|
88
|
+
description = "No deploy function available"
|
|
89
|
+
|
|
90
|
+
table.add_row(app_name, module_name, description)
|
|
91
|
+
|
|
92
|
+
console.print(table)
|
|
93
|
+
console.print(f"\n[bold]Found {len(available_apps)} application(s)[/bold]")
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
console.print(f"[bold red]Error listing applications: {e}[/bold red]")
|
|
97
|
+
raise typer.Exit(1)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# © 2025 Vantage Compute, Inc. All rights reserved.
|
|
2
|
-
# Confidential and proprietary. Unauthorized use prohibited.
|
|
3
|
-
"""Cluster management commands for Vantage CLI."""
|
|
4
|
-
|
|
5
|
-
from vantage_cli import AsyncTyper
|
|
6
|
-
from vantage_cli.apps.juju_localhost import juju_localhost_app
|
|
7
|
-
from vantage_cli.apps.multipass_singlenode import multipass_singlenode_app
|
|
8
|
-
|
|
9
|
-
# Create the apps command group
|
|
10
|
-
apps_app = AsyncTyper(
|
|
11
|
-
name="apps",
|
|
12
|
-
help="Vantage infrastructure automation applications.",
|
|
13
|
-
invoke_without_command=True,
|
|
14
|
-
no_args_is_help=True,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
# Register subcommand groups
|
|
18
|
-
apps_app.add_typer(juju_localhost_app)
|
|
19
|
-
apps_app.add_typer(multipass_singlenode_app)
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"""Juju localhost deployment app package."""
|
|
2
|
-
|
|
3
|
-
from vantage_cli import AsyncTyper
|
|
4
|
-
|
|
5
|
-
from .app import deploy_command
|
|
6
|
-
|
|
7
|
-
juju_localhost_app = AsyncTyper(
|
|
8
|
-
name="juju-localhost",
|
|
9
|
-
help="Juju localhost SLURM application commands.",
|
|
10
|
-
invoke_without_command=True,
|
|
11
|
-
no_args_is_help=True,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
juju_localhost_app.command("deploy")(deploy_command)
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"""Multipass single-node deployment app package."""
|
|
2
|
-
|
|
3
|
-
from vantage_cli import AsyncTyper
|
|
4
|
-
|
|
5
|
-
from .app import deploy_command
|
|
6
|
-
|
|
7
|
-
multipass_singlenode_app = AsyncTyper(
|
|
8
|
-
name="multipass-singlenode",
|
|
9
|
-
help="Multipass single-node application commands.",
|
|
10
|
-
invoke_without_command=True,
|
|
11
|
-
no_args_is_help=True,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
multipass_singlenode_app.command("deploy")(deploy_command)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|