clue2app-cli 0.3.0__tar.gz → 0.3.1__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.
- {clue2app_cli-0.3.0/src/clue2app_cli.egg-info → clue2app_cli-0.3.1}/PKG-INFO +1 -1
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/pyproject.toml +1 -1
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/main.py +110 -1
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/sdk.py +18 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1/src/clue2app_cli.egg-info}/PKG-INFO +1 -1
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/LICENSE +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/README.md +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/setup.cfg +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/__init__.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/agents/__init__.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/agents/ecr_healer.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/auth.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/config.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/core_client.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/creds_module.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/curses_wizard.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/directory_cmd.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/entrypoint_check.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/mcp_cmd.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tests_cmd.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tests_schema/__init__.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tests_schema/c2a-tests.v1.json +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tests_schema/validator.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui/__init__.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui/curses_app.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui/data.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui/screens/__init__.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui/textual_app.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui/widgets/__init__.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/tui_wizard.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/version.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli/wizard.py +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli.egg-info/SOURCES.txt +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli.egg-info/dependency_links.txt +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli.egg-info/entry_points.txt +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli.egg-info/requires.txt +0 -0
- {clue2app_cli-0.3.0 → clue2app_cli-0.3.1}/src/clue2app_cli.egg-info/top_level.txt +0 -0
|
@@ -3815,17 +3815,34 @@ def llm_create(name):
|
|
|
3815
3815
|
"""
|
|
3816
3816
|
from .sdk import Clue2AppSDK
|
|
3817
3817
|
from .auth import is_authenticated
|
|
3818
|
+
from .config import get_active_project
|
|
3818
3819
|
|
|
3819
3820
|
if not is_authenticated():
|
|
3820
3821
|
console.print("[red]Not authenticated.[/red] Run [bold]c2a login[/bold] first.")
|
|
3821
3822
|
return
|
|
3822
3823
|
|
|
3824
|
+
# SCK-740 / clue2app-cli#117: coord's K8sServiceCatalogController.
|
|
3825
|
+
# resolveProjectId reads `projectId` (or `appGroupId`) from the request
|
|
3826
|
+
# body OR the query string. Previously this call sent only {"name": name},
|
|
3827
|
+
# so coord saw no project context and returned
|
|
3828
|
+
# 500 "No active project context for LLM Gateway instance creation"
|
|
3829
|
+
# even when `c2a project use <name>` had set the active project on this
|
|
3830
|
+
# machine. Every other project-scoped CLI verb reads get_active_project()
|
|
3831
|
+
# and threads the id through; llm_create was missed.
|
|
3832
|
+
active = get_active_project()
|
|
3833
|
+
if not active or not active.get("id"):
|
|
3834
|
+
console.print(
|
|
3835
|
+
"[red]No active project.[/red] Set one with "
|
|
3836
|
+
"[bold]c2a project use <name>[/bold] first."
|
|
3837
|
+
)
|
|
3838
|
+
return
|
|
3839
|
+
|
|
3823
3840
|
sdk = Clue2AppSDK()
|
|
3824
3841
|
try:
|
|
3825
3842
|
resp = sdk._make_authenticated_request(
|
|
3826
3843
|
"POST",
|
|
3827
3844
|
"/api/k8s-service-catalog/llm-gateway",
|
|
3828
|
-
json={"name": name},
|
|
3845
|
+
json={"name": name, "projectId": active.get("id")},
|
|
3829
3846
|
)
|
|
3830
3847
|
except Exception as e:
|
|
3831
3848
|
console.print(f"[red]create call failed: {e}[/red]")
|
|
@@ -6553,6 +6570,98 @@ def project_show_cmd(ctx: ClueAppContext, name: str):
|
|
|
6553
6570
|
console.print_exception()
|
|
6554
6571
|
|
|
6555
6572
|
|
|
6573
|
+
def _resolve_project(sdk, name_or_id):
|
|
6574
|
+
"""SCK-737 shared helper: find a project by name, ns, or id. Returns dict or None."""
|
|
6575
|
+
for p in sdk.list_projects():
|
|
6576
|
+
if (p.get('name', '').lower() == name_or_id.lower()
|
|
6577
|
+
or p.get('ns', '').lower() == name_or_id.lower()
|
|
6578
|
+
or p.get('id') == name_or_id):
|
|
6579
|
+
return p
|
|
6580
|
+
return None
|
|
6581
|
+
|
|
6582
|
+
|
|
6583
|
+
@project_group.command(name='lock')
|
|
6584
|
+
@click.argument('name')
|
|
6585
|
+
@click.option('--yes', '-y', is_flag=True, help='Skip confirmation')
|
|
6586
|
+
@pass_context
|
|
6587
|
+
def project_lock_cmd(ctx: ClueAppContext, name: str, yes: bool):
|
|
6588
|
+
"""Lock a project — blocks new app deploys until unlocked (SCK-737).
|
|
6589
|
+
|
|
6590
|
+
A locked project rejects `c2a app create` and new build triggers,
|
|
6591
|
+
but existing apps keep serving traffic. Caller must have
|
|
6592
|
+
PROJECT_ADMIN or SYSTEM.
|
|
6593
|
+
|
|
6594
|
+
Examples:
|
|
6595
|
+
c2a project lock my-project
|
|
6596
|
+
c2a project lock my-project --yes
|
|
6597
|
+
"""
|
|
6598
|
+
from .sdk import Clue2AppSDK
|
|
6599
|
+
from .auth import is_authenticated
|
|
6600
|
+
from rich.prompt import Confirm
|
|
6601
|
+
|
|
6602
|
+
if not is_authenticated():
|
|
6603
|
+
console.print("[red]Not authenticated.[/red] Run [bold]c2a login[/bold] first.")
|
|
6604
|
+
return
|
|
6605
|
+
|
|
6606
|
+
try:
|
|
6607
|
+
sdk = Clue2AppSDK()
|
|
6608
|
+
found = _resolve_project(sdk, name)
|
|
6609
|
+
if not found:
|
|
6610
|
+
console.print(f"[red]Project not found:[/red] {name}")
|
|
6611
|
+
return
|
|
6612
|
+
if found.get('locked'):
|
|
6613
|
+
console.print(f"[yellow]Project '{found.get('name')}' is already locked.[/yellow]")
|
|
6614
|
+
return
|
|
6615
|
+
if not yes:
|
|
6616
|
+
if not Confirm.ask(
|
|
6617
|
+
f"Lock project '[bold]{found.get('name')}[/bold]'? "
|
|
6618
|
+
"New app deploys will be blocked until unlocked."):
|
|
6619
|
+
console.print("Cancelled.")
|
|
6620
|
+
return
|
|
6621
|
+
if sdk.set_project_locked(found['id'], True):
|
|
6622
|
+
console.print(f"[green]✓ Project '{found.get('name')}' locked.[/green]")
|
|
6623
|
+
console.print(f" Unlock with: [dim]c2a project unlock {found.get('name')}[/dim]")
|
|
6624
|
+
except Exception as e:
|
|
6625
|
+
console.print(f"[red]Error locking project:[/red] {e}")
|
|
6626
|
+
if ctx.debug:
|
|
6627
|
+
console.print_exception()
|
|
6628
|
+
|
|
6629
|
+
|
|
6630
|
+
@project_group.command(name='unlock')
|
|
6631
|
+
@click.argument('name')
|
|
6632
|
+
@pass_context
|
|
6633
|
+
def project_unlock_cmd(ctx: ClueAppContext, name: str):
|
|
6634
|
+
"""Unlock a project — restores app-deploy capability (SCK-737).
|
|
6635
|
+
|
|
6636
|
+
Reverses `c2a project lock`. Caller must have PROJECT_ADMIN or SYSTEM.
|
|
6637
|
+
|
|
6638
|
+
Examples:
|
|
6639
|
+
c2a project unlock my-project
|
|
6640
|
+
"""
|
|
6641
|
+
from .sdk import Clue2AppSDK
|
|
6642
|
+
from .auth import is_authenticated
|
|
6643
|
+
|
|
6644
|
+
if not is_authenticated():
|
|
6645
|
+
console.print("[red]Not authenticated.[/red] Run [bold]c2a login[/bold] first.")
|
|
6646
|
+
return
|
|
6647
|
+
|
|
6648
|
+
try:
|
|
6649
|
+
sdk = Clue2AppSDK()
|
|
6650
|
+
found = _resolve_project(sdk, name)
|
|
6651
|
+
if not found:
|
|
6652
|
+
console.print(f"[red]Project not found:[/red] {name}")
|
|
6653
|
+
return
|
|
6654
|
+
if not found.get('locked'):
|
|
6655
|
+
console.print(f"[yellow]Project '{found.get('name')}' is already unlocked.[/yellow]")
|
|
6656
|
+
return
|
|
6657
|
+
if sdk.set_project_locked(found['id'], False):
|
|
6658
|
+
console.print(f"[green]✓ Project '{found.get('name')}' unlocked.[/green]")
|
|
6659
|
+
except Exception as e:
|
|
6660
|
+
console.print(f"[red]Error unlocking project:[/red] {e}")
|
|
6661
|
+
if ctx.debug:
|
|
6662
|
+
console.print_exception()
|
|
6663
|
+
|
|
6664
|
+
|
|
6556
6665
|
# === USER group ===
|
|
6557
6666
|
|
|
6558
6667
|
@cli.group(name='user')
|
|
@@ -1288,6 +1288,24 @@ class Clue2AppSDK:
|
|
|
1288
1288
|
console.print(f"[red]Error deleting project {project_id}:[/red] {e}")
|
|
1289
1289
|
return False
|
|
1290
1290
|
|
|
1291
|
+
def set_project_locked(self, project_id: str, locked: bool) -> bool:
|
|
1292
|
+
"""Lock or unlock a project (SCK-737).
|
|
1293
|
+
|
|
1294
|
+
Wraps coord's POST /api/k8s-project/{id}/locked/{true|false} —
|
|
1295
|
+
a locked project refuses new app deploys. Operator-level action;
|
|
1296
|
+
caller must have PROJECT_ADMIN or SYSTEM.
|
|
1297
|
+
"""
|
|
1298
|
+
try:
|
|
1299
|
+
flag = "true" if locked else "false"
|
|
1300
|
+
response = self._make_authenticated_request(
|
|
1301
|
+
"POST", f"/api/k8s-project/{project_id}/locked/{flag}", timeout=30)
|
|
1302
|
+
response.raise_for_status()
|
|
1303
|
+
return True
|
|
1304
|
+
except requests.exceptions.RequestException as e:
|
|
1305
|
+
verb = "lock" if locked else "unlock"
|
|
1306
|
+
console.print(f"[red]Error {verb}ing project {project_id}:[/red] {e}")
|
|
1307
|
+
return False
|
|
1308
|
+
|
|
1291
1309
|
def create_app(self, name: str, git_url: str, project_id: str = None,
|
|
1292
1310
|
git_username: str = "git", git_password: str = "",
|
|
1293
1311
|
branch: str = "main", config: Dict[str, Any] = None,
|
|
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
|