Skip to content

Commit

Permalink
Feat: Add check command
Browse files Browse the repository at this point in the history
  • Loading branch information
gmuloc committed Sep 27, 2023
1 parent 72bc643 commit 69a6ae4
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
22 changes: 16 additions & 6 deletions anta/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
import click

from anta import __version__
from anta.cli.check import commands as check_commands
from anta.cli.debug import commands as debug_commands
from anta.cli.exec import commands as exec_commands
from anta.cli.get import commands as get_commands
from anta.cli.nrfu import commands as check_commands
from anta.cli.nrfu import commands as nrfu_commands
from anta.cli.utils import AliasedGroup, IgnoreRequiredWithHelp, parse_catalog, parse_inventory
from anta.loader import setup_logging
from anta.result_manager import ResultManager
Expand Down Expand Up @@ -132,6 +133,7 @@ def anta(

ctx.ensure_object(dict)
ctx.obj["inventory"] = parse_inventory(ctx, inventory)
ctx.obj["inventory_path"] = ctx.params["inventory"]


@anta.group("nrfu", cls=IgnoreRequiredWithHelp)
Expand All @@ -151,6 +153,11 @@ def _nrfu(ctx: click.Context, catalog: list[tuple[Callable[..., TestResult], dic
ctx.obj["result_manager"] = ResultManager()


@anta.group("check", cls=AliasedGroup)
def _check() -> None:
"""Check commands for building ANTA"""


@anta.group("exec", cls=AliasedGroup)
def _exec() -> None:
"""Execute commands to inventory devices"""
Expand All @@ -169,11 +176,14 @@ def _debug() -> None:
# Load group commands
# Prefixing with `_` for avoiding the confusion when importing anta.cli.debug.commands as otherwise the debug group has
# a commands attribute.
_check.add_command(check_commands.catalog)
# Inventory cannot be implemented for now as main 'anta' CLI is already parsing it
# _check.add_command(check_commands.inventory)

_exec.add_command(exec_commands.clear_counters)
_exec.add_command(exec_commands.snapshot)
_exec.add_command(exec_commands.collect_tech_support)


_get.add_command(get_commands.from_cvp)
_get.add_command(get_commands.from_ansible)
_get.add_command(get_commands.inventory)
Expand All @@ -182,10 +192,10 @@ def _debug() -> None:
_debug.add_command(debug_commands.run_cmd)
_debug.add_command(debug_commands.run_template)

_nrfu.add_command(check_commands.table)
_nrfu.add_command(check_commands.json)
_nrfu.add_command(check_commands.text)
_nrfu.add_command(check_commands.tpl_report)
_nrfu.add_command(nrfu_commands.table)
_nrfu.add_command(nrfu_commands.json)
_nrfu.add_command(nrfu_commands.text)
_nrfu.add_command(nrfu_commands.tpl_report)


# ANTA CLI Execution
Expand Down
3 changes: 3 additions & 0 deletions anta/cli/check/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright (c) 2023 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
53 changes: 53 additions & 0 deletions anta/cli/check/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) 2023 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
# pylint: disable = redefined-outer-name

"""
Commands for Anta CLI to run check commands.
"""
from __future__ import annotations

import logging

import click

from anta.cli.console import console
from anta.cli.utils import parse_catalog
from anta.device import AsyncEOSDevice
from anta.models import AntaTest
from anta.result_manager import ResultManager

logger = logging.getLogger(__name__)


@click.command(no_args_is_help=True)
@click.pass_context
@click.option(
"--catalog",
"-c",
show_envvar=True,
help="Path to the tests catalog YAML file",
type=click.Path(file_okay=True, dir_okay=False, exists=True, readable=True, resolve_path=True),
required=True,
callback=parse_catalog,
)
def catalog(ctx: click.Context, catalog: list[tuple[AntaTest, AntaTest.Input]]) -> None:
"""
Check that the catalog is valid
"""
logger.info(f"Checking syntax of catalog {ctx.obj['catalog_path']}")
mock_device = AsyncEOSDevice(name="mock", host="127.0.0.1", username="mock", password="mock")
manager = ResultManager()
# Instantiate each test to verify the Inputs are correct
for test_class, test_inputs in catalog:
# TODO - this is the same code with typing as in runner.py but somehow mypy complains that test_class
# ot type AntaTest is not callable
test_instance = test_class(device=mock_device, inputs=test_inputs) # type: ignore[operator]
manager.add_test_result(test_instance.result)
if manager.error_status:
console.print(f"[bold][red]Catalog {ctx.obj['catalog_path']} is invalid")
# TODO print nice report
ctx.exit(1)
else:
console.print(f"[bold][green]Catalog {ctx.obj['catalog_path']} is valid")
4 changes: 4 additions & 0 deletions anta/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def parse_catalog(ctx: click.Context, param: Option, value: str) -> list[tuple[A
# pylint: disable=unused-argument
"""
Click option callback to parse an ANTA tests catalog YAML file
Store the orignal value (catalog path) in the ctx.obj
"""
if ctx.obj.get("_anta_help"):
# Currently looking for help for a subcommand so no
Expand All @@ -100,6 +102,8 @@ def parse_catalog(ctx: click.Context, param: Option, value: str) -> list[tuple[A
anta_log_exception(e, message, logger)
ctx.fail(message)

# Storing catalog path
ctx.obj["catalog_path"] = value
return anta.loader.parse_catalog(data)


Expand Down

0 comments on commit 69a6ae4

Please sign in to comment.