acex-cli 4.2.0__tar.gz → 4.3.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acex-cli
3
- Version: 4.2.0
3
+ Version: 4.3.0
4
4
  Summary: ACE-X CLI - Command-line interface for ACE-X
5
5
  License: AGPL-3.0
6
6
  Keywords: automation,cli,control
@@ -11,8 +11,8 @@ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Programming Language :: Python :: 3.14
14
- Requires-Dist: acex-client (>=4.2.0,<5.0.0)
15
- Requires-Dist: acex-driver-cisco-ioscli (>=0.0.17,<0.0.18)
14
+ Requires-Dist: acex-client (>=4.2.1,<5.0.0)
15
+ Requires-Dist: acex-driver-cisco-ioscli (>=0.3.0,<0.4.0)
16
16
  Requires-Dist: click (==8.1.7)
17
17
  Requires-Dist: ntc-templates (>=8.1.0,<9.0.0)
18
18
  Requires-Dist: rich (>=13.0.0,<14.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "acex-cli"
3
- version = "4.2.0"
3
+ version = "4.3.0"
4
4
  description = "ACE-X CLI - Command-line interface for ACE-X"
5
5
  authors = ["Johan Lahti <johan.lahti@acebit.se>"]
6
6
  readme = "README.md"
@@ -17,8 +17,8 @@ python = "^3.13"
17
17
  typer = "^0.12.0"
18
18
  rich = "^13.0.0"
19
19
  click = "8.1.7"
20
- acex-client = "^4.2.0" # Changes to real dep. by switch_acex_client_dep for publishing
21
- acex-driver-cisco-ioscli = "^0.0.17"
20
+ acex-client = "^4.2.1" # Changes to real dep. by switch_acex_client_dep for publishing
21
+ acex-driver-cisco-ioscli = "^0.3.0"
22
22
  ntc-templates = "^8.1.0"
23
23
 
24
24
  [tool.poetry.scripts]
@@ -0,0 +1,67 @@
1
+ from typing import Optional
2
+
3
+ import typer
4
+
5
+ from acex_cli.sdk import get_sdk
6
+ from acex_cli.output import display_list, display_object
7
+ from acex_client.models.generated_models import AssetResponse
8
+
9
+ app = typer.Typer(help="Asset resource commands")
10
+
11
+
12
+ @app.command("list")
13
+ def list_cmd(
14
+ ctx: typer.Context,
15
+ # Filters (match backend query params)
16
+ vendor: Optional[str] = typer.Option(None, help="Filter by vendor (prefix match)"),
17
+ os: Optional[str] = typer.Option(None, "--os", help="Filter by OS"),
18
+ hardware_model: Optional[str] = typer.Option(None, help="Filter by hardware model"),
19
+ ned_id: Optional[str] = typer.Option(None, help="Filter by NED ID"),
20
+ serial_number: Optional[str] = typer.Option(None, help="Filter by serial number"),
21
+ assigned: Optional[bool] = typer.Option(None, help="Filter assigned/unassigned"),
22
+ # Pagination
23
+ limit: int = typer.Option(100, "--limit", "-l", help="Max items to return"),
24
+ offset: int = typer.Option(0, "--offset", help="Items to skip"),
25
+ # Output
26
+ format: str = typer.Option("table", "--format", "-f", help="Output format: table, json, csv"),
27
+ columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated columns"),
28
+ no_header: bool = typer.Option(False, "--no-header", help="Hide table header"),
29
+ ):
30
+ """List assets with optional filters."""
31
+ sdk = get_sdk(ctx.obj.get_active_context())
32
+ filters = _compact(
33
+ vendor=vendor, os=os, hardware_model=hardware_model,
34
+ ned_id=ned_id, serial_number=serial_number, assigned=assigned,
35
+ )
36
+ result = sdk.assets.query(limit=limit, offset=offset, **filters)
37
+ display_list(
38
+ result,
39
+ format=format,
40
+ columns=columns.split(",") if columns else None,
41
+ no_header=no_header,
42
+ model=AssetResponse,
43
+ title="Assets",
44
+ )
45
+
46
+
47
+ @app.command("show")
48
+ def show_cmd(
49
+ ctx: typer.Context,
50
+ asset_id: str,
51
+ format: str = typer.Option("table", "--format", "-f", help="Output format: table, json, csv"),
52
+ columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated fields"),
53
+ ):
54
+ """Show details for an asset."""
55
+ sdk = get_sdk(ctx.obj.get_active_context())
56
+ asset = sdk.assets.get(asset_id)
57
+ display_object(
58
+ asset,
59
+ format=format,
60
+ columns=columns.split(",") if columns else None,
61
+ model=AssetResponse,
62
+ title=f"Asset {asset_id}",
63
+ )
64
+
65
+
66
+ def _compact(**kwargs):
67
+ return {k: v for k, v in kwargs.items() if v is not None}
@@ -0,0 +1,65 @@
1
+ from typing import Optional
2
+
3
+ import typer
4
+
5
+ from acex_cli.sdk import get_sdk
6
+ from acex_cli.output import display_list, display_object
7
+ from acex_client.models.generated_models import LogicalNode
8
+
9
+ app = typer.Typer(help="Logical node resource commands")
10
+
11
+
12
+ @app.command("list")
13
+ def list_cmd(
14
+ ctx: typer.Context,
15
+ # Filters (match backend query params)
16
+ role: Optional[str] = typer.Option(None, help="Filter by role (prefix match)"),
17
+ site: Optional[str] = typer.Option(None, help="Filter by site (prefix match)"),
18
+ hostname: Optional[str] = typer.Option(None, help="Filter by hostname (prefix match)"),
19
+ sequence: Optional[int] = typer.Option(None, help="Filter by sequence number"),
20
+ assigned: Optional[bool] = typer.Option(None, help="Filter assigned/unassigned"),
21
+ # Pagination
22
+ limit: int = typer.Option(100, "--limit", "-l", help="Max items to return"),
23
+ offset: int = typer.Option(0, "--offset", help="Items to skip"),
24
+ # Output
25
+ format: str = typer.Option("table", "--format", "-f", help="Output format: table, json, csv"),
26
+ columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated columns"),
27
+ no_header: bool = typer.Option(False, "--no-header", help="Hide table header"),
28
+ ):
29
+ """List logical nodes with optional filters."""
30
+ sdk = get_sdk(ctx.obj.get_active_context())
31
+ filters = _compact(
32
+ role=role, site=site, hostname=hostname,
33
+ sequence=sequence, assigned=assigned,
34
+ )
35
+ result = sdk.logical_nodes.query(limit=limit, offset=offset, **filters)
36
+ display_list(
37
+ result,
38
+ format=format,
39
+ columns=columns.split(",") if columns else None,
40
+ no_header=no_header,
41
+ model=LogicalNode,
42
+ title="Logical Nodes",
43
+ )
44
+
45
+
46
+ @app.command("show")
47
+ def show_cmd(
48
+ ctx: typer.Context,
49
+ logical_node_id: str,
50
+ format: str = typer.Option("table", "--format", "-f", help="Output format: table, json, csv"),
51
+ columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated fields"),
52
+ ):
53
+ """Show details for a logical node."""
54
+ sdk = get_sdk(ctx.obj.get_active_context())
55
+ logical_node = sdk.logical_nodes.get(logical_node_id)
56
+ display_object(
57
+ logical_node,
58
+ format=format,
59
+ columns=columns.split(",") if columns else None,
60
+ title=f"Logical Node {logical_node_id}",
61
+ )
62
+
63
+
64
+ def _compact(**kwargs):
65
+ return {k: v for k, v in kwargs.items() if v is not None}
@@ -0,0 +1,49 @@
1
+ from typing import Optional
2
+
3
+ import typer
4
+
5
+ from acex_cli.sdk import get_sdk
6
+ from acex_cli.output import display_list, display_object
7
+ from acex_client.models.generated_models import Ned
8
+
9
+ app = typer.Typer(help="NED (Network Element Driver) commands")
10
+
11
+
12
+ @app.command("list")
13
+ def list_cmd(
14
+ ctx: typer.Context,
15
+ # Output (NEDs endpoint has no server-side filters or pagination)
16
+ format: str = typer.Option("table", "--format", "-f", help="Output format: table, json, csv"),
17
+ columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated columns"),
18
+ no_header: bool = typer.Option(False, "--no-header", help="Hide table header"),
19
+ ):
20
+ """List available NEDs."""
21
+ sdk = get_sdk(ctx.obj.get_active_context())
22
+ result = sdk.neds.query()
23
+ display_list(
24
+ result,
25
+ format=format,
26
+ columns=columns.split(",") if columns else None,
27
+ no_header=no_header,
28
+ model=Ned,
29
+ title="NEDs",
30
+ )
31
+
32
+
33
+ @app.command("show")
34
+ def show_cmd(
35
+ ctx: typer.Context,
36
+ ned_id: str,
37
+ format: str = typer.Option("table", "--format", "-f", help="Output format: table, json, csv"),
38
+ columns: Optional[str] = typer.Option(None, "--columns", "-c", help="Comma-separated fields"),
39
+ ):
40
+ """Show details for a NED."""
41
+ sdk = get_sdk(ctx.obj.get_active_context())
42
+ ned = sdk.neds.get(ned_id)
43
+ display_object(
44
+ ned,
45
+ format=format,
46
+ columns=columns.split(",") if columns else None,
47
+ model=Ned,
48
+ title=f"NED {ned_id}",
49
+ )