diff --git a/brian_polling_manager/interface_stats/cli.py b/brian_polling_manager/interface_stats/cli.py index 196cb94d6f6860489aabe6092d687d6bfb36a508..74d9ee89e302b458f8b97fcedbd1386aae860de8 100644 --- a/brian_polling_manager/interface_stats/cli.py +++ b/brian_polling_manager/interface_stats/cli.py @@ -2,21 +2,73 @@ import enum import json from logging import LogRecord import logging.config -import socket import sys from datetime import datetime -from typing import Iterable, List, Optional, Collection +from typing import Any, Iterable, List, Optional, Collection import click import jsonschema from brian_polling_manager.influx import influx_client from brian_polling_manager.interface_stats import vendors, config -from brian_polling_manager.interface_stats.vendors import Vendor, juniper, nokia -from brian_polling_manager.inventory import load_interfaces +from brian_polling_manager.interface_stats.vendors import Vendor +from brian_polling_manager.inventory import ( + INVENTORY_INTERFACES_SCHEMA, + load_inventory_json, +) from lxml import etree logger = logging.getLogger() +DEFAULT_INTERFACES_URL = "/poller/interfaces/" + + +class PointGroup(enum.Enum): + BRIAN = ("brian", "brian-counters", vendors.brian_points) + ERRORS = ("errors", "error-counters", vendors.error_points) + + def config_params(self, app_params: dict): + return app_params[self.value[1]] + + @property + def points(self): + return self.value[2] + + def __str__(self): + return self.value[0] + + +def write_points_to_influx( + points: Iterable[dict], + influx_params: dict, + timeout=5, + batch_size=50, +): + client = influx_client({"timeout": timeout, **influx_params}) + with client: + client.write_points(points, batch_size=batch_size) + + +def write_points_to_stdout(points, influx_params, stream=sys.stdout, **_): + for point in points: + stream.write(f"{influx_params['measurement']} - {json.dumps(point)}\n") + stream.flush() + + +class OutputMethod(enum.Enum): + INFLUX = ("influx", write_points_to_influx) + STDOUT = ("stdout", write_points_to_stdout) + NO_OUT = ("no-out", lambda *_, **__: None) + + def write_points(self, points: Iterable[dict], influx_params: dict, **kwargs): + return self.value[1](points, influx_params=influx_params, **kwargs) + + @classmethod + def from_string(cls, method: str): + return {m.value[0]: m for m in cls}[method] + + def __str__(self): + return self.value[0] + class MessageCounter(logging.NullHandler): def __init__(self, level=logging.NOTSET) -> None: @@ -27,12 +79,6 @@ class MessageCounter(logging.NullHandler): self.count += 1 -class OutputMethod(enum.Enum): - INFLUX = "influx" - STDOUT = "stdout" - NO_OUT = "no-out" - - def setup_logging(debug=False) -> MessageCounter: """ :param debug: set log level to DEBUG, or INFO otherwise @@ -66,50 +112,37 @@ def setup_logging(debug=False) -> MessageCounter: return counter -def write_points( - points: Iterable[dict], influx_params: dict, output: OutputMethod, **kwargs -): - if output == OutputMethod.INFLUX: - return write_points_to_influx(points, influx_params=influx_params, **kwargs) - if output == OutputMethod.STDOUT: - return write_points_to_stdout(points, influx_params=influx_params, **kwargs) - if output == OutputMethod.NO_OUT: - return - raise ValueError(f"Unsupported output method: {output.value()}") - - -def write_points_to_influx( - points: Iterable[dict], - influx_params: dict, - timeout=5, - batch_size=50, +def load_interfaces( + router_fqdn: str, interfaces: Any, app_config_params: dict, point_group: PointGroup ): - client = influx_client({"timeout": timeout, **influx_params}) - with client: - client.write_points(points, batch_size=batch_size) - - -def write_points_to_stdout(points, influx_params, stream=sys.stdout, **_): - for point in points: - stream.write(f"{influx_params['measurement']} - {json.dumps(point)}\n") - stream.flush() - + # if we choose to write points for all interfaces and we have provided inventory + # provider hosts, we make a selection based on the interfaces. Otherwise we write + # points for all interfaces we find on the router + if interfaces is not ALL_: + return interfaces -def get_netconf(router_name, vendor: Vendor, ssh_params: dict, **kwargs): - module = juniper if vendor == Vendor.JUNIPER else nokia - return module.get_netconf_interface_info( - router_name, ssh_params=ssh_params, **kwargs - ) + inprov_hosts = app_config_params.get("inventory") + params = point_group.config_params(app_config_params) + if inprov_hosts is not None: + return _get_interfaces_for_router( + router_fqdn, + inprov_hosts=inprov_hosts, + url=params.get("inventory-url", DEFAULT_INTERFACES_URL), + ) + return None -def get_interfaces_for_router( - router: str, - inprov_hosts: List[str], +def _get_interfaces_for_router( + router: str, inprov_hosts: List[str], url: str ) -> List[str]: - logger.info(f"Fetching interfaces from inventory provider: {inprov_hosts}") + logger.info( + f"Fetching interfaces from inventory provider: {inprov_hosts} using url '{url}'" + ) all_interfaces = [ - ifc["name"] for ifc in load_interfaces(inprov_hosts) if ifc["router"] == router + ifc["name"] + for ifc in load_inventory_json(url, inprov_hosts, INVENTORY_INTERFACES_SCHEMA) + if ifc["router"] == router ] if not all_interfaces: @@ -124,74 +157,40 @@ def process_router( interfaces: Optional[List[str]], app_config_params: dict, output: OutputMethod, + point_group: PointGroup, ): - - logger.info(f"Processing {vendor.value.capitalize()} router {router_fqdn}") - - ssh_params = app_config_params[vendor.value] - document = get_netconf(router_fqdn, vendor=vendor, ssh_params=ssh_params) + ssh_params = vendor.config_params(app_config_params) + document = vendor.get_netconf(router_name=router_fqdn, ssh_params=ssh_params) timestamp = datetime.now() - influx_params = app_config_params["influx"]["brian-counters"] - logger.info("Processing Brian points...") + influx_params = point_group.config_params(app_config_params)["influx"] points = list( - _brian_points( - router_fqdn=router_fqdn, - netconf_doc=document, - interfaces=interfaces, - timestamp=timestamp, - measurement_name=influx_params["measurement"], - vendor=vendor, - ) - ) - _log_interface_points_sorted(points) - write_points(points, influx_params=influx_params, output=output) - - influx_params = app_config_params["influx"]["error-counters"] - logger.info("Processing Error points...") - points = list( - _error_points( + _points( router_fqdn=router_fqdn, netconf_doc=document, interfaces=interfaces, timestamp=timestamp, measurement_name=influx_params["measurement"], vendor=vendor, + point_group=point_group, ) ) _log_interface_points_sorted(points, point_kind="error") - write_points(points, influx_params=influx_params, output=output) + output.write_points(points, influx_params=influx_params) -def _brian_points( +def _points( router_fqdn: str, netconf_doc: etree.Element, interfaces: Optional[List[str]], timestamp: datetime, measurement_name: str, vendor: Vendor, + point_group: PointGroup, ): - module = juniper if vendor == Vendor.JUNIPER else nokia - interfaces = module.interface_counters(netconf_doc, interfaces=interfaces) - yield from vendors.brian_points( - router_fqdn, interfaces, timestamp, measurement_name - ) - - -def _error_points( - router_fqdn: str, - netconf_doc: etree.Element, - interfaces: Optional[List[str]], - timestamp: datetime, - measurement_name: str, - vendor: Vendor, -): - module = juniper if vendor == Vendor.JUNIPER else nokia - interfaces = module.interface_counters(netconf_doc, interfaces=interfaces) - yield from vendors.error_points( - router_fqdn, interfaces, timestamp, measurement_name - ) + counters = vendor.interface_counters(netconf_doc, interfaces=interfaces) + yield from point_group.points(router_fqdn, counters, timestamp, measurement_name) def _log_interface_points_sorted(points: Collection[dict], point_kind=""): @@ -222,30 +221,30 @@ def main( output: OutputMethod = OutputMethod.INFLUX, interfaces=ALL_, ): - vendor_str = vendor.value - inprov_hosts = app_config_params.get("inventory") + vendor_str = str(vendor) + logger.info(f"Processing {vendor_str.capitalize()} router {router_fqdn}") if not app_config_params.get(vendor_str): raise ValueError(f"'{vendor_str}' ssh params are required") - # if we choose to write points for all interfaces and we have provided inventory - # provider hosts, we make a selection based on the interfaces. Otherwise we write - # points for all interfaces we find on the router - if interfaces is ALL_: - if inprov_hosts is not None: - interfaces = get_interfaces_for_router( - router_fqdn, inprov_hosts=inprov_hosts - ) - else: - interfaces = None - - process_router( - router_fqdn=router_fqdn, - vendor=vendor, - interfaces=interfaces, - app_config_params=app_config_params, - output=output, - ) + for point_group in PointGroup: + logger.info(f"Processing {str(point_group).capitalize()} points...") + + check_interfaces = load_interfaces( + router_fqdn=router_fqdn, + interfaces=interfaces, + app_config_params=app_config_params, + point_group=point_group, + ) + + process_router( + router_fqdn=router_fqdn, + vendor=vendor, + interfaces=check_interfaces, + app_config_params=app_config_params, + output=output, + point_group=point_group, + ) def validate_config(_unused_ctx, _unused_param, file): @@ -257,20 +256,6 @@ def validate_config(_unused_ctx, _unused_param, file): raise click.BadParameter(e) -def validate_hostname(_unused_ctx, _unused_param, hostname_or_names): - hostnames = ( - hostname_or_names - if isinstance(hostname_or_names, (list, tuple)) - else [hostname_or_names] - ) - for _h in hostnames: - try: - socket.gethostbyname(_h) - except socket.error: - raise click.BadParameter(f"{_h} is not resolveable") - return hostname_or_names - - @click.command() @click.option( "--config", @@ -280,14 +265,8 @@ def validate_hostname(_unused_ctx, _unused_param, hostname_or_names): help="config filename", callback=validate_config, ) -@click.option( - "--juniper", - help="A Juniper router fqdn", -) -@click.option( - "--nokia", - help="A Nokia router fqdn", -) +@click.option("--juniper", help="A Juniper router fqdn") +@click.option("--nokia", help="A Nokia router fqdn") @click.option( "-o", "--output", @@ -306,11 +285,7 @@ def validate_hostname(_unused_ctx, _unused_param, hostname_or_names): ), ) @click.option( - "-v", - "--verbose", - is_flag=True, - default=False, - help="Run with verbose output", + "-v", "--verbose", is_flag=True, default=False, help="Run with verbose output" ) @click.argument("interfaces", nargs=-1) def cli( @@ -343,12 +318,12 @@ def cli( app_config_params=app_config_params, router_fqdn=router_fqdn, vendor=vendor, - output=OutputMethod(output.lower()), + output=OutputMethod.from_string(output.lower()), interfaces=interfaces if interfaces else ALL_, ) except Exception: logger.exception( - f"Error while processing {vendor.value.capitalize()} router {router_fqdn}" + f"Error while processing {str(vendor).capitalize()} router {router_fqdn}" ) if error_counter.count: diff --git a/brian_polling_manager/interface_stats/config-example.json b/brian_polling_manager/interface_stats/config-example.json index c66cbc489e82c4e383a3257ce09489b28c320e71..b8e0c53bccabe2564782a752873ea8b3440ac8ee 100644 --- a/brian_polling_manager/interface_stats/config-example.json +++ b/brian_polling_manager/interface_stats/config-example.json @@ -6,21 +6,27 @@ "username": "bogus-user", "password": "bogus-password" }, - "inventory": ["blah"], - "influx": { - "brian-counters": { - "hostname": "hostname", - "database": "dbname", - "measurement": "brian", - "username": "some-username", - "password": "user-password" + "inventory": [ + "blah" + ], + "brian-counters": { + "influx": { + "hostname": "hostname", + "database": "dbname", + "measurement": "brian", + "username": "some-username", + "password": "user-password" }, - "error-counters": { - "hostname": "hostname", - "database": "dbname", - "measurement": "errors", - "username": "some-username", - "password": "user-password" - } + "inventory-url": "/poller/interfaces" + }, + "error-counters": { + "influx": { + "hostname": "hostname", + "database": "dbname", + "measurement": "errors", + "username": "some-username", + "password": "user-password" + }, + "inventory-url": "/poller/error-report-interfaces" } -} +} \ No newline at end of file diff --git a/brian_polling_manager/interface_stats/config.py b/brian_polling_manager/interface_stats/config.py index 0b8ead0941893a94070b53a9ada658860a4d0ff0..08b91fdd31c9622b90bc5123becd12b04116ece3 100644 --- a/brian_polling_manager/interface_stats/config.py +++ b/brian_polling_manager/interface_stats/config.py @@ -24,6 +24,17 @@ CONFIG_SCHEMA = { }, "additionalProperties": False, }, + "interface-counter-info": { + "type": "object", + "properties": { + "influx": {"$ref": "#/definitions/influx-db-measurement"}, + "inventory-url": { + "inventory-url": {"type": "string"}, + }, + }, + "required": ["influx"], + "additionalProperties": False, + }, "influx-db-measurement": { "type": "object", "properties": { @@ -56,25 +67,10 @@ CONFIG_SCHEMA = { "items": {"type": "string", "format": "uri"}, "minItems": 1, }, - "influx": { - "type": "object", - "properties": { - "brian-counters": {"$ref": "#/definitions/influx-db-measurement"}, - "error-counters": {"$ref": "#/definitions/influx-db-measurement"}, - }, - "required": ["brian-counters", "error-counters"], - "additionalProperties": False, - }, - "testing": { - "type": "object", - "properties": { - "dry_run": {"type": "boolean"}, - "no-out": {"type": "boolean"}, - "netconf-source-dir": {"type": "string"}, - }, - }, + "brian-counters": {"$ref": "#/definitions/interface-counter-info"}, + "error-counters": {"$ref": "#/definitions/interface-counter-info"}, }, - "required": ["influx"], + "required": ["brian-counters", "error-counters"], "additionalProperties": False, } @@ -91,9 +87,8 @@ def load(config_file): config = json.loads(config_file.read()) jsonschema.validate(config, CONFIG_SCHEMA) - # set some defaults - for router_vendor in "juniper", "nokia": + # set some defaults ssh_params = config.setdefault(router_vendor, {}) ssh_params.setdefault("port", DEFAULT_NETCONF_PORT) ssh_params.setdefault("hostkey_verify", DEFAULT_HOSTKEY_VERIFY) diff --git a/brian_polling_manager/interface_stats/vendors/__init__.py b/brian_polling_manager/interface_stats/vendors/__init__.py index 801e635060f1bb795eafaccc73ec55203c058c88..bbce3cecede38d36214c81c1314ecb7e3bccb10d 100644 --- a/brian_polling_manager/interface_stats/vendors/__init__.py +++ b/brian_polling_manager/interface_stats/vendors/__init__.py @@ -1,17 +1,32 @@ import enum +from lxml import etree + +from . import juniper, nokia from .common import ( - brian_points, - error_points, BRIAN_POINT_FIELDS_SCHEMA, ERROR_POINT_FIELDS_SCHEMA, INTERFACE_COUNTER_SCHEMA, + brian_points, + error_points, ) class Vendor(enum.Enum): - JUNIPER = "juniper" - NOKIA = "nokia" + JUNIPER = ("juniper", juniper) + NOKIA = ("nokia", nokia) + + def get_netconf(self, router_name: str, ssh_params: dict): + return self.value[1].get_netconf_interface_info(router_name, ssh_params) + + def interface_counters(self, document: etree.Element, interfaces=None): + return self.value[1].interface_counters(document, interfaces) + + def config_params(self, app_params: dict): + return app_params[self.value[0]] + + def __str__(self): + return self.value[0] __all__ = [ diff --git a/brian_polling_manager/inventory.py b/brian_polling_manager/inventory.py index f9838a306c84ca16448533512034886b4ddc5d53..eb7405882a7e726adb0c0303337380e13682301e 100644 --- a/brian_polling_manager/inventory.py +++ b/brian_polling_manager/inventory.py @@ -39,6 +39,7 @@ INVENTORY_INTERFACES_SCHEMA = { 'properties': { 'router': {'type': 'string'}, 'name': {'type': 'string'}, + 'vendor': {'type': 'string'}, }, 'required': ['router', 'name'], } @@ -117,7 +118,7 @@ def _pick_one(haystack): return random.choice(haystack) -def _load_inventory_json(api_route, base_urls, schema): +def load_inventory_json(api_route, base_urls, schema): """ Load & decode the specified inventory api data @@ -147,7 +148,7 @@ def load_interfaces(base_urls): :param base_urls: inventory provider base api url, or a list of them :return: a list (INVENTORY_INTERFACES_SCHEMA) """ - return _load_inventory_json( + return load_inventory_json( 'poller/interfaces', base_urls, INVENTORY_INTERFACES_SCHEMA) @@ -158,7 +159,7 @@ def load_gws_direct_interfaces(base_urls): :param base_urls: inventory provider base api url, or a list of them :return: an interable of interface-specific check data """ - return _load_inventory_json( + return load_inventory_json( 'poller/gws/direct', base_urls, GWS_DIRECT_SCHEMA) @@ -169,7 +170,7 @@ def load_gws_indirect_services(base_urls): :param base_urls: inventory provider base api url, or a list of them :return: an iterable of strings (service names) """ - return _load_inventory_json( + return load_inventory_json( 'poller/gws/indirect', base_urls, GWS_INDIRECT_SCHEMA) @@ -180,7 +181,7 @@ def load_eumetsat_multicast_subscriptions(base_urls): :param base_urls: inventory provider base api url, or a list of them :return: a list of dicts, each with a 'router' key """ - return _load_inventory_json( + return load_inventory_json( 'poller/eumetsat-multicast', base_urls, MULTICAST_SUBSCRIPTION_LIST_SCHEMA) diff --git a/test/interface_stats/conftest.py b/test/interface_stats/conftest.py index 82659a64af532784e97b9e2bc856abad94371f47..b3ccb427aafbe1cafb4bd15f268d1b9c3bdbff3c 100644 --- a/test/interface_stats/conftest.py +++ b/test/interface_stats/conftest.py @@ -2,7 +2,7 @@ import json import pathlib from unittest.mock import patch from brian_polling_manager.interface_stats import cli -from brian_polling_manager.interface_stats.vendors import Vendor, juniper, nokia +from brian_polling_manager.interface_stats.vendors import juniper, nokia import pytest @@ -32,8 +32,8 @@ def data_dir(): @pytest.fixture def mocked_get_netconf(data_dir): - def get_netconf(router_name, vendor, **_): - if vendor == Vendor.JUNIPER: + def get_netconf(vendor, router_name, **_): + if vendor == cli.Vendor.JUNIPER: return juniper.get_netconf_interface_info_from_source_dir( router_name, source_dir=data_dir ) @@ -43,7 +43,9 @@ def mocked_get_netconf(data_dir): router_name, source_dir=data_dir ) - with patch.object(cli, "get_netconf", side_effect=get_netconf) as mock: + with patch.object( + cli.Vendor, "get_netconf", autospec=True, side_effect=get_netconf + ) as mock: yield mock diff --git a/test/interface_stats/test_interface_stats.py b/test/interface_stats/test_interface_stats.py index 8567b73bae31561fa23f1e59274b2eefdfaf881b..f6195b6ea5f19391d539853c8fdad56f80c0cb90 100644 --- a/test/interface_stats/test_interface_stats.py +++ b/test/interface_stats/test_interface_stats.py @@ -5,7 +5,8 @@ from brian_polling_manager import influx import jsonschema import pytest from brian_polling_manager.interface_stats import cli -from brian_polling_manager.interface_stats.vendors import Vendor, common +from brian_polling_manager.interface_stats.cli import PointGroup, Vendor +from brian_polling_manager.interface_stats.vendors import common from lxml import etree import ncclient.manager @@ -168,16 +169,14 @@ def test_no_error_point_counters(): ] -@patch.object(cli, "write_points") +@patch.object(cli.OutputMethod, "write_points") def test_main_for_all_juniper_routers( write_points, mocked_get_netconf, juniper_router_fqdn, juniper_inventory ): config = { "juniper": {"some": "params"}, - "influx": { - "brian-counters": {"measurement": "brian"}, - "error-counters": {"measurement": "error"}, - }, + "brian-counters": {"influx": {"measurement": "brian"}}, + "error-counters": {"influx": {"measurement": "error"}}, } total_points = 0 calls = 0 @@ -206,8 +205,8 @@ def test_main_for_all_juniper_routers( @pytest.fixture -def mocked_load_interfaces(): - with patch.object(cli, "load_interfaces") as mock: +def mocked_load_inventory(): + with patch.object(cli, "load_inventory_json") as mock: mock.return_value = [ {"router": "router1", "name": "ifc1"}, {"router": "router1", "name": "ifc2"}, @@ -217,38 +216,83 @@ def mocked_load_interfaces(): @patch.object(cli, "process_router") -def test_main_with_some_interfaces(process_router, mocked_load_interfaces): - config = {"juniper": {"some": "params"}, "inventory": ["some-inprov"]} - cli.main(config, "router1", Vendor.JUNIPER, interfaces=["ifc1"]) +def test_main_with_some_interfaces(process_router, mocked_load_inventory): + config = { + "juniper": {"some": "params"}, + "inventory": ["some-inprov"], + "brian-counters": {}, + "error-counters": {}, + } + cli.main( + config, + "router1", + Vendor.JUNIPER, + interfaces=["ifc1"], + ) assert process_router.call_args[1]["interfaces"] == ["ifc1"] @patch.object(cli, "process_router") def test_main_with_all_interfaces_and_inprov_hosts( - process_router, mocked_load_interfaces + process_router, mocked_load_inventory ): - config = {"juniper": {"some": "params"}, "inventory": ["some-inprov"]} + config = { + "juniper": {"some": "params"}, + "inventory": ["some-inprov"], + "brian-counters": {}, + "error-counters": {}, + } cli.main(config, "router1", Vendor.JUNIPER) assert process_router.call_args[1]["interfaces"] == ["ifc1", "ifc2"] @patch.object(cli, "process_router") def test_main_with_all_interfaces_no_inprov_hosts( - process_router, mocked_load_interfaces + process_router, mocked_load_inventory ): - config = {"juniper": {"some": "params"}} + config = { + "juniper": {"some": "params"}, + "brian-counters": {}, + "error-counters": {}, + } cli.main(config, "router1", Vendor.JUNIPER) assert process_router.call_args[1]["interfaces"] is None +@pytest.mark.parametrize( + "point_group, url", + [ + (PointGroup.BRIAN, "/brian/endpoint"), + (PointGroup.ERRORS, "/error/endpoint"), + ], +) +def test_loads_interfaces_from_endpoint(point_group, url, mocked_load_inventory): + inprov_hosts = ["some.inprov"] + config = { + "inventory": inprov_hosts, + "brian-counters": {"inventory-url": "/brian/endpoint"}, + "error-counters": {"inventory-url": "/error/endpoint"}, + } + cli.load_interfaces( + "router1", + interfaces=cli.ALL_, + app_config_params=config, + point_group=point_group, + ) + assert mocked_load_inventory.call_args == call( + url, + inprov_hosts, + cli.INVENTORY_INTERFACES_SCHEMA, + ) + + @patch.object(cli, "influx_client") def test_write_points_to_influx(influx_client): points = [{"point": "one"}, {"point": "two"}] influx_params = {"influx": "param"} - cli.write_points( + cli.OutputMethod.INFLUX.write_points( points=points, influx_params=influx_params, - output=cli.OutputMethod.INFLUX, ) assert influx_client.call_args == call({"timeout": 5, "influx": "param"}) assert influx_client().__enter__.call_count @@ -259,7 +303,7 @@ def test_write_points_to_stdout(): stream = Mock() points = [{"point": "one"}, {"point": "two"}] influx_params = {"measurement": "meas"} - cli.write_points( + cli.OutputMethod.STDOUT.write_points( points=points, influx_params=influx_params, output=cli.OutputMethod.STDOUT, @@ -299,7 +343,7 @@ def test_setup_logging_returns_message_counter(logging): ], ) @patch.object(cli, "logging") -def test_setup_sets_loglevel(logging, verbosity, level): +def test_setup_logging_sets_loglevel(logging, verbosity, level): logging.ERROR = "ERROR" logging.INFO = "INFO" logging.DEBUG = "DEBUG" diff --git a/test/interface_stats/test_interface_stats_e2e.py b/test/interface_stats/test_interface_stats_e2e.py index f59380f7445c178d8048622fc47d7f801051a1c4..6f92c8a1eab8f499e26f156189b8207cab21b925 100644 --- a/test/interface_stats/test_interface_stats_e2e.py +++ b/test/interface_stats/test_interface_stats_e2e.py @@ -232,12 +232,14 @@ def app_config_params(influx_params): "ssh_config": f.name, "hostkey_verify": False, }, - "influx": { - "brian-counters": { + "brian-counters": { + "influx": { **influx_params, "measurement": "testenv_brian_counters", }, - "error-counters": { + }, + "error-counters": { + "influx": { **influx_params, "measurement": "testenv_error_counters", }, @@ -258,7 +260,7 @@ def test_cli_output_option(main, app_config_filename, output, all_juniper_router "--config", app_config_filename, "--output", - output.value, + str(output), "--all", "--juniper", all_juniper_routers[0], @@ -345,12 +347,12 @@ def test_e2e_juniper( assert result.exit_code == 0, str(result) verify_influx_content( - influx_config=app_config_params["influx"]["brian-counters"], + influx_config=app_config_params["brian-counters"]["influx"], schema=common.BRIAN_POINT_FIELDS_SCHEMA, ) verify_influx_content( - influx_config=app_config_params["influx"]["error-counters"], + influx_config=app_config_params["error-counters"]["influx"], schema=common.ERROR_POINT_FIELDS_SCHEMA, exclude={"output_discards"}, ) @@ -383,12 +385,12 @@ def test_e2e_nokia( assert result.exit_code == 0, str(result) verify_influx_content( - influx_config=app_config_params["influx"]["brian-counters"], + influx_config=app_config_params["brian-counters"]["influx"], schema=common.BRIAN_POINT_FIELDS_SCHEMA, ) verify_influx_content( - influx_config=app_config_params["influx"]["error-counters"], + influx_config=app_config_params["error-counters"]["influx"], schema=common.ERROR_POINT_FIELDS_SCHEMA, only={ "output_total_errors",