Files
unpoller_unpoller/examples/up.yaml.example
T
Cooper Ry LeesandClaude Opus 5 31cc5a0f31 feat: poll Protect-only consoles via disable_network (closes #1066)
A UNVR or UNVR Pro runs UniFi Protect with no Network application installed.
UnPoller could not poll one at all: NewUnifi ends with GetServerData(), a GET of
/proxy/network/status, which such a console answers with its UniFi OS SPA HTML.
The controller entry died during initialisation and re-failed every interval,
never even printing a config summary -- while the Protect Integration API on the
same host answered every endpoint with the same key.

Set disable_network = true on that controller. It defaults to false, so nothing
about an existing config changes.

The Protect collectors were already complete and already not site-scoped; three
things stood between them and a Protect-only console:

  - getUnifi now calls unifi.NewProtectClient, which skips the Network probe and
    validates the Protect Integration API instead (unpoller/unifi#240).

  - pollController aborted on getFilteredSites long before reaching
    collectProtect, and collectControllerEvents did the same before
    collectProtectLogs. The Network pass is extracted into pollNetwork and
    skipped wholesale; the event collector list reduces to collectProtectLogs,
    the only site-independent one.

  - Metrics counted a poll successful only if it produced devices or clients. A
    Protect-only console produces neither, so a filtered scrape of one -- the
    Prometheus per-target path -- fell through to the dynamic-controller branch
    and reported ErrDynamicLookupsDisabled despite a successful collection.
    ProtectDevices now counts too.

Two smaller things worth calling out for reviewers:

  - extractDevices dereferenced metrics.Devices unguarded. That was already a
    latent panic; skipping the Network pass makes it reachable, so it is fixed
    here rather than left for the first person to hit it.

  - RawMetrics answers the raw-path kind for these consoles and rejects the
    site-scoped kinds with ErrNetworkDisabled. Returning an empty result would
    read as "this console has no devices" rather than "wrong question".

warnProtectOnly logs an error, without failing the controller, for the two
configurations that can never collect anything: disable_network with neither
Protect save flag, and save_protect_devices with no key to authenticate with.
Silently collecting nothing is the failure mode hardest to spot in a log.

pkg/inputunifi had no tests before this. input_test.go follows inputunas'
input_test.go: an httptest fake UNVR serving the console's SPA HTML for
everything but the Protect paths and the login, covering initialisation,
metrics, events, the filtered scrape, RawMetrics, both warnings, config binding
across toml/json/yaml/env, and that the shipped examples leave Network enabled.
TestProtectOnlyControllerFailsWithoutFlag pins the original bug against that
same console, so the flag is demonstrably what makes the difference.

Requires github.com/unpoller/unifi/v6 with NewProtectClient (unpoller/unifi#240).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GVreutpEATmBjm6PBw9RjQ
2026-08-31 13:08:27 +00:00

119 lines
3.3 KiB
Plaintext

##############################################
# UniFi Poller primary configuration file. #
# YAML FORMAT. Provided values are defaults. #
# See up.conf.example! v2 #
##############################################
---
poller:
debug: false
quiet: false
plugins: []
# log_unknown_types: false # Set to true to log unknown device types as DEBUG messages.
# By default, newer UniFi device types that aren't recognized
# are silently ignored to reduce log volume. Enable this when
# debugging or reporting new device types to developers.
prometheus:
disable: false
http_listen: "0.0.0.0:9130"
ssl_cert_path: ""
ssl_key_path: ""
report_errors: false
interval: "60s"
influxdb:
disable: false
interval: "30s"
url: "http://127.0.0.1:8086"
user: "unifipoller"
pass: "unifipoller"
db: "unifi"
verify_ssl: false
tags:
customer: abc_corp
env: prod
webserver:
enable: false
port: 37288
html_path: "/usr/local/lib/unpoller/web"
ssl_cert_path: ""
ssl_key_path: ""
max_events: 200
accounts:
captain: "$2a$04$mxw6i0LKH6u46oaLK2cq5eCTAAFkfNiRpzNbz.EyvJZZWNa2FzIlS"
datadog:
enable: false
address: localhost:8125
namespace: ""
tags:
- customer:abcdef
unifi:
dynamic: false
defaults:
url: "https://127.0.0.1:8443"
user: "unifipoller"
pass: "unifipoller"
sites:
- all
timeout: 60s
save_ids: false
save_events: false
save_alarms: false
save_anomalies: false
save_protect_logs: false
protect_thumbnails: false
save_protect_devices: false
# protect_api_key: "unifiprotectapikey"
# Set true only on a Protect-only console (UNVR): skips the Network API entirely.
disable_network: false
save_dpi: false
save_sites: true
hash_pii: false
verify_ssl: false
# Added an example for overriding the default site name.
# default_site_name_override: "My Custom Default Site"
controllers:
# Repeat the following stanza to poll multiple controllers.
- url: "https://127.0.0.1:8443"
user: "unifipoller"
pass: "unifipoller"
sites:
- all
save_ids: false
save_events: false
save_alarms: false
save_anomalies: false
save_protect_logs: false
protect_thumbnails: false
save_protect_devices: false
# protect_api_key: "unifiprotectapikey"
# Set true only on a Protect-only console (UNVR): skips the Network API entirely.
disable_network: false
save_dpi: false
save_sites: true
hash_pii: false
verify_ssl: false
# A UNAS Pro is a standalone UniFi OS console with no Network application, so it is polled
# by its own input plugin with its own credentials and host -- not as a UniFi controller.
# This section is optional: with no devices configured the plugin stays silent and inert.
#unas:
# enable: true
# defaults:
# user: "unpoller"
# pass: ""
# verify_ssl: false
# timeout: "60s"
# devices:
# # Repeat the following stanza to poll multiple UNAS consoles.
# - url: "https://192.168.1.10"
# user: "unpoller"
# pass: "unpoller"
# verify_ssl: false
# timeout: "60s"