mirror of
https://github.com/unpoller/unpoller.git
synced 2026-09-29 19:11:17 +02:00
fix: poll remote multi-site controllers by internalReference
Remote discovery stored Integration display names, so extra sites were dropped when checkSites compared them to legacy Site.Name. Use unifi v6.1.0 InternalReference instead. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,7 +13,7 @@ require (
|
||||
github.com/prometheus/common v0.70.1
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/stretchr/testify v1.12.1
|
||||
github.com/unpoller/unifi/v6 v6.0.3
|
||||
github.com/unpoller/unifi/v6 v6.1.0
|
||||
go.opentelemetry.io/otel v1.46.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.46.0
|
||||
|
||||
@@ -121,8 +121,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
||||
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
||||
github.com/unpoller/unifi/v6 v6.0.3 h1:NoxbSA5HLMErs/1yVkmuwm+lcyy9SxSfOLDW58PKqrQ=
|
||||
github.com/unpoller/unifi/v6 v6.0.3/go.mod h1:d7dz1cBxVbbFZobNRcdUHHYtTdicVyZ05J5OmgoINa8=
|
||||
github.com/unpoller/unifi/v6 v6.1.0 h1:VDUZSCkK5BS3qF39MgTsJa1plwqZ4sIqBa+JYVamLnE=
|
||||
github.com/unpoller/unifi/v6 v6.1.0/go.mod h1:d7dz1cBxVbbFZobNRcdUHHYtTdicVyZ05J5OmgoINa8=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
|
||||
@@ -175,13 +175,9 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
controller.SaveProtectDevices = &f
|
||||
}
|
||||
|
||||
// Extract site names
|
||||
siteNames := make([]string, 0, len(sites))
|
||||
for _, site := range sites {
|
||||
if site.Name != "" {
|
||||
siteNames = append(siteNames, site.Name)
|
||||
}
|
||||
}
|
||||
// checkSites / getFilteredSites match against legacy Site.Name, which is
|
||||
// RemoteSite.InternalReference, not the display Name. See unpoller/unpoller#986.
|
||||
siteNames := remoteSitePollNames(sites)
|
||||
|
||||
// For Cloud Gateways, if the only site is "default", use the console name from hosts response
|
||||
// as the default site name override. The console name is in reportedState.name
|
||||
@@ -208,8 +204,54 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
controller.ID = console.ID
|
||||
controllers = append(controllers, controller)
|
||||
|
||||
u.Logf("Discovered console %s with %d site(s): %v", consoleName, len(sites), siteNames)
|
||||
u.Logf("Discovered console %s with %d site(s): %v", consoleName, len(sites), formatRemoteSites(sites))
|
||||
}
|
||||
|
||||
return controllers, nil
|
||||
}
|
||||
|
||||
// remoteSitePollNames returns the legacy site identifiers used by checkSites
|
||||
// and getFilteredSites. Prefer InternalReference (OpenAPI Site overview);
|
||||
// fall back to Name when the field is missing (older firmware).
|
||||
func remoteSitePollNames(sites []unifi.RemoteSite) []string {
|
||||
names := make([]string, 0, len(sites))
|
||||
|
||||
for _, site := range sites {
|
||||
name := site.InternalReference
|
||||
if name == "" {
|
||||
name = site.Name
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
// formatRemoteSites logs display name plus legacy id when they differ.
|
||||
func formatRemoteSites(sites []unifi.RemoteSite) []string {
|
||||
out := make([]string, 0, len(sites))
|
||||
|
||||
for _, site := range sites {
|
||||
id := site.InternalReference
|
||||
if id == "" {
|
||||
id = site.Name
|
||||
}
|
||||
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if site.Name != "" && !strings.EqualFold(site.Name, id) {
|
||||
out = append(out, site.Name+" ("+id+")")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
out = append(out, id)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package inputunifi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/unpoller/unifi/v6"
|
||||
)
|
||||
|
||||
func TestRemoteSitePollNames(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
sites []unifi.RemoteSite
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "multi-site uses internalReference not display name",
|
||||
sites: []unifi.RemoteSite{
|
||||
{ID: "uuid-1", InternalReference: "default", Name: "Default"},
|
||||
{ID: "uuid-2", InternalReference: "abc1def2", Name: "Office"},
|
||||
},
|
||||
want: []string{"default", "abc1def2"},
|
||||
},
|
||||
{
|
||||
name: "falls back to Name when internalReference is empty",
|
||||
sites: []unifi.RemoteSite{
|
||||
{ID: "uuid-1", Name: "default"},
|
||||
},
|
||||
want: []string{"default"},
|
||||
},
|
||||
{
|
||||
name: "skips sites with neither field",
|
||||
sites: []unifi.RemoteSite{
|
||||
{ID: "uuid-1"},
|
||||
{ID: "uuid-2", InternalReference: "site2", Name: "Two"},
|
||||
},
|
||||
want: []string{"site2"},
|
||||
},
|
||||
{
|
||||
name: "empty list",
|
||||
sites: nil,
|
||||
want: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, tt.want, remoteSitePollNames(tt.sites))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatRemoteSites(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sites := []unifi.RemoteSite{
|
||||
{ID: "uuid-1", InternalReference: "default", Name: "Default"},
|
||||
{ID: "uuid-2", InternalReference: "abc1def2", Name: "Office"},
|
||||
{ID: "uuid-3", InternalReference: "only-id"},
|
||||
{ID: "uuid-4", Name: "legacy-name-only"},
|
||||
}
|
||||
|
||||
assert.Equal(t, []string{
|
||||
"default",
|
||||
"Office (abc1def2)",
|
||||
"only-id",
|
||||
"legacy-name-only",
|
||||
}, formatRemoteSites(sites))
|
||||
}
|
||||
Reference in New Issue
Block a user