New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

centralcli

Package Overview
Dependencies
Maintainers
1
Versions
322
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

centralcli - pypi Package Compare versions

Comparing version
9.0.2
to
9.0.3
+196
.gitignore
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,python
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,linux,python
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
pytestdebug.log
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
doc/_build/
docs/*.ignore
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
venv
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
### VisualStudioCode ###
.vscode/*
# !.vscode/settings.json
!.vscode/tasks.json
!.vscode/requirements-dev.txt
# !.vscode/launch.json # I change this all the time
!.vscode/extensions.json
*.code-workspace
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,python
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
# .vscode/
scratch.py
# ignore cspell vscode extension config
cspell.json
cspell.config.json
# App ignores
# ignoring directory where tokens are stored.
temp/
# ignore for now, until dynamic
# tests/__init__.py
tests/test_devices.json
tests/test_data.yaml
# ignore dashboard module until built out
centralcli/dashboard/*
*.ignore
centralcli/_*
# ignore cnx allcalls file for now WiP
cnx_allcalls.py
# ignore everything in this dir other than the example file and this file
*
!.gitignore
!*.example

Sorry, the diff of this file is not supported yet

+1
-2

@@ -6,3 +6,2 @@ # pragma: exclude file Still a WIP

import aiohttp
from google.protobuf import json_format
from rich import inspect

@@ -16,3 +15,3 @@ from rich.console import Console

from . import config, log, utils
from . import config, log
from .objects import DateTime

@@ -19,0 +18,0 @@ from .protobuf import audit_pb2, monitoring_pb2, streaming_pb2

+39
-41
Metadata-Version: 2.4
Name: centralcli
Version: 9.0.2
Version: 9.0.3
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.
Project-URL: documentation, https://central-api-cli.readthedocs.org
Project-URL: repository, https://github.com/Pack3tL0ss/central-api-cli
Project-URL: issues, https://github.com/Pack3tL0ss/central-api-cli/issues
Author-email: "Wade Wells (Pack3tL0ss)" <cencli@consolepi.com>
Maintainer-email: "Wade Wells (Pack3tL0ss)" <cencli@consolepi.com>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,Aruba,Aruba Networks,Aruba Central,HPE,HPE Networking,API,RESTFUL,REST
Author: Wade Wells (Pack3tL0ss)
Author-email: cencli@consolepi.com
Maintainer: Wade Wells (Pack3tL0ss)
Maintainer-email: cencli@consolepi.com
Requires-Python: >=3.9,<4.0
Keywords: API,Aruba,Aruba Central,Aruba Networks,HPE,HPE Networking,REST,RESTFUL,cli
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3.9
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Provides-Extra: hook-proxy
Provides-Extra: speedups
Requires-Dist: Brotli ; (platform_python_implementation == "CPython") and (extra == "speedups")
Requires-Dist: PyYAML (>=6)
Requires-Dist: aiodns (>=3.2.0) ; (platform_system != "Windows") and (extra == "speedups")
Requires-Dist: aiohttp (>=3)
Requires-Dist: asyncio (>=3)
Requires-Dist: brotlicffi ; (platform_python_implementation != "CPython") and (extra == "speedups")
Requires-Dist: click (<=7.1.2)
Requires-Dist: colorama ; platform_system == "Windows"
Requires-Dist: eval_type_backport ; python_version < "3.10"
Requires-Dist: fastapi ; extra == "hook-proxy"
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: <4.0,>=3.10
Requires-Dist: aiohttp>=3
Requires-Dist: asyncio>=3
Requires-Dist: click<=7.1.2
Requires-Dist: colorama; platform_system == 'Windows'
Requires-Dist: eval-type-backport; python_version < '3.10'
Requires-Dist: fuzzywuzzy

@@ -36,22 +31,26 @@ Requires-Dist: ipaddress

Requires-Dist: levenshtein
Requires-Dist: oauthlib (>=3.2.2)
Requires-Dist: pendulum (>=2)
Requires-Dist: oauthlib>=3.2.2
Requires-Dist: pendulum>=2
Requires-Dist: protobuf
Requires-Dist: psutil ; extra == "hook-proxy"
Requires-Dist: pycentral (>=0.0.3)
Requires-Dist: pydantic (>=2.0.0)
Requires-Dist: pylibyaml (>=0.1.0)
Requires-Dist: requests_oauthlib (>=2.0.0)
Requires-Dist: rich (>=10)
Requires-Dist: shellingham (>=1)
Requires-Dist: stringenum ; python_version < "3.11"
Requires-Dist: tablib (>=3)
Requires-Dist: tabulate (>=0.8)
Requires-Dist: tinydb (>=4)
Requires-Dist: typer (>=0.6,<0.11.0)
Requires-Dist: uniplot (>=0.13.0)
Requires-Dist: uvicorn ; extra == "hook-proxy"
Project-URL: Documentation, https://central-api-cli.readthedocs.org
Project-URL: Repository, https://github.com/Pack3tL0ss/central-api-cli
Project-URL: issues, https://github.com/Pack3tL0ss/central-api-cli/issues
Requires-Dist: pycentral>=0.0.3
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pylibyaml>=0.1.0
Requires-Dist: pyyaml>=6
Requires-Dist: requests-oauthlib>=2.0.0
Requires-Dist: rich>=10
Requires-Dist: shellingham>=1
Requires-Dist: stringenum; python_version < '3.11'
Requires-Dist: tablib>=3
Requires-Dist: tabulate>=0.8
Requires-Dist: tinydb>=4
Requires-Dist: typer<0.11.0,>=0.6
Requires-Dist: uniplot>=0.13.0
Provides-Extra: hook-proxy
Requires-Dist: fastapi; extra == 'hook-proxy'
Requires-Dist: psutil; extra == 'hook-proxy'
Requires-Dist: uvicorn; extra == 'hook-proxy'
Provides-Extra: speedups
Requires-Dist: aiodns>=3.2.0; (platform_system != 'Windows') and extra == 'speedups'
Requires-Dist: brotli; (platform_python_implementation == 'CPython') and extra == 'speedups'
Requires-Dist: brotlicffi; (platform_python_implementation != 'CPython') and extra == 'speedups'
Description-Content-Type: text/markdown

@@ -308,2 +307,1 @@

*NOTE: The Reference Guide documents a few commands that are hidden in the CLI*
[project]
name = "centralcli"
version = "9.0.2"
version = "9.0.3"
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."

@@ -9,3 +9,3 @@ license = "MIT"

readme = "README.md"
requires-python = ">=3.9,<4.0"
requires-python = ">=3.10,<4.0"

@@ -55,6 +55,7 @@ dependencies = [

"Environment :: Console",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"License :: OSI Approved :: MIT License"

@@ -81,8 +82,41 @@ ]

pytest-asyncio = ">=1.2.0"
jsonref = ">=1.1.0"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
include = [
]
exclude = [
"/.github",
"/docs",
"/.*",
"*.lock",
"/logs",
"/out",
"/tests",
"noxfile.py",
"requirements*",
]
[tool.hatch.build.targets.wheel]
packages = ["centralcli"]
[dependency-groups]
nox = [
"nox-uv>=0.6.3",
]
test = [
"pytest",
"pytest-cov",
"pytest-asyncio",
"jsonref",
]
lint = [
"ruff",
]
[tool.pytest.ini_options]

@@ -89,0 +123,0 @@ testpaths = ["tests"]

#!/usr/bin/env python3
"""
A CLI app / python package for interacting with Aruba Central Cloud Management Platform.
Features of Central CLI:
- Cross Platform Support
- Auto/TAB Completion
- Specify device, site, etc. by fuzzy match of multiple fields (i.e. name, mac, serial#, ip address)
- Multiple output formats + Output to file
- Numerous import formats (csv, yaml, json, etc.)
- Multiple workspace support (easily switch between different central workspaces --ws myotherworkspace)
- Batch Operation based on data from input file. i.e. Add sites in batch based on data from a csv.
- Automatically rename APs in mass using portions or all of:
- The switch hostname the AP is connected to, switch port, AP MAC, AP model, AP serial, and the Site it's assigned to in Aruba Central
- Automatic Token refresh. With prompt to paste in a new token if it becomes invalid.
centralcli can also be imported as a python package for use in your own scripts.
Documentation: https://central-api-cli.readthedocs.io/en/latest/readme.html
HomePage: https://github.com/Pack3tL0ss/central-api-cli
"""
# flake8: noqa
import os
import sys
from pathlib import Path
from typing import Callable, Iterable, List, Literal, Optional, Sequence, overload
import click
import typer
from rich.traceback import install
from .environment import env
from .utils import Utils
install(show_locals=True, suppress=[click])
utils = Utils() # TODO make utils.py a module, strip the class
@overload
def get_option_from_args(option: str, is_flag: Literal[True]) -> bool: ...
@overload
def get_option_from_args(option: str) -> bool: ...
@overload
def get_option_from_args(option: str, is_flag: Literal[False]) -> str: ...
@overload
def get_option_from_args(option: str, is_flag: Literal[False], convert_int: Optional[Literal[False]], pop: Optional[bool]) -> str: ...
@overload
def get_option_from_args(option: str, is_flag: Literal[False], convert_int: Literal[True], pop: Optional[bool]) -> int: ...
def get_option_from_args(option: str, is_flag: bool = True, pop: bool = True, convert_int: bool = False) -> str | int | bool:
"""Get CLI Options from sys.argv
Args:
option (str): The option to look for. i.e. '--debug'
is_flag (bool, optional): If the option is a flag, meaning there is no value expected to follow and the return of this function will be a bool. Defaults to True.
pop (bool, optional): If the option should be removed from sys.argv after the value is determined. Defaults to True.
convert_int (bool, optional): If the value retuned should be coverted to an int. Defaults to False.
Returns:
str | int | bool | None: Returns a bool if is_flag=True.
Otherwise returns the value following the option (str unless convert_int otherwise int) or None if the option is not found.
"""
assert not all([is_flag, convert_int])
if option not in sys.argv:
return False if is_flag else None
idx = sys.argv.index(option)
if pop:
_ = sys.argv.pop(sys.argv.index(option))
value_idx = idx if pop else idx + 1
if is_flag:
return True
value = sys.argv[value_idx] if not pop else sys.argv.pop(value_idx)
return value if not convert_int else int(value)
_calling_script = Path(sys.argv[0])
if str(_calling_script) == "." and os.environ.get("TERM_PROGRAM", "") == "vscode":
_calling_script = Path.cwd() / "cli.py" # vscode run in python shell
if _calling_script.name == "cencli":
base_dir = Path(typer.get_app_dir(__name__))
elif _calling_script.name.startswith("test_"):
base_dir = _calling_script.parent.parent
elif "centralcli" in Path(__file__).parts:
base_dir = Path(__file__).parent
while base_dir.name != "centralcli":
base_dir = base_dir.parent
base_dir = base_dir.parent
else:
base_dir = _calling_script.resolve().parent
if base_dir.name == "centralcli":
base_dir = base_dir.parent
else:
print("Warning Logic Error in git/pypi detection")
print(f"base_dir Parts: {base_dir.parts}")
from . import constants
from .config import Config
from .logger import MyLogger
if os.environ.get("TERM_PROGRAM") == "vscode": # pragma: no cover
from .vscodeargs import vscode_arg_handler
vscode_arg_handler()
# hidden dev option stripped from args before instantiating CLI app
# Must be b4 config is instantiated.
# Results in use of mock cache. API request/responses are still real
if get_option_from_args("--mock"):
env.is_pytest = True
config = Config(base_dir=base_dir)
log_file = config.log_dir / f"{__name__}.log"
if '--debug' in sys.argv or env.debug:
config.debug = True # for the benefit of the 2 log messages below
if '--debugv' in sys.argv:
config.debug = config.debugv = True
# debugv is stripped from args below
log = MyLogger(log_file, debug=config.debug, show=config.debug, verbose=config.debugv, deprecation_warnings=config.deprecation_warnings)
log.debug(f"{__name__} __init__ calling script: {_calling_script}, base_dir: {config.base_dir}")
# HACK Windows completion fix for upstream issue.
# completion has gotten jacked up. typer calls click.utils._expand_args in Windows which was added in click 8, but completion is broken in click 8 so cencli is pinned to 7.1.2 until I can investigate further
# This hack manually adds the _expand_args functionality to click.utils which is pinned to 7.1.2 Otherwise an exception is thrown on Windows.
if os.name == "nt": # pragma: no cover
def _expand_args(
args: Iterable[str],
*,
user: bool = True,
env: bool = True,
glob_recursive: bool = True,
) -> List[str]:
"""Simulate Unix shell expansion with Python functions.
See :func:`glob.glob`, :func:`os.path.expanduser`, and
:func:`os.path.expandvars`.
This is intended for use on Windows, where the shell does not do any
expansion. It may not exactly match what a Unix shell would do.
:param args: List of command line arguments to expand.
:param user: Expand user home directory.
:param env: Expand environment variables.
:param glob_recursive: ``**`` matches directories recursively.
:meta private:
"""
import re
from glob import glob
out = []
for arg in args:
if user:
arg = os.path.expanduser(arg)
if env:
arg = os.path.expandvars(arg)
try:
matches = glob(arg, recursive=glob_recursive)
except re.error:
matches = []
if not matches:
out.append(arg)
else:
out.extend(matches)
return out
import click
if not hasattr(click.utils, "_expand_args"):
click.utils._expand_args = _expand_args
# if no environ vars set for LESS command line options
# set -X to retain scroll-back after quitting less
# -R for color output (default for the pager but defaults are not used if LESS is set)
# +G so (start with output scrolled to end) so scroll-back contains all contents
# if not os.environ.get("LESS"):
os.environ["LESS"] = "-RX +G"
def _get_value_from_argv(flag: str, *, is_flag: bool = False, transformer: Callable = None, strip_from_argv: bool = True) -> tuple[Sequence, str | int | bool]:
if flag not in sys.argv:
return sys.argv, None if not is_flag else False
idx = sys.argv.index(flag)
if is_flag:
value = True
else:
value = sys.argv[idx + 1] # want to fail fast here so not checking len of sys.argv
value = value if not transformer else transformer(value)
if strip_from_argv:
_ = [sys.argv.pop(idx) for _ in range(idx, idx + (1 if is_flag else 2))]
return sys.argv, value
# Most of these are global hidden flags/args that are stripped before sending to cli
# We do it this way, as we then don't need to include them in each CLI command
# Most would be hidden flags anyway.
sys.argv, raw_out = _get_value_from_argv("--raw", is_flag=True)
if "--capture-raw" in sys.argv: # captures raw responses into a flat file for later use in local testing
config.dev.capture_raw = True
_ = sys.argv.pop(sys.argv.index("--capture-raw"))
if "--test" in sys.argv:
config.dev.capture_raw = True
sys.argv, env.current_test = _get_value_from_argv("--test")
if "--debug-limit" in sys.argv:
_idx = sys.argv.index("--debug-limit")
_ = sys.argv.pop(sys.argv.index("--debug-limit"))
if len(sys.argv) - 1 >= _idx and sys.argv[_idx].isdigit():
config.dev.limit = int(sys.argv[_idx])
_ = sys.argv.pop(_idx)
if "--sanitize" in sys.argv:
_ = sys.argv.pop(sys.argv.index("--sanitize"))
config.dev.sanitize = True
if "--debugv" in sys.argv:
_ = sys.argv.pop(sys.argv.index("--debugv"))
# config var updated above, just stripping flag here.
if "?" in sys.argv:
sys.argv[sys.argv.index("?")] = "--help" # Replace '?' with '--help' as '?' causes issues in cli in some scenarios
if "--account" in sys.argv: # bachward compat TODO remove anytime after 12.2025
sys.argv = [item if item != "--account" else "--ws" for item in sys.argv]
print("--account flag is deprecated. Use --ws or --workspace.", file=sys.stderr)
if "--again" in sys.argv:
valid_options = ["--json", "--yaml", "--csv", "--table", "--sort", "-r", "--pager", "-d", "--debug"]
ws_flag = "--workspace" if "--workspace" in sys.argv else "--ws"
if ws_flag in sys.argv:
ws_idx = sys.argv.index(ws_flag) + 1
if len(sys.argv) - 1 >= ws_idx:
valid_options += ["--ws", sys.argv[ws_idx]]
out_args = []
if "--out" in sys.argv:
outfile = sys.argv[sys.argv.index("--out") + 1]
out_args = ["--out", outfile]
args = [*[arg for arg in sys.argv if arg in valid_options], *out_args]
sys.argv = [sys.argv[0], "show", "last", *args]
from .cache import Cache, CacheCert, CacheClient, CacheDevice, CacheGroup, CacheGuest, CacheInvDevice, CacheLabel, CacheMpsk, CacheMpskNetwork, CachePortal, CacheSite, CacheTemplate, CacheFloorPlanAP, CacheBuilding
cache = Cache(config=config)
if config.valid:
CacheDevice.set_db(cache.DevDB)
CacheInvDevice.set_db(cache.InvDB)
CacheCert.set_db(cache.CertDB)
CacheGroup.set_db(cache.GroupDB)
CacheSite.set_db(cache.SiteDB)
CacheClient.set_db(cache.ClientDB, cache=cache)
CacheLabel.set_db(cache.LabelDB)
CachePortal.set_db(cache.PortalDB)
CacheGuest.set_db(cache.GuestDB, cache=cache)
CacheTemplate.set_db(cache.TemplateDB)
CacheMpskNetwork.set_db(cache.MpskNetDB)
CacheMpsk.set_db(cache.MpskDB)
CacheBuilding.set_db(cache.BuildingDB)
CacheFloorPlanAP.set_db(cache.FloorPlanAPDB, building_db=cache.BuildingDB)
from .clicommon import CLICommon
common = CLICommon(config.workspace, cache, raw_out=raw_out)
from . import cleaner, render
# allow singular form and common synonyms for the defined show commands
# show switches / show switch, delete label / labels ...
if len(sys.argv) > 2:
sys.argv[2] = constants.arg_to_what(sys.argv[2], cmd=sys.argv[1])

Sorry, the diff of this file is too big to display