summaryrefslogtreecommitdiffstats
path: root/eos_downloader/cli
diff options
context:
space:
mode:
Diffstat (limited to 'eos_downloader/cli')
-rw-r--r--eos_downloader/cli/cli.py48
-rw-r--r--eos_downloader/cli/debug/commands.py41
-rw-r--r--eos_downloader/cli/get/commands.py211
-rw-r--r--eos_downloader/cli/info/commands.py86
-rw-r--r--eos_downloader/cli/utils.py38
5 files changed, 320 insertions, 104 deletions
diff --git a/eos_downloader/cli/cli.py b/eos_downloader/cli/cli.py
index ddd0dea..ad77f2b 100644
--- a/eos_downloader/cli/cli.py
+++ b/eos_downloader/cli/cli.py
@@ -11,49 +11,51 @@ ARDL CLI Baseline.
"""
import click
-from rich.console import Console
-import eos_downloader
-from eos_downloader.cli.get import commands as get_commands
+
+from eos_downloader import __version__
from eos_downloader.cli.debug import commands as debug_commands
+from eos_downloader.cli.get import commands as get_commands
from eos_downloader.cli.info import commands as info_commands
+from eos_downloader.cli.utils import AliasedGroup
+
-@click.group()
+@click.group(cls=AliasedGroup)
+@click.version_option(__version__)
@click.pass_context
-@click.option('--token', show_envvar=True, default=None, help='Arista Token from your customer account')
+@click.option(
+ "--token",
+ show_envvar=True,
+ default=None,
+ help="Arista Token from your customer account",
+)
def ardl(ctx: click.Context, token: str) -> None:
"""Arista Network Download CLI"""
ctx.ensure_object(dict)
- ctx.obj['token'] = token
+ ctx.obj["token"] = token
-@click.command()
-def version() -> None:
- """Display version of ardl"""
- console = Console()
- console.print(f'ardl is running version {eos_downloader.__version__}')
-
-
-@ardl.group(no_args_is_help=True)
+@ardl.group(cls=AliasedGroup, no_args_is_help=True)
@click.pass_context
-def get(ctx: click.Context) -> None:
+def get(ctx: click.Context, cls: click.Group = AliasedGroup) -> None:
# pylint: disable=redefined-builtin
"""Download Arista from Arista website"""
-@ardl.group(no_args_is_help=True)
+@ardl.group(cls=AliasedGroup, no_args_is_help=True)
@click.pass_context
-def info(ctx: click.Context) -> None:
+def info(ctx: click.Context, cls: click.Group = AliasedGroup) -> None:
# pylint: disable=redefined-builtin
"""List information from Arista website"""
-@ardl.group(no_args_is_help=True)
+@ardl.group(cls=AliasedGroup, no_args_is_help=True)
@click.pass_context
-def debug(ctx: click.Context) -> None:
+def debug(ctx: click.Context, cls: click.Group = AliasedGroup) -> None:
# pylint: disable=redefined-builtin
"""Debug commands to work with ardl"""
+
# ANTA CLI Execution
@@ -64,13 +66,9 @@ def cli() -> None:
get.add_command(get_commands.cvp)
info.add_command(info_commands.eos_versions)
debug.add_command(debug_commands.xml)
- ardl.add_command(version)
# Load CLI
- ardl(
- obj={},
- auto_envvar_prefix='arista'
- )
+ ardl(obj={}, auto_envvar_prefix="arista")
-if __name__ == '__main__':
+if __name__ == "__main__":
cli()
diff --git a/eos_downloader/cli/debug/commands.py b/eos_downloader/cli/debug/commands.py
index 107b8a0..5a0d7f8 100644
--- a/eos_downloader/cli/debug/commands.py
+++ b/eos_downloader/cli/debug/commands.py
@@ -22,32 +22,51 @@ import eos_downloader.eos
@click.command()
@click.pass_context
-@click.option('--output', default=str('arista.xml'), help='Path to save XML file', type=click.Path(), show_default=True)
-@click.option('--log-level', '--log', help='Logging level of the command', default=None, type=click.Choice(['debug', 'info', 'warning', 'error', 'critical'], case_sensitive=False))
+@click.option(
+ "--output",
+ default=str("arista.xml"),
+ help="Path to save XML file",
+ type=click.Path(),
+ show_default=True,
+)
+@click.option(
+ "--log-level",
+ "--log",
+ help="Logging level of the command",
+ default=None,
+ type=click.Choice(
+ ["debug", "info", "warning", "error", "critical"], case_sensitive=False
+ ),
+)
def xml(ctx: click.Context, output: str, log_level: str) -> None:
# sourcery skip: remove-unnecessary-cast
"""Extract XML directory structure"""
console = Console()
# Get from Context
- token = ctx.obj['token']
+ token = ctx.obj["token"]
logger.remove()
if log_level is not None:
logger.add("eos-downloader.log", rotation="10 MB", level=log_level.upper())
my_download = eos_downloader.eos.EOSDownloader(
- image='unset',
- software='EOS',
- version='unset',
+ image="unset",
+ software="EOS",
+ version="unset",
token=token,
- hash_method='sha512sum')
+ hash_method="sha512sum",
+ )
my_download.authenticate()
- xml_object: ET.ElementTree = my_download._get_folder_tree() # pylint: disable=protected-access
+ xml_object: ET.ElementTree = (
+ my_download.get_folder_tree()
+ ) # pylint: disable=protected-access
xml_content = xml_object.getroot()
- xmlstr = minidom.parseString(ET.tostring(xml_content)).toprettyxml(indent=" ", newl='')
- with open(output, "w", encoding='utf-8') as f:
+ xmlstr = minidom.parseString(ET.tostring(xml_content)).toprettyxml(
+ indent=" ", newl=""
+ )
+ with open(output, "w", encoding="utf-8") as f:
f.write(str(xmlstr))
- console.print(f'XML file saved in: { output }')
+ console.print(f"XML file saved in: { output }")
diff --git a/eos_downloader/cli/get/commands.py b/eos_downloader/cli/get/commands.py
index 13a8eec..b4525fe 100644
--- a/eos_downloader/cli/get/commands.py
+++ b/eos_downloader/cli/get/commands.py
@@ -21,68 +21,156 @@ from rich.console import Console
import eos_downloader.eos
from eos_downloader.models.version import BASE_VERSION_STR, RTYPE_FEATURE, RTYPES
-EOS_IMAGE_TYPE = ['64', 'INT', '2GB-INT', 'cEOS', 'cEOS64', 'vEOS', 'vEOS-lab', 'EOS-2GB', 'default']
-CVP_IMAGE_TYPE = ['ova', 'rpm', 'kvm', 'upgrade']
+EOS_IMAGE_TYPE = [
+ "64",
+ "INT",
+ "2GB-INT",
+ "cEOS",
+ "cEOS64",
+ "vEOS",
+ "vEOS-lab",
+ "EOS-2GB",
+ "default",
+]
+CVP_IMAGE_TYPE = ["ova", "rpm", "kvm", "upgrade"]
+
@click.command(no_args_is_help=True)
@click.pass_context
-@click.option('--image-type', default='default', help='EOS Image type', type=click.Choice(EOS_IMAGE_TYPE), required=True)
-@click.option('--version', default=None, help='EOS version', type=str, required=False)
-@click.option('--latest', '-l', is_flag=True, type=click.BOOL, default=False, help='Get latest version in given branch. If --branch is not use, get the latest branch with specific release type')
-@click.option('--release-type', '-rtype', type=click.Choice(RTYPES, case_sensitive=False), default=RTYPE_FEATURE, help='EOS release type to search')
-@click.option('--branch', '-b', type=click.STRING, default=None, help='EOS Branch to list releases')
-@click.option('--docker-name', default='arista/ceos', help='Docker image name (default: arista/ceos)', type=str, show_default=True)
-@click.option('--output', default=str(os.path.relpath(os.getcwd(), start=os.curdir)), help='Path to save image', type=click.Path(),show_default=True)
+@click.option(
+ "--image-type",
+ default="default",
+ help="EOS Image type",
+ type=click.Choice(EOS_IMAGE_TYPE),
+ required=True,
+)
+@click.option("--version", default=None, help="EOS version", type=str, required=False)
+@click.option(
+ "--latest",
+ "-l",
+ is_flag=True,
+ type=click.BOOL,
+ default=False,
+ help="Get latest version in given branch. If --branch is not use, get the latest branch with specific release type",
+)
+@click.option(
+ "--release-type",
+ "-rtype",
+ type=click.Choice(RTYPES, case_sensitive=False),
+ default=RTYPE_FEATURE,
+ help="EOS release type to search",
+)
+@click.option(
+ "--branch",
+ "-b",
+ type=click.STRING,
+ default=None,
+ help="EOS Branch to list releases",
+)
+@click.option(
+ "--docker-name",
+ default="arista/ceos",
+ help="Docker image name (default: arista/ceos)",
+ type=str,
+ show_default=True,
+)
+@click.option(
+ "--output",
+ default=str(os.path.relpath(os.getcwd(), start=os.curdir)),
+ help="Path to save image",
+ type=click.Path(),
+ show_default=True,
+)
# Debugging
-@click.option('--log-level', '--log', help='Logging level of the command', default=None, type=click.Choice(['debug', 'info', 'warning', 'error', 'critical'], case_sensitive=False))
+@click.option(
+ "--log-level",
+ "--log",
+ help="Logging level of the command",
+ default=None,
+ type=click.Choice(
+ ["debug", "info", "warning", "error", "critical"], case_sensitive=False
+ ),
+)
# Boolean triggers
-@click.option('--eve-ng', is_flag=True, help='Run EVE-NG vEOS provisioning (only if CLI runs on an EVE-NG server)', default=False)
-@click.option('--disable-ztp', is_flag=True, help='Disable ZTP process in vEOS image (only available with --eve-ng)', default=False)
-@click.option('--import-docker', is_flag=True, help='Import docker image (only available with --image_type cEOSlab)', default=False)
+@click.option(
+ "--eve-ng",
+ is_flag=True,
+ help="Run EVE-NG vEOS provisioning (only if CLI runs on an EVE-NG server)",
+ default=False,
+)
+@click.option(
+ "--disable-ztp",
+ is_flag=True,
+ help="Disable ZTP process in vEOS image (only available with --eve-ng)",
+ default=False,
+)
+@click.option(
+ "--import-docker",
+ is_flag=True,
+ help="Import docker image (only available with --image_type cEOSlab)",
+ default=False,
+)
def eos(
- ctx: click.Context, image_type: str, output: str, log_level: str, eve_ng: bool, disable_ztp: bool,
- import_docker: bool, docker_name: str, version: Union[str, None] = None, release_type: str = RTYPE_FEATURE,
- latest: bool = False, branch: Union[str,None] = None
- ) -> int:
+ ctx: click.Context,
+ image_type: str,
+ output: str,
+ log_level: str,
+ eve_ng: bool,
+ disable_ztp: bool,
+ import_docker: bool,
+ docker_name: str,
+ version: Union[str, None] = None,
+ release_type: str = RTYPE_FEATURE,
+ latest: bool = False,
+ branch: Union[str, None] = None,
+) -> int:
"""Download EOS image from Arista website"""
console = Console()
# Get from Context
- token = ctx.obj['token']
- if token is None or token == '':
- console.print('❗ Token is unset ! Please configure ARISTA_TOKEN or use --token option', style="bold red")
+ token = ctx.obj["token"]
+ if token is None or token == "":
+ console.print(
+ "❗ Token is unset ! Please configure ARISTA_TOKEN or use --token option",
+ style="bold red",
+ )
sys.exit(1)
logger.remove()
if log_level is not None:
logger.add("eos-downloader.log", rotation="10 MB", level=log_level.upper())
- console.print("🪐 [bold blue]eos-downloader[/bold blue] is starting...", )
- console.print(f' - Image Type: {image_type}')
- console.print(f' - Version: {version}')
-
+ console.print(
+ "🪐 [bold blue]eos-downloader[/bold blue] is starting...",
+ )
+ console.print(f" - Image Type: {image_type}")
+ console.print(f" - Version: {version}")
if version is not None:
my_download = eos_downloader.eos.EOSDownloader(
image=image_type,
- software='EOS',
+ software="EOS",
version=version,
token=token,
- hash_method='sha512sum')
+ hash_method="sha512sum",
+ )
my_download.authenticate()
elif latest:
my_download = eos_downloader.eos.EOSDownloader(
image=image_type,
- software='EOS',
- version='unset',
+ software="EOS",
+ version="unset",
token=token,
- hash_method='sha512sum')
+ hash_method="sha512sum",
+ )
my_download.authenticate()
if branch is None:
branch = str(my_download.latest_branch(rtype=release_type).branch)
latest_version = my_download.latest_eos(branch, rtype=release_type)
if str(latest_version) == BASE_VERSION_STR:
- console.print(f'[red]Error[/red], cannot find any version in {branch} for {release_type} release type')
+ console.print(
+ f"[red]Error[/red], cannot find any version in {branch} for {release_type} release type"
+ )
sys.exit(1)
my_download.version = str(latest_version)
@@ -92,46 +180,71 @@ def eos(
my_download.download_local(file_path=output, checksum=True)
if import_docker:
- my_download.docker_import(
- image_name=docker_name
- )
- console.print('✅ processing done !')
+ my_download.docker_import(image_name=docker_name)
+ console.print("✅ processing done !")
sys.exit(0)
-
@click.command(no_args_is_help=True)
@click.pass_context
-@click.option('--format', default='upgrade', help='CVP Image type', type=click.Choice(CVP_IMAGE_TYPE), required=True)
-@click.option('--version', default=None, help='CVP version', type=str, required=True)
-@click.option('--output', default=str(os.path.relpath(os.getcwd(), start=os.curdir)), help='Path to save image', type=click.Path(),show_default=True)
-@click.option('--log-level', '--log', help='Logging level of the command', default=None, type=click.Choice(['debug', 'info', 'warning', 'error', 'critical'], case_sensitive=False))
-def cvp(ctx: click.Context, version: str, format: str, output: str, log_level: str) -> int:
+@click.option(
+ "--format",
+ default="upgrade",
+ help="CVP Image type",
+ type=click.Choice(CVP_IMAGE_TYPE),
+ required=True,
+)
+@click.option("--version", default=None, help="CVP version", type=str, required=True)
+@click.option(
+ "--output",
+ default=str(os.path.relpath(os.getcwd(), start=os.curdir)),
+ help="Path to save image",
+ type=click.Path(),
+ show_default=True,
+)
+@click.option(
+ "--log-level",
+ "--log",
+ help="Logging level of the command",
+ default=None,
+ type=click.Choice(
+ ["debug", "info", "warning", "error", "critical"], case_sensitive=False
+ ),
+)
+def cvp(
+ ctx: click.Context, version: str, format: str, output: str, log_level: str
+) -> int:
"""Download CVP image from Arista website"""
console = Console()
# Get from Context
- token = ctx.obj['token']
- if token is None or token == '':
- console.print('❗ Token is unset ! Please configure ARISTA_TOKEN or use --token option', style="bold red")
+ token = ctx.obj["token"]
+ if token is None or token == "":
+ console.print(
+ "❗ Token is unset ! Please configure ARISTA_TOKEN or use --token option",
+ style="bold red",
+ )
sys.exit(1)
logger.remove()
if log_level is not None:
logger.add("eos-downloader.log", rotation="10 MB", level=log_level.upper())
- console.print("🪐 [bold blue]eos-downloader[/bold blue] is starting...", )
- console.print(f' - Image Type: {format}')
- console.print(f' - Version: {version}')
+ console.print(
+ "🪐 [bold blue]eos-downloader[/bold blue] is starting...",
+ )
+ console.print(f" - Image Type: {format}")
+ console.print(f" - Version: {version}")
my_download = eos_downloader.eos.EOSDownloader(
image=format,
- software='CloudVision',
+ software="CloudVision",
version=version,
token=token,
- hash_method='md5sum')
+ hash_method="md5sum",
+ )
my_download.authenticate()
my_download.download_local(file_path=output, checksum=False)
- console.print('✅ processing done !')
+ console.print("✅ processing done !")
sys.exit(0)
diff --git a/eos_downloader/cli/info/commands.py b/eos_downloader/cli/info/commands.py
index b51003b..64097a1 100644
--- a/eos_downloader/cli/info/commands.py
+++ b/eos_downloader/cli/info/commands.py
@@ -24,12 +24,53 @@ from eos_downloader.models.version import BASE_VERSION_STR, RTYPE_FEATURE, RTYPE
@click.command(no_args_is_help=True)
@click.pass_context
-@click.option('--latest', '-l', is_flag=True, type=click.BOOL, default=False, help='Get latest version in given branch. If --branch is not use, get the latest branch with specific release type')
-@click.option('--release-type', '-rtype', type=click.Choice(RTYPES, case_sensitive=False), default=RTYPE_FEATURE, help='EOS release type to search')
-@click.option('--branch', '-b', type=click.STRING, default=None, help='EOS Branch to list releases')
-@click.option('--verbose', '-v', is_flag=True, type=click.BOOL, default=False, help='Human readable output. Default is none to use output in script)')
-@click.option('--log-level', '--log', help='Logging level of the command', default='warning', type=click.Choice(['debug', 'info', 'warning', 'error', 'critical'], case_sensitive=False))
-def eos_versions(ctx: click.Context, log_level: str, branch: Union[str,None] = None, release_type: str = RTYPE_FEATURE, latest: bool = False, verbose: bool = False) -> None:
+@click.option(
+ "--latest",
+ "-l",
+ is_flag=True,
+ type=click.BOOL,
+ default=False,
+ help="Get latest version in given branch. If --branch is not use, get the latest branch with specific release type",
+)
+@click.option(
+ "--release-type",
+ "-rtype",
+ type=click.Choice(RTYPES, case_sensitive=False),
+ default=RTYPE_FEATURE,
+ help="EOS release type to search",
+)
+@click.option(
+ "--branch",
+ "-b",
+ type=click.STRING,
+ default=None,
+ help="EOS Branch to list releases",
+)
+@click.option(
+ "--verbose",
+ "-v",
+ is_flag=True,
+ type=click.BOOL,
+ default=False,
+ help="Human readable output. Default is none to use output in script)",
+)
+@click.option(
+ "--log-level",
+ "--log",
+ help="Logging level of the command",
+ default="warning",
+ type=click.Choice(
+ ["debug", "info", "warning", "error", "critical"], case_sensitive=False
+ ),
+)
+def eos_versions(
+ ctx: click.Context,
+ log_level: str,
+ branch: Union[str, None] = None,
+ release_type: str = RTYPE_FEATURE,
+ latest: bool = False,
+ verbose: bool = False,
+) -> None:
# pylint: disable = too-many-branches
"""
List Available EOS version on Arista.com website.
@@ -42,22 +83,23 @@ def eos_versions(ctx: click.Context, log_level: str, branch: Union[str,None] = N
"""
console = Console()
# Get from Context
- token = ctx.obj['token']
+ token = ctx.obj["token"]
logger.remove()
if log_level is not None:
logger.add("eos-downloader.log", rotation="10 MB", level=log_level.upper())
my_download = eos_downloader.eos.EOSDownloader(
- image='unset',
- software='EOS',
- version='unset',
+ image="unset",
+ software="EOS",
+ version="unset",
token=token,
- hash_method='sha512sum')
+ hash_method="sha512sum",
+ )
auth = my_download.authenticate()
if verbose and auth:
- console.print('✅ Authenticated on arista.com')
+ console.print("✅ Authenticated on arista.com")
if release_type is not None:
release_type = release_type.upper()
@@ -67,21 +109,27 @@ def eos_versions(ctx: click.Context, log_level: str, branch: Union[str,None] = N
branch = str(my_download.latest_branch(rtype=release_type).branch)
latest_version = my_download.latest_eos(branch, rtype=release_type)
if str(latest_version) == BASE_VERSION_STR:
- console.print(f'[red]Error[/red], cannot find any version in {branch} for {release_type} release type')
+ console.print(
+ f"[red]Error[/red], cannot find any version in {branch} for {release_type} release type"
+ )
sys.exit(1)
if verbose:
- console.print(f'Branch {branch} has been selected with release type {release_type}')
+ console.print(
+ f"Branch {branch} has been selected with release type {release_type}"
+ )
if branch is not None:
- console.print(f'Latest release for {branch}: {latest_version}')
+ console.print(f"Latest release for {branch}: {latest_version}")
else:
- console.print(f'Latest EOS release: {latest_version}')
+ console.print(f"Latest EOS release: {latest_version}")
else:
- console.print(f'{ latest_version }')
+ console.print(f"{ latest_version }")
else:
versions = my_download.get_eos_versions(branch=branch, rtype=release_type)
if verbose:
- console.print(f'List of available versions for {branch if branch is not None else "all branches"}')
+ console.print(
+ f'List of available versions for {branch if branch is not None else "all branches"}'
+ )
for version in versions:
- console.print(f' → {str(version)}')
+ console.print(f" → {str(version)}")
else:
pprint([str(version) for version in versions])
diff --git a/eos_downloader/cli/utils.py b/eos_downloader/cli/utils.py
new file mode 100644
index 0000000..4a14f53
--- /dev/null
+++ b/eos_downloader/cli/utils.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+# coding: utf-8 -*-
+# pylint: disable=inconsistent-return-statements
+
+
+"""
+Extension for the python ``click`` module
+to provide a group or command with aliases.
+"""
+
+
+from typing import Any
+import click
+
+
+class AliasedGroup(click.Group):
+ """
+ Implements a subclass of Group that accepts a prefix for a command.
+ If there were a command called push, it would accept pus as an alias (so long as it was unique)
+ """
+ def get_command(self, ctx: click.Context, cmd_name: str) -> Any:
+ """Documentation to build"""
+ rv = click.Group.get_command(self, ctx, cmd_name)
+ if rv is not None:
+ return rv
+ matches = [x for x in self.list_commands(ctx)
+ if x.startswith(cmd_name)]
+ if not matches:
+ return None
+ if len(matches) == 1:
+ return click.Group.get_command(self, ctx, matches[0])
+ ctx.fail(f"Too many matches: {', '.join(sorted(matches))}")
+
+ def resolve_command(self, ctx: click.Context, args: Any) -> Any:
+ """Documentation to build"""
+ # always return the full command name
+ _, cmd, args = super().resolve_command(ctx, args)
+ return cmd.name, cmd, args