Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 33 additions & 41 deletions annet/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
from contextlog import get_logger
from valkit.python import valid_logging_level

from annet import api, cli_args, filtering, generators
from annet import api, cli_args, filtering, generators, patching
from annet.api import Deployer, collapse_texts
from annet.argparse import ArgParser, subcommand
from annet.deploy import get_deployer, get_fetcher
from annet.diff import gen_sort_diff
from annet.gen import Loader, old_raw
from annet.gen import Loader, format_config_blocks, old_new
from annet.lib import get_context_path, repair_context_file
from annet.output import OutputDriver, output_driver_connector
from annet.storage import Device, get_storage
Expand All @@ -41,32 +41,6 @@ def list_subcommands():
return globals().copy()


def _gen_current_items(
config,
stdin,
loader: Loader,
output_driver: OutputDriver,
gen_args: cli_args.GenOptions,
) -> Iterable[Tuple[str, str, bool]]:
for device, result in old_raw(
args=gen_args,
loader=loader,
config=config,
stdin=stdin,
do_files_download=True,
use_mesh=False,
):
if device.hw.vendor != "pc":
destname = output_driver.cfg_file_names(device)[0]
yield (destname, result, False)
else:
for entire_path, entire_data in sorted(result.items(), key=operator.itemgetter(0)):
if entire_data is None:
entire_data = ""
destname = output_driver.entire_config_dest_path(device, entire_path)
yield (destname, entire_data, False)


@contextmanager
def get_loader(gen_args: cli_args.GenOptions, args: cli_args.QueryOptionsBase):
exit_stack = ExitStack()
Expand All @@ -84,23 +58,41 @@ def show():
pass


@subcommand(cli_args.QueryOptions, cli_args.opt_config, cli_args.FileOutOptions, parent=show)
def show_current(args: cli_args.QueryOptions, config, arg_out: cli_args.FileOutOptions) -> None:
"""Show current devices' configuration"""
gen_args = cli_args.GenOptions(args, no_acl=True)
@subcommand(cli_args.ShowCurrentOptions, parent=show)
def show_current(args: cli_args.ShowCurrentOptions) -> None:
"""Show current devices' configuration, optionally filtered by generator ACL (-g) and interfaces (-i)"""
args.no_acl = not (args.acl or args.allowed_gens or args.filter_ifaces)
filterer = filtering.filterer_connector.get()
output_driver = output_driver_connector.get()
with get_loader(gen_args, args) as loader:
with get_loader(args, args) as loader:
if not loader.devices:
get_logger().error("No devices found for %s", args.query)

items = _gen_current_items(
loader=loader,
output_driver=output_driver,
gen_args=gen_args,
stdin=args.stdin(config=config),
config=config,
)
output_driver.write_output(arg_out, items, len(loader.devices))
def items() -> Iterable[Tuple[str, str, bool]]:
for res in old_new(
args,
config=args.config,
loader=loader,
filterer=filterer,
no_new=True,
add_implicit=False,
do_files_download=True,
):
if res.err:
raise res.err
device = res.device
if not device.is_pc():
if res.old:
orderer = patching.Orderer.from_hw(device.hw)
old_text = format_config_blocks(orderer.order_config(res.old), device.hw, args.indent)
yield output_driver.cfg_file_names(device)[0], old_text, False
else:
for entire_path, entire_data in sorted(res.old_files.items()):
if entire_data is None:
entire_data = ""
yield output_driver.entire_config_dest_path(device, entire_path), entire_data, False

output_driver.write_output(args, items(), len(loader.devices))


@subcommand(cli_args.QueryOptions, cli_args.FileOutOptions, parent=show)
Expand Down
7 changes: 7 additions & 0 deletions annet/cli_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ def opt_query_factory(**kwargs):

opt_no_acl = Arg("--no-acl", default=False, help="Disable ACL for config generation")

opt_acl = Arg("--acl", default=False, help="Apply generator ACL to filter output (implied by -g and -i)")

opt_no_acl_exclusive = Arg(
"--no-acl-exclusive", default=False, help="Check that ACLs of the executed generators do not intersect"
)
Expand Down Expand Up @@ -417,6 +419,11 @@ class ShowGenOptions(GenOptions, FileOutOptions):
show_hosts_progress = opt_show_hosts_progress


class ShowCurrentOptions(ShowGenOptions):
config = opt_config
acl = opt_acl


class ShowDiffOptions(DiffOptions, FileOutOptions):
indent = opt_indent
show_rules = opt_show_rules
Expand Down
50 changes: 2 additions & 48 deletions annet/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@
from contextlog import get_logger

from annet import generators, implicit, patching, rulebook, tracing
from annet.annlib import jsontools
from annet.annlib.rbparser.acl import compile_acl_text
from annet.cli_args import DeployOptions, GenOptions, ShowGenOptions
from annet.deploy import get_fetcher, scrub_config
from annet.cli_args import GenOptions, ShowGenOptions
from annet.deploy import get_fetcher
from annet.filtering import Filterer
from annet.generators import (
BaseGenerator,
Expand Down Expand Up @@ -425,51 +424,6 @@ def old_new(
yield result


@tracing.function
def old_raw(
args: GenOptions,
loader: Loader,
config,
stdin=None,
do_files_download=False,
use_mesh=True,
) -> Iterable[Tuple[Device, Union[str, Dict[str, str]]]]:
device_gens = loader.resolve_gens(loader.devices)
running, failed_running = _old_resolve_running(config, loader.devices)
downloaded_files, failed_files = _old_resolve_files(config, loader.devices, device_gens, do_files_download)
if stdin is None:
stdin = args.stdin(filter_acl=args.filter_acl, config=config)
ctx = OldNewDeviceContext(
config=config,
args=args,
downloaded_files=split_downloaded_files_multi_device(downloaded_files, device_gens, loader.devices),
failed_files=failed_files,
running=running,
failed_running=failed_running,
stdin=stdin,
do_files_download=do_files_download,
device_count=len(loader.devices),
no_new=True,
add_annotations=False,
add_implicit=False,
gens=DeviceGenerators(),
fetched_packages={},
failed_packages={},
do_print_perf=True,
)
for device in loader.devices:
if not device.is_pc():
config = _old_new_get_config_cli(ctx, device)
config = scrub_config(config, device.breed)
yield device, config
else:
files = _old_new_get_config_files(ctx, device)
if files.entire_files:
yield device, files.entire_files
if files.json_fragment_files:
yield device, {path: jsontools.format_json(data) for path, data in files.json_fragment_files.items()}


@tracing.function
def worker(
device_id, args: ShowGenOptions, stdin, loader: "Loader", filterer: Filterer
Expand Down
Loading