sima-cli 2.1.12__tar.gz → 2.1.14__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.
- {sima_cli-2.1.12/sima_cli.egg-info → sima_cli-2.1.14}/PKG-INFO +1 -1
- {sima_cli-2.1.12 → sima_cli-2.1.14}/pyproject.toml +1 -1
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/__version__.py +1 -1
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/package_builder.py +11 -1
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/cmdexec.py +16 -4
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/commands.py +78 -5
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/install.py +35 -5
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/neat.py +376 -18
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/network_doctor.py +1 -1
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/utils.py +213 -3
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/docker.py +68 -39
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/vulcan/artifacts.py +35 -12
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/vulcan/commands.py +6 -2
- {sima_cli-2.1.12 → sima_cli-2.1.14/sima_cli.egg-info}/PKG-INFO +1 -1
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_docker_utils.py +49 -61
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_package_builder.py +91 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_sdk_image_detection.py +650 -11
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_sdk_network_doctor.py +4 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_vulcan.py +108 -4
- {sima_cli-2.1.12 → sima_cli-2.1.14}/LICENSE +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/MANIFEST.in +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/README.md +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/requirements.txt +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/setup.cfg +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/setup.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/__main__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/app_zoo/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/app_zoo/app.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/app_zoo/commands.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/auth/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/auth/auth0.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/auth/devportal.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/auth/login.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/cli.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/data/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/data/resources_internal.yaml +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/data/resources_public.yaml +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/deploy_only/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/deploy_only/device/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/deploy_only/device/commands.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/deploy_only/mpk/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/deploy_only/mpk/commands.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/discover/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/discover/discover.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/discover/linuxll.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/download/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/download/downloader.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/compatibility.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/github_assets.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/hostdriver.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/metadata_info.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/metadata_installer.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/metadata_validator.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/optiview.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/palette.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/install/registry.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/mla/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/mla/meminfo.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/model_zoo/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/model_zoo/model.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/network/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/network/network.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/playbooks/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/playbooks/commands.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/playbooks/manager.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/config.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/linux_devkit_network.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/linux_shared_network.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/preinstall.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/requirements.json +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/script.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/stop.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/sdk/uninstall.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/serial/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/serial/serial.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/storage/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/storage/nvme.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/storage/sdcard.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/bmaptool.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/bootimg.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/cleanlog.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/elxr.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/local.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/netboot.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/query.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/remote.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/update/updater.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/upgrade/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/upgrade/selfupdate.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/api_common.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/artifactory.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/common.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/config.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/config_loader.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/container_registries.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/deprecation.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/device_api.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/disk.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/env.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/errors.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/mpk_api.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/net.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/network.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/pcie.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/pkg_update_check.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/serializers.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/services.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/utils/tag.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli/vulcan/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli.egg-info/SOURCES.txt +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli.egg-info/dependency_links.txt +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli.egg-info/entry_points.txt +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli.egg-info/requires.txt +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/sima_cli.egg-info/top_level.txt +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/e2e/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/__init__.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_app_zoo.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_appzoo_commands.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_auth.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_auth0.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_cli.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_cli_stdio.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_cli_update.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_cli_update_rerun.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_deprecation.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_download.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_elxr_update.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_firmware.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_generate_cli_markdown_docs.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_install_stub.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_metadata_installer.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_metadata_validator.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_model_zoo.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_netboot.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_pkg_update_check.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_sdk_linux_shared_network.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_sdk_preinstall.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_sdk_uninstall.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_selfupdate.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_skills_commands.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_skills_manager.py +0 -0
- {sima_cli-2.1.12 → sima_cli-2.1.14}/tests/unit/test_utils.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# sima_cli/__version__.py
|
|
2
|
-
__version__ = "2.1.
|
|
2
|
+
__version__ = "2.1.14"
|
|
@@ -136,7 +136,17 @@ def _format_size(total_bytes: int) -> str:
|
|
|
136
136
|
|
|
137
137
|
def _matches_exclude_pattern(resource: str, patterns: Sequence[str]) -> bool:
|
|
138
138
|
filename = Path(resource).name
|
|
139
|
-
|
|
139
|
+
path_parts = resource.split("/")
|
|
140
|
+
for pattern in patterns:
|
|
141
|
+
if not pattern:
|
|
142
|
+
continue
|
|
143
|
+
if pattern.startswith(".") and "/" not in pattern and "\\" not in pattern:
|
|
144
|
+
if filename.endswith(pattern) or pattern in path_parts:
|
|
145
|
+
return True
|
|
146
|
+
continue
|
|
147
|
+
if pattern in resource or pattern in filename:
|
|
148
|
+
return True
|
|
149
|
+
return False
|
|
140
150
|
|
|
141
151
|
|
|
142
152
|
def collect_artifact_resources(
|
|
@@ -18,10 +18,15 @@ from sima_cli.sdk.utils import (
|
|
|
18
18
|
|
|
19
19
|
console = Console()
|
|
20
20
|
|
|
21
|
+
|
|
22
|
+
class SdkContainerUnavailable(RuntimeError):
|
|
23
|
+
"""Raised when no running SDK container matches a requested tool."""
|
|
24
|
+
|
|
25
|
+
|
|
21
26
|
# ─────────────────────────────────────────────
|
|
22
27
|
# Core executer
|
|
23
28
|
# ─────────────────────────────────────────────
|
|
24
|
-
def exec_container_cmd(ctx, keyword: str, cmd: Optional[str] = None):
|
|
29
|
+
def exec_container_cmd(ctx, keyword: str, cmd: Optional[str] = None, raise_on_missing: bool = False):
|
|
25
30
|
"""
|
|
26
31
|
Find a running container matching the given SDK keyword (e.g. mpk, yocto),
|
|
27
32
|
optionally filtering by version (from ctx.obj['version_filter']),
|
|
@@ -34,6 +39,8 @@ def exec_container_cmd(ctx, keyword: str, cmd: Optional[str] = None):
|
|
|
34
39
|
containers = get_all_containers(running_containers_only=True)
|
|
35
40
|
if not containers:
|
|
36
41
|
console.print("[yellow]⚠️ No running containers found.[/yellow]")
|
|
42
|
+
if raise_on_missing:
|
|
43
|
+
raise SdkContainerUnavailable("No running containers found.")
|
|
37
44
|
sys.exit(0)
|
|
38
45
|
|
|
39
46
|
# ──────────────────────────────────────────────
|
|
@@ -61,11 +68,16 @@ def exec_container_cmd(ctx, keyword: str, cmd: Optional[str] = None):
|
|
|
61
68
|
)
|
|
62
69
|
|
|
63
70
|
if not matches:
|
|
64
|
-
|
|
65
|
-
f"
|
|
71
|
+
message = (
|
|
72
|
+
f"No running containers found for '{keyword}'"
|
|
66
73
|
+ (f" with version '{version_filter}'" if version_filter else "")
|
|
67
|
-
+ ".
|
|
74
|
+
+ "."
|
|
75
|
+
)
|
|
76
|
+
console.print(
|
|
77
|
+
f"[red]❌ {message}[/red]"
|
|
68
78
|
)
|
|
79
|
+
if raise_on_missing:
|
|
80
|
+
raise SdkContainerUnavailable(message)
|
|
69
81
|
sys.exit(1)
|
|
70
82
|
|
|
71
83
|
# ──────────────────────────────────────────────
|
|
@@ -24,10 +24,10 @@ from typing import Optional
|
|
|
24
24
|
from rich.console import Console
|
|
25
25
|
from rich.panel import Panel
|
|
26
26
|
from sima_cli.sdk.install import setup_and_start
|
|
27
|
-
from sima_cli.sdk.cmdexec import exec_container_cmd
|
|
27
|
+
from sima_cli.sdk.cmdexec import SdkContainerUnavailable, exec_container_cmd
|
|
28
28
|
from sima_cli.sdk.uninstall import remove_containers, remove_unused_images
|
|
29
29
|
from sima_cli.sdk.stop import stop_containers
|
|
30
|
-
from sima_cli.sdk.utils import get_all_containers
|
|
30
|
+
from sima_cli.sdk.utils import get_all_containers, container_matches_sdk_keyword
|
|
31
31
|
from sima_cli.sdk.utils import extract_short_name
|
|
32
32
|
from sima_cli.discover.discover import discover_and_probe
|
|
33
33
|
from rich.table import Table
|
|
@@ -38,6 +38,7 @@ from sima_cli.sdk.config import IMAGE_CONFIG
|
|
|
38
38
|
from sima_cli.sdk.network_doctor import (
|
|
39
39
|
build_network_doctor_report,
|
|
40
40
|
collect_network_doctor_bundle,
|
|
41
|
+
ensure_existing_neat_container_startable,
|
|
41
42
|
print_network_doctor_report,
|
|
42
43
|
repair_linux_devkit_network,
|
|
43
44
|
)
|
|
@@ -156,7 +157,66 @@ def _resolve_devkit_ipv4(devkit: Optional[str]) -> str:
|
|
|
156
157
|
return value
|
|
157
158
|
|
|
158
159
|
|
|
159
|
-
def
|
|
160
|
+
def _container_name(container) -> str:
|
|
161
|
+
return container.get("Names") or container.get("Name") or container.get("name") or ""
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _container_is_running(container) -> bool:
|
|
165
|
+
state = (container.get("State") or "").lower().strip()
|
|
166
|
+
status = (container.get("Status") or "").lower().strip()
|
|
167
|
+
return state == "running" or status.startswith("up") or "running" in status
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _version_matches(container, version_filter: str) -> bool:
|
|
171
|
+
if not version_filter:
|
|
172
|
+
return True
|
|
173
|
+
needle = version_filter.lower()
|
|
174
|
+
name = _container_name(container).lower()
|
|
175
|
+
image = (container.get("Image") or container.get("image") or "").lower()
|
|
176
|
+
return needle in name or needle in image
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _start_stopped_neat_containers(ctx) -> None:
|
|
180
|
+
version_filter = None
|
|
181
|
+
if ctx and getattr(ctx, "obj", None):
|
|
182
|
+
version_filter = ctx.obj.get("version_filter")
|
|
183
|
+
|
|
184
|
+
containers = get_all_containers(running_containers_only=False)
|
|
185
|
+
matches = [
|
|
186
|
+
container
|
|
187
|
+
for container in containers
|
|
188
|
+
if container_matches_sdk_keyword(container, "neat")
|
|
189
|
+
and _version_matches(container, version_filter)
|
|
190
|
+
and not _container_is_running(container)
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
if not matches:
|
|
194
|
+
message = "No stopped Neat SDK containers found."
|
|
195
|
+
if version_filter:
|
|
196
|
+
message = f"No stopped Neat SDK containers found for version '{version_filter}'."
|
|
197
|
+
raise click.ClickException(f"{message} Run: sima-cli sdk setup")
|
|
198
|
+
|
|
199
|
+
for container in matches:
|
|
200
|
+
name = _container_name(container)
|
|
201
|
+
if not name:
|
|
202
|
+
continue
|
|
203
|
+
try:
|
|
204
|
+
ensure_existing_neat_container_startable(name)
|
|
205
|
+
console.print(
|
|
206
|
+
f"[cyan]▶ Starting existing Neat SDK container:[/cyan] [bold]{name}[/bold] "
|
|
207
|
+
"[dim](this may take a moment)[/dim]"
|
|
208
|
+
)
|
|
209
|
+
subprocess.run(["docker", "start", name], check=True, capture_output=True, text=True)
|
|
210
|
+
except subprocess.CalledProcessError as e:
|
|
211
|
+
raise click.ClickException(
|
|
212
|
+
f"Failed to start Neat SDK container '{name}' while running: {' '.join(e.cmd)}"
|
|
213
|
+
) from e
|
|
214
|
+
except RuntimeError as e:
|
|
215
|
+
raise click.ClickException(str(e)) from e
|
|
216
|
+
console.print(f"[green]✅ Started Neat SDK container:[/green] [bold]{name}[/bold]")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def launch_sdk_tool(tool: str, cmd, ctx, recover_unavailable: bool = False):
|
|
160
220
|
"""
|
|
161
221
|
Launch a selected SDK tool container, optionally executing a command inside it.
|
|
162
222
|
If no command is provided, defaults to an interactive bash login shell.
|
|
@@ -182,7 +242,17 @@ def launch_sdk_tool(tool: str, cmd, ctx):
|
|
|
182
242
|
else:
|
|
183
243
|
cmd_str = str(cmd)
|
|
184
244
|
|
|
185
|
-
|
|
245
|
+
if not recover_unavailable:
|
|
246
|
+
exec_container_cmd(ctx, tool, cmd_str)
|
|
247
|
+
return
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
exec_container_cmd(ctx, tool, cmd_str, raise_on_missing=True)
|
|
251
|
+
except SdkContainerUnavailable:
|
|
252
|
+
if tool != "neat":
|
|
253
|
+
raise
|
|
254
|
+
_start_stopped_neat_containers(ctx)
|
|
255
|
+
exec_container_cmd(ctx, tool, cmd_str)
|
|
186
256
|
|
|
187
257
|
|
|
188
258
|
# ------------------------------------------------------------
|
|
@@ -554,13 +624,16 @@ def neat(ctx, cmd):
|
|
|
554
624
|
running container with bash -lc. If CMD is omitted, sima-cli opens an
|
|
555
625
|
interactive login shell.
|
|
556
626
|
|
|
627
|
+
If no matching Neat SDK container is running, existing stopped Neat SDK
|
|
628
|
+
container(s) are started automatically and the command is retried.
|
|
629
|
+
|
|
557
630
|
\b
|
|
558
631
|
Examples:
|
|
559
632
|
sima-cli sdk neat
|
|
560
633
|
sima-cli sdk neat python --version
|
|
561
634
|
sima-cli sdk neat "python app.py --config config.json"
|
|
562
635
|
"""
|
|
563
|
-
launch_sdk_tool("neat", cmd, ctx)
|
|
636
|
+
launch_sdk_tool("neat", cmd, ctx, recover_unavailable=True)
|
|
564
637
|
|
|
565
638
|
|
|
566
639
|
@sdk.command(
|
|
@@ -765,6 +765,22 @@ def _format_gb(byte_count: int) -> str:
|
|
|
765
765
|
return f"{byte_count / (1024 ** 3):.1f} GB"
|
|
766
766
|
|
|
767
767
|
|
|
768
|
+
def _ensure_writable_sdk_extensions_dir(path: Path) -> Path:
|
|
769
|
+
resolved = Path(os.path.realpath(str(path)))
|
|
770
|
+
try:
|
|
771
|
+
resolved.mkdir(parents=True, exist_ok=True)
|
|
772
|
+
probe = resolved / ".sima-cli-write-test"
|
|
773
|
+
with open(probe, "w", encoding="utf-8") as handle:
|
|
774
|
+
handle.write("ok\n")
|
|
775
|
+
probe.unlink()
|
|
776
|
+
except OSError as e:
|
|
777
|
+
raise RuntimeError(
|
|
778
|
+
f"SDK extensions directory is not writable: {resolved}. "
|
|
779
|
+
"Choose another directory where your user can create files."
|
|
780
|
+
) from e
|
|
781
|
+
return resolved
|
|
782
|
+
|
|
783
|
+
|
|
768
784
|
def _setup_sdk_extensions(
|
|
769
785
|
selected_images: List[str],
|
|
770
786
|
noninteractive: bool = False,
|
|
@@ -791,12 +807,16 @@ def _setup_sdk_extensions(
|
|
|
791
807
|
if noninteractive or yes_to_all:
|
|
792
808
|
extensions_dir = default_extensions_dir
|
|
793
809
|
click.echo(f"ℹ️ Using default SDK extensions directory: {extensions_dir}")
|
|
810
|
+
extensions_dir = _ensure_writable_sdk_extensions_dir(extensions_dir)
|
|
794
811
|
else:
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
812
|
+
while True:
|
|
813
|
+
response = input(f"Enter SDK extensions directory [{default_extensions_dir}]: ").strip()
|
|
814
|
+
extensions_dir = Path(response).expanduser() if response else default_extensions_dir
|
|
815
|
+
try:
|
|
816
|
+
extensions_dir = _ensure_writable_sdk_extensions_dir(extensions_dir)
|
|
817
|
+
break
|
|
818
|
+
except RuntimeError as e:
|
|
819
|
+
click.secho(f"⚠️ {e}", fg="yellow")
|
|
800
820
|
print(f"✅ SDK extensions directory configured: {extensions_dir}")
|
|
801
821
|
return str(extensions_dir)
|
|
802
822
|
|
|
@@ -1148,6 +1168,16 @@ def setup_and_start(
|
|
|
1148
1168
|
configure_container_user(existing_container, login_name, user_uid, user_gid)
|
|
1149
1169
|
|
|
1150
1170
|
if devkit_env and is_neat_sdk_image(img):
|
|
1171
|
+
if not skip_insight:
|
|
1172
|
+
# Re-issue the mounted HTTPS cert for the (possibly new) host
|
|
1173
|
+
# IP before bootstrap restarts neat-insight, so the browser
|
|
1174
|
+
# doesn't hit a SAN mismatch ("connection is not private")
|
|
1175
|
+
# after a re-point.
|
|
1176
|
+
from sima_cli.sdk.neat import refresh_neat_certificates
|
|
1177
|
+
refresh_neat_certificates(
|
|
1178
|
+
workspace, existing_container, devkit_env,
|
|
1179
|
+
yes_to_all=yes_to_all, noninteractive=noninteractive,
|
|
1180
|
+
)
|
|
1151
1181
|
bootstrap_devkit_container(existing_container, devkit_env)
|
|
1152
1182
|
|
|
1153
1183
|
if len(selected_images) == 1:
|