cave-cli 3.5.1__tar.gz → 3.5.2__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.
- {cave_cli-3.5.1/cave_cli.egg-info → cave_cli-3.5.2}/PKG-INFO +16 -8
- {cave_cli-3.5.1 → cave_cli-3.5.2}/README.md +15 -7
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/cli.py +73 -20
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/create.py +20 -19
- cave_cli-3.5.2/cave_cli/commands/doctor.py +170 -0
- cave_cli-3.5.2/cave_cli/commands/kill.py +36 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/list_cmd.py +11 -5
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/list_versions.py +16 -9
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/prettify.py +2 -2
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/purge.py +18 -5
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/reset.py +11 -4
- cave_cli-3.5.2/cave_cli/commands/run.py +343 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/sync_cmd.py +12 -12
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/test.py +8 -7
- cave_cli-3.5.2/cave_cli/commands/theme.py +34 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/uninstall.py +5 -3
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/update.py +6 -4
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/upgrade.py +10 -5
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/version.py +9 -7
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/cache.py +62 -0
- cave_cli-3.5.2/cave_cli/utils/display.py +969 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/docker.py +175 -69
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/git.py +0 -2
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/logger.py +28 -6
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/validate.py +2 -2
- {cave_cli-3.5.1 → cave_cli-3.5.2/cave_cli.egg-info}/PKG-INFO +16 -8
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli.egg-info/SOURCES.txt +3 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/pyproject.toml +2 -2
- cave_cli-3.5.1/cave_cli/commands/kill.py +0 -23
- cave_cli-3.5.1/cave_cli/commands/run.py +0 -189
- {cave_cli-3.5.1 → cave_cli-3.5.2}/LICENSE +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/NOTICE.md +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/__init__.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/commands/__init__.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/__init__.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/constants.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/env.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/net.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/subprocess.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli/utils/sync.py +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli.egg-info/dependency_links.txt +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli.egg-info/entry_points.txt +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/cave_cli.egg-info/top_level.txt +0 -0
- {cave_cli-3.5.1 → cave_cli-3.5.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cave_cli
|
|
3
|
-
Version: 3.5.
|
|
3
|
+
Version: 3.5.2
|
|
4
4
|
Summary: CLI for creating and managing Docker-based CAVE web applications.
|
|
5
5
|
Author-email: MIT-CAVE <cave-contact@mit.edu>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -50,9 +50,7 @@ docker run hello-world
|
|
|
50
50
|
<details>
|
|
51
51
|
<summary>Windows</summary>
|
|
52
52
|
|
|
53
|
-
- Install Docker Desktop
|
|
54
|
-
- Install WSL2 with Ubuntu: https://learn.microsoft.com/en-us/windows/wsl/install
|
|
55
|
-
- Open your WSL Ubuntu terminal for all `cave` commands
|
|
53
|
+
- Install Docker Desktop: https://docs.docker.com/docker-for-windows/install/
|
|
56
54
|
|
|
57
55
|
</details>
|
|
58
56
|
|
|
@@ -81,7 +79,7 @@ pipx ensurepath
|
|
|
81
79
|
|
|
82
80
|
</details>
|
|
83
81
|
<details>
|
|
84
|
-
<summary>Other Linux / Windows
|
|
82
|
+
<summary>Other Linux / Windows</summary>
|
|
85
83
|
|
|
86
84
|
```sh
|
|
87
85
|
python3 -m pip install --user pipx
|
|
@@ -91,10 +89,10 @@ pipx ensurepath
|
|
|
91
89
|
|
|
92
90
|
For more options see the [pipx installation guide](https://pipx.pypa.io/stable/installation/).
|
|
93
91
|
|
|
94
|
-
Verify the installation:
|
|
92
|
+
Verify the installation and check your environment health:
|
|
95
93
|
|
|
96
94
|
```sh
|
|
97
|
-
cave
|
|
95
|
+
cave doctor
|
|
98
96
|
```
|
|
99
97
|
|
|
100
98
|
## Quick Start
|
|
@@ -117,7 +115,8 @@ cave --help
|
|
|
117
115
|
| Command | Description |
|
|
118
116
|
|---|---|
|
|
119
117
|
| `cave create <name>` | Create a new CAVE app from the template repository |
|
|
120
|
-
| `cave run` | Build Docker image and run the app |
|
|
118
|
+
| `cave run` | Build Docker image and run the app with a live TUI dashboard |
|
|
119
|
+
| `cave doctor` | Check the health of your Docker, Git, and Pipx environment |
|
|
121
120
|
|
|
122
121
|
### Peripheral Commands
|
|
123
122
|
|
|
@@ -137,6 +136,7 @@ cave --help
|
|
|
137
136
|
| `cave list` | List running CAVE apps |
|
|
138
137
|
| `cave kill` | Stop Docker containers for an app |
|
|
139
138
|
| `cave list-versions` | List available CAVE app versions |
|
|
139
|
+
| `cave theme <name>` | Set the CLI color theme (dark, light, solarized, monokai) |
|
|
140
140
|
| `cave update` | Update the CAVE CLI itself |
|
|
141
141
|
| `cave uninstall` | Remove the CAVE CLI |
|
|
142
142
|
| `cave version` | Print version information |
|
|
@@ -149,6 +149,14 @@ cave --help
|
|
|
149
149
|
| `--loglevel LEVEL` | Set log level: DEBUG, INFO, WARN, ERROR, SILENT |
|
|
150
150
|
| `-y`, `--yes` | Automatically answer confirmation prompts with yes |
|
|
151
151
|
|
|
152
|
+
### `cave run` Options
|
|
153
|
+
|
|
154
|
+
| Flag | Description |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `--all` | Show raw container output instead of the TUI dashboard |
|
|
157
|
+
| `-it`, `--interactive` | Run in interactive mode (drops into a bash shell) |
|
|
158
|
+
| `ip:port` | Optional argument for LAN hosting (e.g. `192.168.1.1:8000`) |
|
|
159
|
+
|
|
152
160
|
## Updating
|
|
153
161
|
|
|
154
162
|
```sh
|
|
@@ -33,9 +33,7 @@ docker run hello-world
|
|
|
33
33
|
<details>
|
|
34
34
|
<summary>Windows</summary>
|
|
35
35
|
|
|
36
|
-
- Install Docker Desktop
|
|
37
|
-
- Install WSL2 with Ubuntu: https://learn.microsoft.com/en-us/windows/wsl/install
|
|
38
|
-
- Open your WSL Ubuntu terminal for all `cave` commands
|
|
36
|
+
- Install Docker Desktop: https://docs.docker.com/docker-for-windows/install/
|
|
39
37
|
|
|
40
38
|
</details>
|
|
41
39
|
|
|
@@ -64,7 +62,7 @@ pipx ensurepath
|
|
|
64
62
|
|
|
65
63
|
</details>
|
|
66
64
|
<details>
|
|
67
|
-
<summary>Other Linux / Windows
|
|
65
|
+
<summary>Other Linux / Windows</summary>
|
|
68
66
|
|
|
69
67
|
```sh
|
|
70
68
|
python3 -m pip install --user pipx
|
|
@@ -74,10 +72,10 @@ pipx ensurepath
|
|
|
74
72
|
|
|
75
73
|
For more options see the [pipx installation guide](https://pipx.pypa.io/stable/installation/).
|
|
76
74
|
|
|
77
|
-
Verify the installation:
|
|
75
|
+
Verify the installation and check your environment health:
|
|
78
76
|
|
|
79
77
|
```sh
|
|
80
|
-
cave
|
|
78
|
+
cave doctor
|
|
81
79
|
```
|
|
82
80
|
|
|
83
81
|
## Quick Start
|
|
@@ -100,7 +98,8 @@ cave --help
|
|
|
100
98
|
| Command | Description |
|
|
101
99
|
|---|---|
|
|
102
100
|
| `cave create <name>` | Create a new CAVE app from the template repository |
|
|
103
|
-
| `cave run` | Build Docker image and run the app |
|
|
101
|
+
| `cave run` | Build Docker image and run the app with a live TUI dashboard |
|
|
102
|
+
| `cave doctor` | Check the health of your Docker, Git, and Pipx environment |
|
|
104
103
|
|
|
105
104
|
### Peripheral Commands
|
|
106
105
|
|
|
@@ -120,6 +119,7 @@ cave --help
|
|
|
120
119
|
| `cave list` | List running CAVE apps |
|
|
121
120
|
| `cave kill` | Stop Docker containers for an app |
|
|
122
121
|
| `cave list-versions` | List available CAVE app versions |
|
|
122
|
+
| `cave theme <name>` | Set the CLI color theme (dark, light, solarized, monokai) |
|
|
123
123
|
| `cave update` | Update the CAVE CLI itself |
|
|
124
124
|
| `cave uninstall` | Remove the CAVE CLI |
|
|
125
125
|
| `cave version` | Print version information |
|
|
@@ -132,6 +132,14 @@ cave --help
|
|
|
132
132
|
| `--loglevel LEVEL` | Set log level: DEBUG, INFO, WARN, ERROR, SILENT |
|
|
133
133
|
| `-y`, `--yes` | Automatically answer confirmation prompts with yes |
|
|
134
134
|
|
|
135
|
+
### `cave run` Options
|
|
136
|
+
|
|
137
|
+
| Flag | Description |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `--all` | Show raw container output instead of the TUI dashboard |
|
|
140
|
+
| `-it`, `--interactive` | Run in interactive mode (drops into a bash shell) |
|
|
141
|
+
| `ip:port` | Optional argument for LAN hosting (e.g. `192.168.1.1:8000`) |
|
|
142
|
+
|
|
135
143
|
## Updating
|
|
136
144
|
|
|
137
145
|
```sh
|
|
@@ -142,6 +142,13 @@ def main():
|
|
|
142
142
|
default=False,
|
|
143
143
|
help="Run in interactive mode (entrypoint set to bash)",
|
|
144
144
|
)
|
|
145
|
+
p_run.add_argument(
|
|
146
|
+
"--all",
|
|
147
|
+
dest="show_all",
|
|
148
|
+
action="store_true",
|
|
149
|
+
default=False,
|
|
150
|
+
help="Show raw container output instead of the TUI dashboard (also enabled by --verbose)",
|
|
151
|
+
)
|
|
145
152
|
|
|
146
153
|
# ------------------------------------------------------------------ #
|
|
147
154
|
# reset #
|
|
@@ -265,6 +272,13 @@ def main():
|
|
|
265
272
|
help="Stop Docker containers for a CAVE app",
|
|
266
273
|
)
|
|
267
274
|
add_global_args(p_kill)
|
|
275
|
+
p_kill.add_argument(
|
|
276
|
+
"name",
|
|
277
|
+
nargs="?",
|
|
278
|
+
default=None,
|
|
279
|
+
metavar="app-name",
|
|
280
|
+
help="Name of the CAVE app to kill",
|
|
281
|
+
)
|
|
268
282
|
p_kill.add_argument(
|
|
269
283
|
"-a",
|
|
270
284
|
"--all",
|
|
@@ -309,6 +323,15 @@ def main():
|
|
|
309
323
|
help="Glob pattern to filter versions (e.g. v3.*, v3.4.*)",
|
|
310
324
|
)
|
|
311
325
|
|
|
326
|
+
# ------------------------------------------------------------------ #
|
|
327
|
+
# doctor #
|
|
328
|
+
# ------------------------------------------------------------------ #
|
|
329
|
+
p_doctor = subparsers.add_parser(
|
|
330
|
+
"doctor",
|
|
331
|
+
help="Check the health of the CAVE environment",
|
|
332
|
+
)
|
|
333
|
+
add_global_args(p_doctor)
|
|
334
|
+
|
|
312
335
|
# ------------------------------------------------------------------ #
|
|
313
336
|
# update #
|
|
314
337
|
# ------------------------------------------------------------------ #
|
|
@@ -342,6 +365,22 @@ def main():
|
|
|
342
365
|
)
|
|
343
366
|
add_global_args(p_version)
|
|
344
367
|
|
|
368
|
+
# ------------------------------------------------------------------ #
|
|
369
|
+
# theme #
|
|
370
|
+
# ------------------------------------------------------------------ #
|
|
371
|
+
p_theme = subparsers.add_parser(
|
|
372
|
+
"theme",
|
|
373
|
+
help="Set the CLI color theme",
|
|
374
|
+
)
|
|
375
|
+
add_global_args(p_theme)
|
|
376
|
+
p_theme.add_argument(
|
|
377
|
+
"name",
|
|
378
|
+
nargs="?",
|
|
379
|
+
default=None,
|
|
380
|
+
metavar="THEME",
|
|
381
|
+
help="Name of the theme to apply (dark, light, solarized, monokai)",
|
|
382
|
+
)
|
|
383
|
+
|
|
345
384
|
# ------------------------------------------------------------------ #
|
|
346
385
|
# Dispatch #
|
|
347
386
|
# ------------------------------------------------------------------ #
|
|
@@ -371,85 +410,99 @@ def main():
|
|
|
371
410
|
# Command dispatch #
|
|
372
411
|
# ------------------------------------------------------------------ #
|
|
373
412
|
if args.command == "create":
|
|
374
|
-
from cave_cli.
|
|
413
|
+
from cave_cli.commands.doctor import check_all
|
|
375
414
|
from cave_cli.commands.create import create
|
|
376
415
|
|
|
377
|
-
|
|
416
|
+
check_all()
|
|
378
417
|
create(args)
|
|
379
418
|
|
|
380
419
|
elif args.command == "run":
|
|
381
|
-
from cave_cli.
|
|
420
|
+
from cave_cli.commands.doctor import check_all
|
|
382
421
|
from cave_cli.commands.run import run
|
|
383
422
|
|
|
384
|
-
|
|
423
|
+
check_all()
|
|
385
424
|
run(args)
|
|
386
425
|
|
|
387
426
|
elif args.command == "reset":
|
|
388
|
-
from cave_cli.
|
|
427
|
+
from cave_cli.commands.doctor import check_all
|
|
389
428
|
from cave_cli.commands.reset import reset
|
|
390
429
|
|
|
391
|
-
|
|
430
|
+
check_all()
|
|
392
431
|
reset(args)
|
|
393
432
|
|
|
394
433
|
elif args.command == "upgrade":
|
|
395
|
-
from cave_cli.
|
|
434
|
+
from cave_cli.commands.doctor import check_all
|
|
396
435
|
from cave_cli.commands.upgrade import upgrade
|
|
397
436
|
|
|
398
|
-
|
|
437
|
+
check_all()
|
|
399
438
|
upgrade(args)
|
|
400
439
|
|
|
401
440
|
elif args.command == "sync":
|
|
402
|
-
from cave_cli.
|
|
441
|
+
from cave_cli.commands.doctor import check_all
|
|
403
442
|
from cave_cli.commands.sync_cmd import sync_cmd
|
|
404
443
|
|
|
405
|
-
|
|
444
|
+
check_all()
|
|
406
445
|
sync_cmd(args)
|
|
407
446
|
|
|
408
447
|
elif args.command == "test":
|
|
409
|
-
from cave_cli.
|
|
448
|
+
from cave_cli.commands.doctor import check_all
|
|
410
449
|
from cave_cli.commands.test import test
|
|
411
450
|
|
|
412
|
-
|
|
451
|
+
check_all()
|
|
413
452
|
test(args)
|
|
414
453
|
|
|
415
454
|
elif args.command == "prettify":
|
|
416
|
-
from cave_cli.
|
|
455
|
+
from cave_cli.commands.doctor import check_all
|
|
417
456
|
from cave_cli.commands.prettify import prettify
|
|
418
457
|
|
|
419
|
-
|
|
458
|
+
check_all()
|
|
420
459
|
prettify(args)
|
|
421
460
|
|
|
422
461
|
elif args.command == "list":
|
|
423
|
-
from cave_cli.
|
|
462
|
+
from cave_cli.commands.doctor import check_all
|
|
424
463
|
from cave_cli.commands.list_cmd import list_cmd
|
|
425
464
|
|
|
426
|
-
|
|
465
|
+
check_all()
|
|
427
466
|
list_cmd(args)
|
|
428
467
|
|
|
429
468
|
elif args.command == "kill":
|
|
430
|
-
from cave_cli.
|
|
469
|
+
from cave_cli.commands.doctor import check_all
|
|
431
470
|
from cave_cli.commands.kill import kill
|
|
432
471
|
|
|
433
|
-
|
|
472
|
+
check_all()
|
|
434
473
|
kill(args)
|
|
435
474
|
|
|
436
475
|
elif args.command == "purge":
|
|
437
|
-
from cave_cli.
|
|
476
|
+
from cave_cli.commands.doctor import check_all
|
|
438
477
|
from cave_cli.commands.purge import purge
|
|
439
478
|
|
|
440
|
-
|
|
479
|
+
check_all()
|
|
441
480
|
purge(args)
|
|
442
481
|
|
|
443
482
|
elif args.command == "list-versions":
|
|
483
|
+
from cave_cli.commands.doctor import check_all
|
|
444
484
|
from cave_cli.commands.list_versions import list_versions
|
|
445
485
|
|
|
486
|
+
check_all()
|
|
446
487
|
list_versions(args)
|
|
447
488
|
|
|
448
489
|
elif args.command == "update":
|
|
490
|
+
from cave_cli.commands.doctor import check_all
|
|
449
491
|
from cave_cli.commands.update import update
|
|
450
492
|
|
|
493
|
+
check_all()
|
|
451
494
|
update(args)
|
|
452
495
|
|
|
496
|
+
elif args.command == "doctor":
|
|
497
|
+
from cave_cli.commands.doctor import doctor
|
|
498
|
+
|
|
499
|
+
doctor(args)
|
|
500
|
+
|
|
501
|
+
elif args.command == "theme":
|
|
502
|
+
from cave_cli.commands.theme import theme_cmd
|
|
503
|
+
|
|
504
|
+
theme_cmd(args)
|
|
505
|
+
|
|
453
506
|
elif args.command == "uninstall":
|
|
454
507
|
from cave_cli.commands.uninstall import uninstall
|
|
455
508
|
|
|
@@ -8,6 +8,7 @@ from pathlib import Path
|
|
|
8
8
|
from cave_cli.commands.reset import reset
|
|
9
9
|
from cave_cli.commands.run import run_cave
|
|
10
10
|
from cave_cli.utils.constants import HTTPS_URL
|
|
11
|
+
from cave_cli.utils.display import print_section, step_done, step_fail, step_start
|
|
11
12
|
from cave_cli.utils.docker import build_image, check_docker, generate_secret_key
|
|
12
13
|
from cave_cli.utils.env import create_env_interactive
|
|
13
14
|
from cave_cli.utils.git import add, branch_rename, clone, commit, init
|
|
@@ -37,29 +38,31 @@ def create(args: argparse.Namespace) -> None:
|
|
|
37
38
|
clone_url = getattr(args, "url", None) or HTTPS_URL
|
|
38
39
|
version = getattr(args, "version", None)
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
logger.info("Downloading the app template...")
|
|
41
|
+
print_section("App Creation")
|
|
42
42
|
|
|
43
|
+
step_start("Downloading app template")
|
|
43
44
|
success = clone(clone_url, app_name, branch=version)
|
|
44
45
|
if not success or not os.path.isdir(app_name):
|
|
46
|
+
step_fail("Downloading app template")
|
|
45
47
|
logger.error("Clone failed. Ensure you used a valid version.")
|
|
46
48
|
logger.error(
|
|
47
49
|
f"The version must be a tag (or branch) listed at {clone_url}."
|
|
48
50
|
)
|
|
49
51
|
sys.exit(1)
|
|
50
|
-
|
|
51
|
-
logger.info("Done")
|
|
52
|
+
step_done("Downloading app template")
|
|
52
53
|
|
|
53
54
|
app_dir = os.path.abspath(app_name)
|
|
54
55
|
remove_licence_info(app_dir)
|
|
55
|
-
|
|
56
56
|
Path(os.path.join(app_dir, ".env")).touch()
|
|
57
57
|
|
|
58
58
|
example_env = os.path.join(app_dir, "example.env")
|
|
59
59
|
env_path = os.path.join(app_dir, ".env")
|
|
60
60
|
|
|
61
61
|
build_image(app_name, app_dir)
|
|
62
|
+
|
|
63
|
+
step_start("Generating secret key")
|
|
62
64
|
secret_key = generate_secret_key(app_name)
|
|
65
|
+
step_done("Generating secret key")
|
|
63
66
|
|
|
64
67
|
create_env_interactive(
|
|
65
68
|
app_name=app_name,
|
|
@@ -73,10 +76,11 @@ def create(args: argparse.Namespace) -> None:
|
|
|
73
76
|
verbose=getattr(args, "verbose", False),
|
|
74
77
|
loglevel=getattr(args, "loglevel", "INFO"),
|
|
75
78
|
)
|
|
76
|
-
reset(reset_args, app_dir=app_dir, app_name=app_name)
|
|
79
|
+
reset(reset_args, app_dir=app_dir, app_name=app_name, skip_build=True)
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
print_section("Version Control")
|
|
82
|
+
|
|
83
|
+
step_start("Configuring git repository")
|
|
80
84
|
git_dir = os.path.join(app_dir, ".git")
|
|
81
85
|
if os.path.isdir(git_dir):
|
|
82
86
|
rmtree_force(git_dir)
|
|
@@ -97,9 +101,9 @@ def create(args: argparse.Namespace) -> None:
|
|
|
97
101
|
add(app_dir)
|
|
98
102
|
commit(app_dir, "Initialize CAVE App")
|
|
99
103
|
branch_rename(app_dir, "main")
|
|
100
|
-
|
|
104
|
+
step_done("Configuring git repository")
|
|
101
105
|
|
|
102
|
-
|
|
106
|
+
step_start("Generating LLM docs")
|
|
103
107
|
docs_args = argparse.Namespace(
|
|
104
108
|
entrypoint="./utils/generate_docs.sh",
|
|
105
109
|
interactive=False,
|
|
@@ -110,15 +114,12 @@ def create(args: argparse.Namespace) -> None:
|
|
|
110
114
|
verbose=getattr(args, "verbose", False),
|
|
111
115
|
loglevel=getattr(args, "loglevel", "INFO"),
|
|
112
116
|
)
|
|
113
|
-
run_cave(app_dir, app_name, docs_args)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
f"Created variables and additional configuration options "
|
|
120
|
-
f"are available in {app_name}/.env"
|
|
121
|
-
)
|
|
117
|
+
run_cave(app_dir, app_name, docs_args, skip_header=True, skip_build=True)
|
|
118
|
+
step_done("Generating LLM docs")
|
|
119
|
+
|
|
120
|
+
print_section("Done")
|
|
121
|
+
step_done(f"App '{app_name}' created successfully!")
|
|
122
|
+
step_done(f"Configuration options available in {app_name}/.env")
|
|
122
123
|
|
|
123
124
|
|
|
124
125
|
def force_remove(func, path, exc):
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from cave_cli.utils.display import (
|
|
5
|
+
print_section,
|
|
6
|
+
step_done,
|
|
7
|
+
step_fail,
|
|
8
|
+
step_start,
|
|
9
|
+
)
|
|
10
|
+
from cave_cli.utils.logger import logger
|
|
11
|
+
from cave_cli.utils.subprocess import run, version_tuple
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def check_git() -> tuple[bool, str]:
|
|
15
|
+
"""
|
|
16
|
+
Usage:
|
|
17
|
+
|
|
18
|
+
- Validates that git is installed
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
|
|
22
|
+
- ``success``: bool
|
|
23
|
+
- ``message``: str remediation or version
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
result = run(["git", "--version"])
|
|
27
|
+
if result.returncode == 0:
|
|
28
|
+
return True, result.stdout.strip()
|
|
29
|
+
except FileNotFoundError:
|
|
30
|
+
pass
|
|
31
|
+
return (
|
|
32
|
+
False,
|
|
33
|
+
"git is not installed. Please install git: https://git-scm.com/",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def check_pipx() -> tuple[bool, str]:
|
|
38
|
+
"""
|
|
39
|
+
Usage:
|
|
40
|
+
|
|
41
|
+
- Validates that pipx is installed
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
|
|
45
|
+
- ``success``: bool
|
|
46
|
+
- ``message``: str remediation or version
|
|
47
|
+
"""
|
|
48
|
+
import shutil
|
|
49
|
+
|
|
50
|
+
pipx = shutil.which("pipx")
|
|
51
|
+
if pipx:
|
|
52
|
+
try:
|
|
53
|
+
result = run([pipx, "--version"])
|
|
54
|
+
if result.returncode == 0:
|
|
55
|
+
return True, f"pipx version {result.stdout.strip()}"
|
|
56
|
+
except Exception:
|
|
57
|
+
pass
|
|
58
|
+
return (
|
|
59
|
+
False,
|
|
60
|
+
"pipx is not installed. Please install pipx: https://pipx.pypa.io/",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def check_docker() -> tuple[bool, str]:
|
|
65
|
+
"""
|
|
66
|
+
Usage:
|
|
67
|
+
|
|
68
|
+
- Validates that Docker is installed, running, and meets the minimum version
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
|
|
72
|
+
- ``success``: bool
|
|
73
|
+
- ``message``: str remediation or version
|
|
74
|
+
"""
|
|
75
|
+
from cave_cli.utils.constants import MIN_DOCKER_VERSION
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
result = run(["docker", "--version"])
|
|
79
|
+
except FileNotFoundError:
|
|
80
|
+
return (
|
|
81
|
+
False,
|
|
82
|
+
f"Docker is not installed. "
|
|
83
|
+
f"Please install Docker version {MIN_DOCKER_VERSION} or greater: "
|
|
84
|
+
f"https://docs.docker.com/get-docker/",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if result.returncode != 0 or not result.stdout:
|
|
88
|
+
return (
|
|
89
|
+
False,
|
|
90
|
+
f"Could determine Docker version. "
|
|
91
|
+
f"Please install Docker version {MIN_DOCKER_VERSION} or greater.",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
version_str = result.stdout.strip()
|
|
95
|
+
import re
|
|
96
|
+
|
|
97
|
+
match = re.search(r"(\d+\.\d+\.\d+)", version_str)
|
|
98
|
+
if not match:
|
|
99
|
+
return False, f"Could not parse Docker version from: {version_str}"
|
|
100
|
+
|
|
101
|
+
current = match.group(1)
|
|
102
|
+
if version_tuple(current) < version_tuple(MIN_DOCKER_VERSION):
|
|
103
|
+
return (
|
|
104
|
+
False,
|
|
105
|
+
f"Your current Docker version ({current}) is too old. "
|
|
106
|
+
f"Please install Docker version {MIN_DOCKER_VERSION} or greater.",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
info_result = run(["docker", "info"])
|
|
110
|
+
if info_result.returncode != 0:
|
|
111
|
+
return False, "Docker is not running... Please start Docker."
|
|
112
|
+
|
|
113
|
+
return True, version_str
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def check_all(exit_on_fail: bool = True) -> dict[str, tuple[bool, str]]:
|
|
117
|
+
"""
|
|
118
|
+
Usage:
|
|
119
|
+
|
|
120
|
+
- Runs all environment checks
|
|
121
|
+
|
|
122
|
+
Optional:
|
|
123
|
+
|
|
124
|
+
- ``exit_on_fail``: bool - Exits the process if any check fails
|
|
125
|
+
"""
|
|
126
|
+
results = {
|
|
127
|
+
"Docker": check_docker(),
|
|
128
|
+
"Git": check_git(),
|
|
129
|
+
"Pipx": check_pipx(),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if exit_on_fail:
|
|
133
|
+
failed = False
|
|
134
|
+
for name, (success, message) in results.items():
|
|
135
|
+
if not success:
|
|
136
|
+
logger.error(message)
|
|
137
|
+
failed = True
|
|
138
|
+
if failed:
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
|
|
141
|
+
return results
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def doctor(args: argparse.Namespace) -> None:
|
|
145
|
+
"""
|
|
146
|
+
Usage:
|
|
147
|
+
|
|
148
|
+
- Checks the health of the CAVE environment (Docker, Git, Pipx)
|
|
149
|
+
"""
|
|
150
|
+
print_section("CAVE Doctor")
|
|
151
|
+
|
|
152
|
+
results = check_all(exit_on_fail=False)
|
|
153
|
+
|
|
154
|
+
all_pass = True
|
|
155
|
+
for name, (success, message) in results.items():
|
|
156
|
+
if success:
|
|
157
|
+
step_done(f"{name}: {message}")
|
|
158
|
+
else:
|
|
159
|
+
step_fail(f"{name}: {message}")
|
|
160
|
+
all_pass = False
|
|
161
|
+
|
|
162
|
+
print_section("Status")
|
|
163
|
+
if all_pass:
|
|
164
|
+
logger.success("Your environment is healthy and ready to CAVE!")
|
|
165
|
+
else:
|
|
166
|
+
logger.error(
|
|
167
|
+
"Some issues were found in your environment. "
|
|
168
|
+
"Please follow the remediation steps above."
|
|
169
|
+
)
|
|
170
|
+
sys.exit(1)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from cave_cli.utils.display import step_done, step_start
|
|
4
|
+
from cave_cli.utils.docker import get_running_apps, remove_containers
|
|
5
|
+
from cave_cli.utils.logger import logger
|
|
6
|
+
from cave_cli.utils.validate import get_app
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def kill(args: argparse.Namespace) -> None:
|
|
10
|
+
"""
|
|
11
|
+
Usage:
|
|
12
|
+
|
|
13
|
+
- Stops Docker containers for CAVE apps
|
|
14
|
+
"""
|
|
15
|
+
kill_all = getattr(args, "all", False)
|
|
16
|
+
app_name = getattr(args, "name", None)
|
|
17
|
+
|
|
18
|
+
running_apps = get_running_apps()
|
|
19
|
+
|
|
20
|
+
if kill_all:
|
|
21
|
+
if not running_apps:
|
|
22
|
+
logger.info("No CAVE apps are currently running.")
|
|
23
|
+
return
|
|
24
|
+
for name in running_apps:
|
|
25
|
+
remove_containers(name)
|
|
26
|
+
elif app_name:
|
|
27
|
+
if app_name not in running_apps:
|
|
28
|
+
logger.error(f"App '{app_name}' is not running.")
|
|
29
|
+
return
|
|
30
|
+
remove_containers(app_name)
|
|
31
|
+
else:
|
|
32
|
+
_, app_name = get_app()
|
|
33
|
+
if app_name not in running_apps:
|
|
34
|
+
logger.info(f"App '{app_name}' is already stopped.")
|
|
35
|
+
return
|
|
36
|
+
remove_containers(app_name)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
|
|
3
|
+
from cave_cli.utils.display import print_key_value, print_section
|
|
3
4
|
from cave_cli.utils.docker import (
|
|
4
5
|
get_container_env,
|
|
5
6
|
get_container_host_port,
|
|
@@ -18,20 +19,25 @@ def list_cmd(args: argparse.Namespace) -> None:
|
|
|
18
19
|
show_all = getattr(args, "all", False)
|
|
19
20
|
|
|
20
21
|
if show_all:
|
|
21
|
-
|
|
22
|
+
print_section("CAVE App Containers (All)")
|
|
22
23
|
for suffix in ("_django", "_db_host", "_redis_host", "_nginx_host"):
|
|
23
24
|
for name in get_all_containers(suffix):
|
|
24
|
-
|
|
25
|
+
print(f" ● {name}")
|
|
25
26
|
else:
|
|
26
|
-
logger.header("CAVE Apps (Running):")
|
|
27
27
|
apps = get_running_apps()
|
|
28
|
+
if not apps:
|
|
29
|
+
logger.info("No CAVE apps are currently running.")
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
print_section("CAVE Apps (Running)")
|
|
28
33
|
for app_name in apps:
|
|
29
34
|
nginx_containers = get_all_containers("_nginx_host")
|
|
30
35
|
nginx_name = f"{app_name}_nginx_host"
|
|
31
36
|
if nginx_name in nginx_containers:
|
|
32
37
|
ip = get_container_env(nginx_name, "CAVE_IP")
|
|
33
38
|
port = get_container_env(nginx_name, "CAVE_PORT")
|
|
34
|
-
|
|
39
|
+
print_key_value(app_name, f"https://{ip}:{port}")
|
|
35
40
|
else:
|
|
36
41
|
port = get_container_host_port(f"{app_name}_django")
|
|
37
|
-
|
|
42
|
+
print_key_value(app_name, f"http://localhost:{port}")
|
|
43
|
+
print("")
|