centralcli 7.2.0__tar.gz → 7.2.3__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.
- {centralcli-7.2.0 → centralcli-7.2.3}/PKG-INFO +1 -1
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/__init__.py +10 -9
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cache.py +21 -12
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliupdate.py +19 -19
- {centralcli-7.2.0 → centralcli-7.2.3}/pyproject.toml +1 -1
- {centralcli-7.2.0 → centralcli-7.2.3}/LICENSE +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/README.md +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/boilerplate/README.md +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/boilerplate/_cnx_allcalls.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/boilerplate/allcalls.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/caas.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/central.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cleaner.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cli.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliadd.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliassign.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clibatch.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clicaas.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clicheck.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliclone.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clicommon.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clidel.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clidelfirmware.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliexport.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clikick.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clioptions.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clirefresh.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clirename.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliset.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clisetfirmware.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishow.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowaudit.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowbandwidth.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowbranch.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowcloudauth.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowfirmware.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowmpsk.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowospf.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowoverlay.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowtshoot.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clishowwids.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clitest.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/clitshoot.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliunassign.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/cliupgrade.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/config.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/constants.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/exceptions.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/logger.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/models.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/objects.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/render.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/response.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/setup.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/static/favicon.ico +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/strings.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/typedefs.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/utils.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/vendored/csvlexer/__init__.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/vendored/csvlexer/csv.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/vscodeargs.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/wh2snow.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/wh_proxy.py +0 -0
- {centralcli-7.2.0 → centralcli-7.2.3}/centralcli/wh_proxy_service.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: centralcli
|
|
3
|
-
Version: 7.2.
|
|
3
|
+
Version: 7.2.3
|
|
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
|
|
@@ -194,15 +194,16 @@ if "--capture-raw" in sys.argv: # captures raw responses into a flat file for l
|
|
|
194
194
|
central = CentralApi(config.account)
|
|
195
195
|
Cache.set_config(config)
|
|
196
196
|
cache = Cache(central)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
197
|
+
if config.valid:
|
|
198
|
+
CacheDevice.set_db(cache.DevDB)
|
|
199
|
+
CacheInvDevice.set_db(cache.InvDB)
|
|
200
|
+
CacheGroup.set_db(cache.GroupDB)
|
|
201
|
+
CacheSite.set_db(cache.SiteDB)
|
|
202
|
+
CacheClient.set_db(cache.ClientDB, cache=cache)
|
|
203
|
+
CacheLabel.set_db(cache.LabelDB)
|
|
204
|
+
CachePortal.set_db(cache.PortalDB)
|
|
205
|
+
CacheTemplate.set_db(cache.TemplateDB)
|
|
206
|
+
CacheMpskNetwork.set_db(cache.MpskDB)
|
|
206
207
|
cli = CLICommon(config.account, cache, central, raw_out=raw_out)
|
|
207
208
|
|
|
208
209
|
# allow singular form and common synonyms for the defined show commands
|
|
@@ -464,6 +464,10 @@ class CachePortal(CentralObject):
|
|
|
464
464
|
def __rich__(self) -> str:
|
|
465
465
|
return f'[bright_green]Portal Profile[/]:[bright_green]{self.name}[/]|[cyan]{self.id}[/]'
|
|
466
466
|
|
|
467
|
+
@property
|
|
468
|
+
def help_text(self):
|
|
469
|
+
return render.rich_capture(self.__rich__())
|
|
470
|
+
|
|
467
471
|
|
|
468
472
|
class CacheTemplate(CentralObject):
|
|
469
473
|
db: Table | None = None
|
|
@@ -560,6 +564,12 @@ class CacheClient(CentralObject):
|
|
|
560
564
|
def __rich__(self) -> str:
|
|
561
565
|
return f'[bright_green]Client[/]:[cyan]{self.name}[/]|({utils.color([self.type, self.ip, self.mac, self.connected_name], "green_yellow", sep="|")}|s[green_yellow]{self.site})[/]'
|
|
562
566
|
|
|
567
|
+
@property
|
|
568
|
+
def help_text(self) -> str:
|
|
569
|
+
return render.rich_capture(
|
|
570
|
+
f"[bright_green]{self.name}[/]|[cyan]{self.mac}[/]|[bright_green]{self.ip}[/]|[cyan]{f's:{self.site}' if self.site else f'g:{self.group}'}[/]|[dark_olive_green2]{self.connected_name}[/]"
|
|
571
|
+
)
|
|
572
|
+
|
|
563
573
|
|
|
564
574
|
class CacheMpskNetwork(CentralObject):
|
|
565
575
|
db: Table | None = None
|
|
@@ -1349,9 +1359,9 @@ class Cache:
|
|
|
1349
1359
|
match = [m for m in match if m.name not in args]
|
|
1350
1360
|
for m in sorted(match, key=lambda i: i.name):
|
|
1351
1361
|
if m.name.startswith(incomplete):
|
|
1352
|
-
out += [tuple([m.name, m.
|
|
1362
|
+
out += [tuple([m.name, m.help_text])]
|
|
1353
1363
|
elif m.id.startswith(incomplete):
|
|
1354
|
-
out += [tuple([m.id, m.
|
|
1364
|
+
out += [tuple([m.id, m.help_text])]
|
|
1355
1365
|
else:
|
|
1356
1366
|
out += [tuple([m.name, m.help_text])] # failsafe, shouldn't hit
|
|
1357
1367
|
|
|
@@ -1959,19 +1969,18 @@ class Cache:
|
|
|
1959
1969
|
# remove clients that are already on the command line
|
|
1960
1970
|
match = [m for m in match if m.name not in args]
|
|
1961
1971
|
for c in sorted(match, key=lambda i: i.name):
|
|
1962
|
-
if c.name.startswith(incomplete):
|
|
1963
|
-
out += c.help_text
|
|
1972
|
+
if c.name.lower().startswith(incomplete.lower()):
|
|
1973
|
+
out += [(c.name, c.help_text)]
|
|
1964
1974
|
elif c.mac.strip(":.-").lower().startswith(incomplete.strip(":.-")):
|
|
1965
|
-
out += c.help_text
|
|
1975
|
+
out += [(c.mac, c.help_text)]
|
|
1966
1976
|
elif c.ip.startswith(incomplete):
|
|
1967
|
-
out += c.help_text
|
|
1977
|
+
out += [(c.ip, c.help_text)]
|
|
1968
1978
|
else:
|
|
1969
1979
|
# failsafe, shouldn't hit
|
|
1970
|
-
out += (c.
|
|
1980
|
+
out += [(c.name, f'{c.help_text} FailSafe Match')]
|
|
1971
1981
|
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
yield c[0].replace(":", "-"), c[1]
|
|
1982
|
+
for c in out:
|
|
1983
|
+
yield c[0].replace(":", "-"), c[1] # TODO completion behavior has changed. This works-around issue bash doesn't complete past 00: and zsh treats each octet as a dev name when : is used.
|
|
1975
1984
|
|
|
1976
1985
|
def event_log_completion(
|
|
1977
1986
|
self,
|
|
@@ -2324,14 +2333,14 @@ class Cache:
|
|
|
2324
2333
|
bool: _description_
|
|
2325
2334
|
"""
|
|
2326
2335
|
_start_time = time.perf_counter()
|
|
2327
|
-
if data:
|
|
2336
|
+
if data is not None:
|
|
2328
2337
|
with econsole.status(f":arrows_clockwise: Updating [dark_olive_green2]{db.name}[/] Cache: [cyan]{len(data)}[/] records."):
|
|
2329
2338
|
if truncate:
|
|
2330
2339
|
db.truncate()
|
|
2331
2340
|
db_res = db.insert_multiple([dict(d) for d in data]) # Converts any TinyDB.Documents to dict as that has unexpected results.
|
|
2332
2341
|
return self.verify_db_action(db, expected=len(data), response=db_res, elapsed=round(time.perf_counter() - _start_time, 2))
|
|
2333
2342
|
|
|
2334
|
-
doc_ids = utils.listify(doc_ids)
|
|
2343
|
+
doc_ids = utils.listify(doc_ids) or []
|
|
2335
2344
|
with econsole.status(f":wastebasket: [red]Removing[/]] [cyan]{len(doc_ids)}[/] records from [dark_olive_green2]{db.name}[/] cache."):
|
|
2336
2345
|
db_res = db.remove(doc_ids=doc_ids)
|
|
2337
2346
|
return self.verify_db_action(db, expected=len(doc_ids), response=db_res, remove=True, elapsed=round(time.perf_counter() - _start_time, 2))
|
|
@@ -3,29 +3,34 @@
|
|
|
3
3
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import sys
|
|
6
|
-
from typing import List, Union
|
|
6
|
+
from typing import TYPE_CHECKING, List, Union
|
|
7
7
|
# from typing import List
|
|
8
8
|
import typer
|
|
9
9
|
from rich import print
|
|
10
10
|
from rich.console import Console
|
|
11
|
+
from rich.text import Text
|
|
11
12
|
from jinja2 import FileSystemLoader, Environment
|
|
12
13
|
import yaml
|
|
13
14
|
|
|
14
15
|
# Detect if called from pypi installed package or via cloned github repo (development)
|
|
15
16
|
try:
|
|
16
|
-
from centralcli import utils, cli,
|
|
17
|
+
from centralcli import utils, cli, cleaner, BatchRequest, log
|
|
17
18
|
except (ImportError, ModuleNotFoundError) as e:
|
|
18
19
|
pkg_dir = Path(__file__).absolute().parent
|
|
19
20
|
if pkg_dir.name == "centralcli":
|
|
20
21
|
sys.path.insert(0, str(pkg_dir.parent))
|
|
21
|
-
from centralcli import utils, cli,
|
|
22
|
+
from centralcli import utils, cli, cleaner, BatchRequest, log
|
|
22
23
|
else:
|
|
23
24
|
print(pkg_dir.parts)
|
|
24
25
|
raise e
|
|
25
26
|
|
|
26
|
-
from
|
|
27
|
-
from
|
|
27
|
+
from .constants import IdenMetaVars, DevTypes, GatewayRole, state_abbrev_to_pretty
|
|
28
|
+
from . import render
|
|
28
29
|
from .cache import CacheTemplate
|
|
30
|
+
from .caas import CaasAPI
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from .cache import CacheDevice, CacheGroup
|
|
29
34
|
|
|
30
35
|
|
|
31
36
|
SPIN_TXT_AUTH = "Establishing Session with Aruba Central API Gateway..."
|
|
@@ -277,7 +282,6 @@ def generate_template(template_file: Union[Path, str], var_file: Union[Path, str
|
|
|
277
282
|
@app.command("config")
|
|
278
283
|
def config_(
|
|
279
284
|
group_dev: str = cli.arguments.group_dev,
|
|
280
|
-
# TODO collect multi-line input as option to paste in config
|
|
281
285
|
cli_file: Path = typer.Argument(..., help="File containing desired config/template in CLI format.", exists=True, autocompletion=lambda incomplete: tuple(), show_default=False,),
|
|
282
286
|
var_file: Path = typer.Argument(None, help="File containing variables for j2 config template.", exists=True, autocompletion=lambda incomplete: tuple(), show_default=False,),
|
|
283
287
|
do_gw: bool = typer.Option(None, "--gw", help="Update group level config for gateways."),
|
|
@@ -289,18 +293,12 @@ def config_(
|
|
|
289
293
|
) -> None:
|
|
290
294
|
"""Update group or device level config (ap or gw).
|
|
291
295
|
"""
|
|
292
|
-
group_dev:
|
|
296
|
+
group_dev: CacheDevice | CacheGroup = cli.cache.get_identifier(group_dev, qry_funcs=["group", "dev"], device_type=["ap", "gw"])
|
|
293
297
|
config_out = utils.generate_template(cli_file, var_file=var_file)
|
|
294
298
|
cli_cmds = utils.validate_config(config_out)
|
|
295
299
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
console.begin_capture()
|
|
299
|
-
console.rule("Configuration to be sent")
|
|
300
|
-
console.print("\n".join([f"[green]{line}[/green]" for line in cli_cmds]))
|
|
301
|
-
console.rule()
|
|
302
|
-
console.print(f"\nUpdating {'group' if group_dev.is_group else group_dev.generic_type.upper()} [cyan]{group_dev.name}[/]")
|
|
303
|
-
_msg = console.end_capture()
|
|
300
|
+
output = render.output(cli_cmds)
|
|
301
|
+
output = Text.from_ansi(output.tty)
|
|
304
302
|
|
|
305
303
|
if group_dev.is_group:
|
|
306
304
|
device = None
|
|
@@ -313,7 +311,7 @@ def config_(
|
|
|
313
311
|
if device and device.generic_type != "gw":
|
|
314
312
|
cli.exit(f"Invalid input: --gw option conflicts with {device.name} which is an {device.generic_type}")
|
|
315
313
|
use_caas = True
|
|
316
|
-
caasapi =
|
|
314
|
+
caasapi = CaasAPI(central=cli.central)
|
|
317
315
|
node_iden = group_dev.name if group_dev.is_group else group_dev.mac
|
|
318
316
|
elif do_ap or (device and device.generic_type == "ap"):
|
|
319
317
|
if device and device.generic_type != "ap":
|
|
@@ -321,7 +319,10 @@ def config_(
|
|
|
321
319
|
use_caas = False
|
|
322
320
|
node_iden = group_dev.name if group_dev.is_group else group_dev.serial
|
|
323
321
|
|
|
324
|
-
|
|
322
|
+
cli.console.rule("Configuration to be sent")
|
|
323
|
+
cli.console.print(output, emoji=False)
|
|
324
|
+
cli.console.rule()
|
|
325
|
+
cli.console.print(f"\nUpdating {'group' if group_dev.is_group else group_dev.generic_type.upper()} [cyan]{group_dev.name}[/]")
|
|
325
326
|
if cli.confirm(yes):
|
|
326
327
|
if use_caas:
|
|
327
328
|
resp = cli.central.request(caasapi.send_commands, node_iden, cli_cmds)
|
|
@@ -329,8 +330,7 @@ def config_(
|
|
|
329
330
|
else:
|
|
330
331
|
# FIXME this is OK for group level ap config , for AP this method is not valid
|
|
331
332
|
if group_dev.is_dev:
|
|
332
|
-
|
|
333
|
-
raise typer.Exit(1)
|
|
333
|
+
cli.exit("Not Implemented yet for AP device level updates")
|
|
334
334
|
resp = cli.central.request(cli.central.replace_ap_config, node_iden, cli_cmds)
|
|
335
335
|
cli.display_results(resp, tablefmt="action")
|
|
336
336
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "centralcli"
|
|
3
|
-
version = "7.2.
|
|
3
|
+
version = "7.2.3"
|
|
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>"]
|
|
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
|
|
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
|