centralcli 5.2.1__tar.gz → 5.2.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.
Files changed (59) hide show
  1. {centralcli-5.2.1 → centralcli-5.2.2}/PKG-INFO +1 -1
  2. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/central.py +4 -3
  3. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cleaner.py +38 -5
  4. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishow.py +15 -8
  5. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliupdate.py +1 -1
  6. {centralcli-5.2.1 → centralcli-5.2.2}/pyproject.toml +1 -1
  7. centralcli-5.2.1/centralcli/boilerplate/cnx_allcalls.py +0 -59399
  8. {centralcli-5.2.1 → centralcli-5.2.2}/LICENSE +0 -0
  9. {centralcli-5.2.1 → centralcli-5.2.2}/README.md +0 -0
  10. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/__init__.py +0 -0
  11. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/boilerplate/README.md +0 -0
  12. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/boilerplate/allcalls.py +0 -0
  13. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/caas.py +0 -0
  14. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cache.py +0 -0
  15. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cli.py +0 -0
  16. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliadd.py +0 -0
  17. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliassign.py +0 -0
  18. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clibatch.py +0 -0
  19. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clicaas.py +0 -0
  20. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliclone.py +0 -0
  21. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clicommon.py +0 -0
  22. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clidel.py +0 -0
  23. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clidelfirmware.py +0 -0
  24. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliexport.py +0 -0
  25. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clikick.py +0 -0
  26. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clioptions.py +0 -0
  27. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clirefresh.py +0 -0
  28. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clirename.py +0 -0
  29. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliset.py +0 -0
  30. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clisetfirmware.py +0 -0
  31. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowaudit.py +0 -0
  32. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowbranch.py +0 -0
  33. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowcloudauth.py +0 -0
  34. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowfirmware.py +0 -0
  35. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowmpsk.py +0 -0
  36. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowospf.py +0 -0
  37. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowoverlay.py +0 -0
  38. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowtshoot.py +0 -0
  39. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clishowwids.py +0 -0
  40. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clitest.py +0 -0
  41. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/clitshoot.py +0 -0
  42. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliunassign.py +0 -0
  43. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/cliupgrade.py +0 -0
  44. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/config.py +0 -0
  45. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/constants.py +0 -0
  46. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/exceptions.py +0 -0
  47. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/logger.py +0 -0
  48. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/models.py +0 -0
  49. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/objects.py +0 -0
  50. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/render.py +0 -0
  51. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/response.py +0 -0
  52. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/setup.py +0 -0
  53. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/static/favicon.ico +0 -0
  54. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/strings.py +0 -0
  55. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/utils.py +0 -0
  56. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/vscodeargs.py +0 -0
  57. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/wh2snow.py +0 -0
  58. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/wh_proxy.py +0 -0
  59. {centralcli-5.2.1 → centralcli-5.2.2}/centralcli/wh_proxy_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: centralcli
3
- Version: 5.2.1
3
+ Version: 5.2.2
4
4
  Summary: A CLI for interacting with Aruba Central (Cloud Management Platform). Facilitates bulk imports, exports, reporting. A handy tool if you have devices managed by Aruba Central.
5
5
  Home-page: https://github.com/Pack3tL0ss/central-api-cli
6
6
  License: MIT
@@ -2784,6 +2784,8 @@ class CentralApi(Session):
2784
2784
  return await self.post(url, json_data=json_data)
2785
2785
 
2786
2786
  # API-FLAW add ap and gw to group with gw-role as wlan and upgrade to aos10. Returns 200, but no changes made
2787
+ # TODO need to add flag for SD_WAN_Gateway architecture (Silver Peak), only valid associated GwNetworkRole is VPNConcentrator
2788
+ # TODO need to add SD_WAN_Gateway to AllowedDevTypes
2787
2789
  async def update_group_properties(
2788
2790
  self,
2789
2791
  group: str,
@@ -2794,7 +2796,7 @@ class CentralApi(Session):
2794
2796
  microbranch: bool = None,
2795
2797
  gw_role: constants.GatewayRole = None,
2796
2798
  monitor_only_sw: bool = None,
2797
- monitor_only_cx: bool = None, # Not supported by central yet
2799
+ monitor_only_cx: bool = None,
2798
2800
  ) -> Response:
2799
2801
  """Update properties for the given group.
2800
2802
 
@@ -2822,7 +2824,7 @@ class CentralApi(Session):
2822
2824
  microbranch (bool): True to enable Microbranch network role for APs is applicable only for AOS10 architecture.
2823
2825
  gw_role (GatewayRole): Gateway role valid values "branch", "vpnc", "wlan" ("wlan" only valid on AOS10 group)
2824
2826
  monitor_only_sw: Monitor only ArubaOS-SW switches, applies to UI group only
2825
- monitor_only_cx: Monitor only ArubaOS-CX switches, applies to UI group only (Future capability)
2827
+ monitor_only_cx: Monitor only ArubaOS-CX switches, applies to UI group only
2826
2828
 
2827
2829
  Returns:
2828
2830
  Response: CentralAPI Response object
@@ -2906,7 +2908,6 @@ class CentralApi(Session):
2906
2908
  mon_only_switches += ["AOS_S"]
2907
2909
  if monitor_only_cx:
2908
2910
  mon_only_switches += ["AOS_CX"]
2909
- raise NotImplementedError("AOS_CX Monitor Only not supported in Central yet.")
2910
2911
 
2911
2912
  arch = None
2912
2913
  if microbranch is not None:
@@ -13,7 +13,7 @@ import sys
13
13
  import json
14
14
  from enum import Enum
15
15
  from pathlib import Path
16
- from typing import Any, Dict, List, Union
16
+ from typing import Any, Dict, List, Union, Literal
17
17
 
18
18
  import pendulum
19
19
  from rich.console import Console
@@ -1774,9 +1774,10 @@ def cloudauth_get_namedmpsk(data: List[Dict[str, Any]], verbosity: int = 0,) ->
1774
1774
  def show_all_ap_lldp_neighbors_for_site(data):
1775
1775
  data = utils.unlistify(data)
1776
1776
  # TODO circular import if placed at top review import logic
1777
- from centralcli import cache
1778
- aps_in_cache = [dev["serial"] for dev in cache.devices if dev["type"] == "ap"]
1779
- ap_connections = [edge for edge in data["edges"] if edge["toIf"]["serial"] in aps_in_cache]
1777
+ # from centralcli import cache
1778
+ # aps_in_cache = [dev["serial"] for dev in cache.devices if dev["type"] == "ap"]
1779
+ aps_in_site = [dev.get("serial") for dev in data["devices"] if dev["role"] == "IAP"]
1780
+ ap_connections = [edge for edge in data["edges"] if edge["toIf"]["serial"] in aps_in_site]
1780
1781
  data = [
1781
1782
  {
1782
1783
  "ap": x["toIf"].get("deviceName", "--"),
@@ -1790,9 +1791,41 @@ def show_all_ap_lldp_neighbors_for_site(data):
1790
1791
  "switch_serial": x["fromIf"].get("serial", "--"),
1791
1792
  "switch_port": x["fromIf"].get("name", "--"),
1792
1793
  "untagged_vlan": x["fromIf"].get("untaggedVlan", "--"),
1793
- "tagged_vlans": ",".join([str(v) for v in x["fromIf"].get("taggedVlans") or [] if v != x["fromIf"].get("untaggedVlan", 9999)]),
1794
+ "tagged_vlans": ",".join([str(v) for v in sorted(x["fromIf"].get("taggedVlans") or []) if v != x["fromIf"].get("untaggedVlan", 9999)]),
1794
1795
  "healthy": "✅" if x.get("health", "") == "good" else "❌"
1795
1796
  } for x in ap_connections
1796
1797
  ]
1797
1798
 
1799
+ return simple_kv_formatter(data)
1800
+
1801
+
1802
+ def show_all_ap_lldp_neighbors_for_sitev2(data, filter: Literal["up", "down"] = None):
1803
+ data = utils.unlistify(data)
1804
+ # TODO circular import if placed at top review import logic
1805
+ from centralcli import cache
1806
+ # switches_in_cache = [dev["serial"] for dev in cache.devices if dev["type"] in ["cx", "sw"]]
1807
+ if filter is None:
1808
+ aps_in_site = {dev["serial"]: dev for dev in data["devices"] if dev["role"] == "IAP"}
1809
+ else:
1810
+ status = 0 if filter == "down" else 1
1811
+ aps_in_site = {dev["serial"]: dev for dev in data["devices"] if dev["role"] == "IAP" and dev["status"] == status}
1812
+ ap_connections = {edge["toIf"]["serial"]: edge for edge in data["edges"] if edge["toIf"]["serial"] in aps_in_site}
1813
+ data = [
1814
+ {
1815
+ "ap": aps_in_site[ap].get("name", "--"),
1816
+ "ap_ip": aps_in_site[ap].get("ipAddress", "--"),
1817
+ "ap_serial": aps_in_site[ap].get("serial", "--"),
1818
+ "ap_port": ap_connections.get(ap, {"toIf": {}})["toIf"].get("portNumber", "--"),
1819
+ # "ap_untagged_vlan": x["toIf"].get("untaggedVlan"),
1820
+ # "ap_tagged_vlans": x["toIf"].get("taggedVlans"),
1821
+ "switch": ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("deviceName", "--"),
1822
+ "switch_ip": ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("ipAddress", "--") if ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("ipAddress") not in [None, "Unknown"] else cache.devices_by_serial.get(ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("serial", "--"), {}).get("ip", "--"),
1823
+ "switch_serial": ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("serial", "--"),
1824
+ "switch_port": ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("name", "--"),
1825
+ "untagged_vlan": ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("untaggedVlan", "--"),
1826
+ "tagged_vlans": ",".join([str(v) for v in sorted(ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("taggedVlans") or []) if v != ap_connections.get(ap, {"fromIf": {}})["fromIf"].get("untaggedVlan", 9999)]),
1827
+ "healthy": "✅" if aps_in_site[ap].get("health", "") == "good" else "❌"
1828
+ } for ap in aps_in_site
1829
+ ]
1830
+
1798
1831
  return simple_kv_formatter(data)
@@ -461,15 +461,22 @@ def aps(
461
461
  print(":x: [bright_red]Error:[/] [cyan]--site <site name>[/] is required for neighbors output.")
462
462
  raise typer.Exit(1)
463
463
 
464
- site = cli.cache.get_site_identifier(site)
465
- resp = cli.central.request(cli.central.get_topo_for_site, site.id, )
466
- tablefmt = cli.get_format(do_json=do_json, do_yaml=do_yaml, do_csv=do_csv, do_table=do_table, default="rich")
467
- cli.display_results(resp, tablefmt=tablefmt, title="AP Neighbors", pager=pager, outfile=outfile, sort_by=sort_by, reverse=reverse, cleaner=cleaner.show_all_ap_lldp_neighbors_for_site)
464
+ site: CentralObject = cli.cache.get_site_identifier(site)
465
+ resp: Response = cli.central.request(cli.central.get_topo_for_site, site.id, )
466
+ tablefmt: str = cli.get_format(do_json=do_json, do_yaml=do_yaml, do_csv=do_csv, do_table=do_table, default="rich")
467
+
468
+ cleaner_kwargs = {}
469
+ if up and down:
470
+ ... # They used both flags. ignore
471
+ elif up or down:
472
+ cleaner_kwargs["filter"] = "down" if down else "up"
473
+ cli.display_results(resp, tablefmt=tablefmt, title=f"AP Neighbors for site {site.name}", pager=pager, outfile=outfile, sort_by=sort_by, reverse=reverse, cleaner=cleaner.show_all_ap_lldp_neighbors_for_sitev2, **cleaner_kwargs)
468
474
  else:
469
- if down:
470
- status = "Down"
471
- elif up:
472
- status = "Up"
475
+ if up and down:
476
+ ... # They used both flags. ignore
477
+ elif up or down:
478
+ status = "Down" if down else "Up"
479
+
473
480
  show_devices(
474
481
  aps, dev_type="aps", verbosity=verbose, outfile=outfile, update_cache=update_cache, group=group, site=site, label=label, status=status,
475
482
  state=state, pub_ip=pub_ip, do_clients=True, do_stats=True, do_ssids=True,
@@ -200,7 +200,7 @@ def group(
200
200
  cx: bool = typer.Option(None, "--cx", help="Allow ArubaOS-CX switches in group."),
201
201
  gw: bool = typer.Option(None, "--gw", help=f"Allow gateways in group.\n{' ':34}If No device types specified all are allowed."),
202
202
  mo_sw: bool = typer.Option(None, is_flag=True, help="Monitor Only for ArubaOS-SW"),
203
- mo_cx: bool = typer.Option(None, help="Monitor Only for ArubaOS-CX", hidden=True),
203
+ mo_cx: bool = typer.Option(None, help="Monitor Only for ArubaOS-CX"),
204
204
  # ap_user: str = typer.Option("admin", help="Provide user for AP group"), # TODO build func to update group pass
205
205
  # ap_passwd: str = typer.Option(None, help="Provide password for AP group (use single quotes)"),
206
206
  yes: bool = typer.Option(False, "-Y", help="Bypass confirmation prompts - Assume Yes"),
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "centralcli"
3
- version = "5.2.1"
3
+ version = "5.2.2"
4
4
  description = "A CLI for interacting with Aruba Central (Cloud Management Platform). Facilitates bulk imports, exports, reporting. A handy tool if you have devices managed by Aruba Central."
5
5
  license = "MIT"
6
6
  authors = ["Wade Wells (Pack3tL0ss) <wade@consolepi.org>"]