From d56f8dba6daedbd261266edbe6dfebb8550dcccc Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Wed, 6 Sep 2023 09:09:41 +0200 Subject: [PATCH] Allow empty string interface to not call the OPNsense traffic diagnostic REST API endpoint --- README.md | 10 ++++++++-- opnsense_exporter/opnsense_api.py | 4 +++- opnsense_exporter/server.py | 4 +++- tests/test_opnsense_api.py | 13 +++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 02ac288..f0b1385 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,11 @@ optional arguments: OPNsense user. Expect to be the same on MAIN and BACKUP servers --opnsense-interfaces INTERFACES, -i INTERFACES - OPNsense interfaces (coma separated) list to export - trafic rates (bytes/s) (default: wan,lan) + OPNsense interfaces (coma separated) list to + export trafic rates (bytes/s). An empty string '' + means not calling the traffic diagnostic REST API + so no `opnsense_active_server_traffic_rate` + metric. (default: wan,lan) --opnsense-password PASSWORD, -p PASSWORD OPNsense password. Expect to be the same on MAIN and BACKUP servers @@ -109,6 +112,9 @@ You can setup env through `.env` file or environment variables with defined as d - remove `opnsense_main_ha_state` and `opnsense_backup_ha_state` metrics marked as deprecated on version 0.5.0 and replace by `opnsense_server_ha_state` and `role` label +- allow empty string interfaces to **not** call diagnostic + traffic REST API + ### Version 0.5.1 (2023-09-04) diff --git a/opnsense_exporter/opnsense_api.py b/opnsense_exporter/opnsense_api.py index 85d8644..5cdfc1a 100644 --- a/opnsense_exporter/opnsense_api.py +++ b/opnsense_exporter/opnsense_api.py @@ -106,6 +106,8 @@ class OPNSenseAPI: return OPNSenseHAState.UNAVAILABLE def get_traffic(self, interfaces): + if not interfaces: + return [] try: data = self.get(f"/api/diagnostics/traffic/top/{interfaces}", timeout=15) except RequestException as ex: @@ -120,7 +122,7 @@ class OPNSenseAPI: for interface in interfaces.split(","): traffic_in = OPNSenseTraffic(interface, OPNSenseTrafficMetric.IN) traffic_out = OPNSenseTraffic(interface, OPNSenseTrafficMetric.OUT) - for record in data.get(interface, []).get("records", []): + for record in data.get(interface, {}).get("records", []): traffic_in.value += record.get(OPNSenseTrafficMetric.IN.value, 0) traffic_out.value += record.get(OPNSenseTrafficMetric.OUT.value, 0) traffics.extend([traffic_in, traffic_out]) diff --git a/opnsense_exporter/server.py b/opnsense_exporter/server.py index fd9c7a9..14f6853 100644 --- a/opnsense_exporter/server.py +++ b/opnsense_exporter/server.py @@ -131,7 +131,9 @@ def run(): type=str, dest="interfaces", default=os.environ.get("OPNSENSE_INTERFACES", "wan,lan"), - help="OPNsense interfaces (coma separated) list to export trafic rates (bytes/s)", + help="OPNsense interfaces (coma separated) list to export trafic rates (bytes/s). " + "An empty string '' means not calling the traffic diagnostic REST API so no " + "`opnsense_active_server_traffic_rate` metric.", ) parser.add_argument( "--opnsense-password", diff --git a/tests/test_opnsense_api.py b/tests/test_opnsense_api.py index 6ef2f45..73fbc1a 100644 --- a/tests/test_opnsense_api.py +++ b/tests/test_opnsense_api.py @@ -129,6 +129,19 @@ def test_get_traffic_none(): ) +@responses.activate +def test_get_traffic_empty_string(): + rsp = responses.add( + responses.GET, + f"https://{MAIN_HOST}/api/diagnostics/traffic/top/", + json={"not": "called"}, + ) + assert ( + OPNSenseAPI(OPNSenseRole.MAIN, MAIN_HOST, LOGIN, PASSWORD).get_traffic("") == [] + ) + assert rsp.call_count == 0 + + def test_labels(): assert OPNSenseAPI(OPNSenseRole.MAIN, MAIN_HOST, LOGIN, PASSWORD).labels == { "role": "main",