mirror of
https://github.com/unpoller/unpoller.git
synced 2026-03-31 06:24:21 -04:00
move remote.go to use unifi library functions
This commit is contained in:
@@ -1,228 +1,29 @@
|
||||
package inputunifi
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/unpoller/unifi/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
remoteAPIBaseURL = "https://api.ui.com"
|
||||
remoteAPIVersion = "v1"
|
||||
)
|
||||
|
||||
// Console represents a UniFi console from the remote API.
|
||||
type Console struct {
|
||||
ID string `json:"id"`
|
||||
IPAddress string `json:"ipAddress"`
|
||||
Type string `json:"type"`
|
||||
Owner bool `json:"owner"`
|
||||
IsBlocked bool `json:"isBlocked"`
|
||||
ReportedState struct {
|
||||
Name string `json:"name"`
|
||||
Hostname string `json:"hostname"`
|
||||
IP string `json:"ip"`
|
||||
State string `json:"state"`
|
||||
Mac string `json:"mac"`
|
||||
} `json:"reportedState"`
|
||||
ConsoleName string // Derived field: name from reportedState
|
||||
}
|
||||
|
||||
// HostsResponse represents the response from /v1/hosts endpoint.
|
||||
type HostsResponse struct {
|
||||
Data []Console `json:"data"`
|
||||
HTTPStatusCode int `json:"httpStatusCode"`
|
||||
TraceID string `json:"traceId"`
|
||||
NextToken string `json:"nextToken,omitempty"`
|
||||
}
|
||||
|
||||
// Site represents a site from the remote API.
|
||||
type RemoteSite struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// SitesResponse represents the response from the sites endpoint.
|
||||
type SitesResponse struct {
|
||||
Data []RemoteSite `json:"data"`
|
||||
HTTPStatusCode int `json:"httpStatusCode"`
|
||||
TraceID string `json:"traceId"`
|
||||
}
|
||||
|
||||
// remoteAPIClient handles HTTP requests to the remote UniFi API.
|
||||
type remoteAPIClient struct {
|
||||
apiKey string
|
||||
baseURL string
|
||||
client *http.Client
|
||||
logError func(string, ...any)
|
||||
logDebug func(string, ...any)
|
||||
log func(string, ...any)
|
||||
}
|
||||
|
||||
// newRemoteAPIClient creates a new remote API client.
|
||||
func (u *InputUnifi) newRemoteAPIClient(apiKey string) *remoteAPIClient {
|
||||
if apiKey == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// discoverRemoteControllers discovers all controllers via remote API and creates Controller entries.
|
||||
func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, error) {
|
||||
// Handle file:// prefix for API key
|
||||
if strings.HasPrefix(apiKey, "file://") {
|
||||
apiKey = u.getPassFromFile(strings.TrimPrefix(apiKey, "file://"))
|
||||
}
|
||||
|
||||
return &remoteAPIClient{
|
||||
apiKey: apiKey,
|
||||
baseURL: remoteAPIBaseURL,
|
||||
client: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
logError: u.LogErrorf,
|
||||
logDebug: u.LogDebugf,
|
||||
log: u.Logf,
|
||||
}
|
||||
}
|
||||
|
||||
// makeRequest makes an HTTP request to the remote API.
|
||||
func (c *remoteAPIClient) makeRequest(method, path string, queryParams map[string]string) ([]byte, error) {
|
||||
fullURL := c.baseURL + path
|
||||
|
||||
if len(queryParams) > 0 {
|
||||
u, err := url.Parse(fullURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing URL: %w", err)
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
for k, v := range queryParams {
|
||||
q.Set(k, v)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
fullURL = u.String()
|
||||
}
|
||||
|
||||
c.logDebug("Making %s request to: %s", method, fullURL)
|
||||
|
||||
req, err := http.NewRequest(method, fullURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("X-API-Key", c.apiKey)
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("making request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// discoverConsoles discovers all consoles available via the remote API.
|
||||
func (c *remoteAPIClient) discoverConsoles() ([]Console, error) {
|
||||
// Start with first page
|
||||
queryParams := map[string]string{
|
||||
"pageSize": "10",
|
||||
}
|
||||
|
||||
var allConsoles []Console
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
queryParams["nextToken"] = nextToken
|
||||
} else {
|
||||
// Remove nextToken from params for first request
|
||||
delete(queryParams, "nextToken")
|
||||
}
|
||||
|
||||
body, err := c.makeRequest("GET", "/v1/hosts", queryParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching consoles: %w", err)
|
||||
}
|
||||
|
||||
var response HostsResponse
|
||||
if err := json.Unmarshal(body, &response); err != nil {
|
||||
return nil, fmt.Errorf("parsing consoles response: %w", err)
|
||||
}
|
||||
|
||||
// Filter for console type only
|
||||
for _, console := range response.Data {
|
||||
if console.Type == "console" && !console.IsBlocked {
|
||||
// Extract the console name from reportedState
|
||||
console.ConsoleName = console.ReportedState.Name
|
||||
if console.ConsoleName == "" {
|
||||
console.ConsoleName = console.ReportedState.Hostname
|
||||
}
|
||||
allConsoles = append(allConsoles, console)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there's a nextToken to continue pagination
|
||||
if response.NextToken == "" {
|
||||
break
|
||||
}
|
||||
|
||||
nextToken = response.NextToken
|
||||
c.logDebug("Fetching next page of consoles with nextToken: %s", nextToken)
|
||||
}
|
||||
|
||||
return allConsoles, nil
|
||||
}
|
||||
|
||||
// discoverSites discovers all sites for a given console ID.
|
||||
func (c *remoteAPIClient) discoverSites(consoleID string) ([]RemoteSite, error) {
|
||||
path := fmt.Sprintf("/v1/connector/consoles/%s/proxy/network/integration/v1/sites", consoleID)
|
||||
|
||||
queryParams := map[string]string{
|
||||
"offset": "0",
|
||||
"limit": "100",
|
||||
}
|
||||
|
||||
body, err := c.makeRequest("GET", path, queryParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching sites for console %s: %w", consoleID, err)
|
||||
}
|
||||
|
||||
var response SitesResponse
|
||||
if err := json.Unmarshal(body, &response); err != nil {
|
||||
return nil, fmt.Errorf("parsing sites response: %w", err)
|
||||
}
|
||||
|
||||
return response.Data, nil
|
||||
}
|
||||
|
||||
// discoverRemoteControllers discovers all controllers via remote API and creates Controller entries.
|
||||
func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, error) {
|
||||
client := u.newRemoteAPIClient(apiKey)
|
||||
if client == nil {
|
||||
if apiKey == "" {
|
||||
return nil, fmt.Errorf("remote API key not provided")
|
||||
}
|
||||
|
||||
// Use library client
|
||||
client := unifi.NewRemoteAPIClient(apiKey, u.LogErrorf, u.LogDebugf, u.Logf)
|
||||
|
||||
u.Logf("Discovering remote UniFi consoles...")
|
||||
|
||||
consoles, err := client.discoverConsoles()
|
||||
consoles, err := client.DiscoverConsoles()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("discovering consoles: %w", err)
|
||||
}
|
||||
@@ -246,7 +47,7 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
}
|
||||
u.LogDebugf("Discovering sites for console: %s (%s)", console.ID, consoleName)
|
||||
|
||||
sites, err := client.discoverSites(console.ID)
|
||||
sites, err := client.DiscoverSites(console.ID)
|
||||
if err != nil {
|
||||
u.LogErrorf("Failed to discover sites for console %s: %v", console.ID, err)
|
||||
continue
|
||||
@@ -268,7 +69,7 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
// Set URL to connector base - the library appends /proxy/network/status
|
||||
// But for integration API we need /proxy/network/integration/v1/...
|
||||
// This may require library updates, but try connector base first
|
||||
URL: fmt.Sprintf("%s/v1/connector/consoles/%s", remoteAPIBaseURL, console.ID),
|
||||
URL: fmt.Sprintf("%s/v1/connector/consoles/%s", unifi.RemoteAPIBaseURL, console.ID),
|
||||
}
|
||||
|
||||
// Ensure defaults are set before calling setControllerDefaults
|
||||
|
||||
Reference in New Issue
Block a user