Files
ubiquiti-clients/pkg/edgeos/api.go

282 lines
5.5 KiB
Go

package edgeos
import (
"context"
"errors"
"sync"
)
// GetConfig retrieves the complete device configuration from /api/edge/get.json for a specific device.
func (c *Client) GetConfig(ctx context.Context, host string) (*ConfigData, error) {
d, err := c.getDeviceByHost(host)
if err != nil {
return nil, err
}
var out ConfigResponse
if err := d.do(ctx, "GET", "/api/edge/get.json", nil, &out); err != nil {
return nil, err
}
if !out.Success {
return nil, errors.New("config request unsuccessful")
}
return &out.GET, nil
}
// GetAllConfigs retrieves device configuration for all devices.
func (c *Client) GetAllConfigs(ctx context.Context) (map[string]*ConfigData, error) {
results := make(map[string]*ConfigData)
var (
mu sync.Mutex
wg sync.WaitGroup
errs error
)
c.mu.RLock()
hosts := make([]string, 0, len(c.devices))
for h := range c.devices {
hosts = append(hosts, h)
}
c.mu.RUnlock()
for _, host := range hosts {
wg.Go(func() {
res, err := c.GetConfig(ctx, host)
if err != nil {
mu.Lock()
errs = errors.Join(errs, err)
mu.Unlock()
return
}
mu.Lock()
results[host] = res
mu.Unlock()
})
}
wg.Wait()
return results, errs
}
// GetAuthInfo retrieves the authentication info for a specific device.
func (c *Client) GetAuthInfo(ctx context.Context, host string) (*AuthResponse, error) {
d, err := c.getDeviceByHost(host)
if err != nil {
return nil, err
}
d.mu.Lock()
authInfo := d.authInfo
d.mu.Unlock()
if authInfo == nil {
if err := d.login(ctx); err != nil {
return nil, err
}
d.mu.Lock()
authInfo = d.authInfo
d.mu.Unlock()
}
return authInfo, nil
}
// GetAllAuthInfo retrieves authentication info for all devices.
func (c *Client) GetAllAuthInfo(ctx context.Context) (map[string]*AuthResponse, error) {
results := make(map[string]*AuthResponse)
var (
mu sync.Mutex
wg sync.WaitGroup
errs error
)
c.mu.RLock()
hosts := make([]string, 0, len(c.devices))
for h := range c.devices {
hosts = append(hosts, h)
}
c.mu.RUnlock()
for _, host := range hosts {
wg.Go(func() {
res, err := c.GetAuthInfo(ctx, host)
if err != nil {
mu.Lock()
errs = errors.Join(errs, err)
mu.Unlock()
return
}
mu.Lock()
results[host] = res
mu.Unlock()
})
}
wg.Wait()
return results, errs
}
// GetInterfaces retrieves the interfaces for a specific device from the config data.
func (c *Client) GetInterfaces(ctx context.Context, host string) (*InterfacesConfig, error) {
config, err := c.GetConfig(ctx, host)
if err != nil {
return nil, err
}
return &config.Interfaces, nil
}
// GetAllInterfaces retrieves interfaces for all devices.
func (c *Client) GetAllInterfaces(ctx context.Context) (map[string]*InterfacesConfig, error) {
results := make(map[string]*InterfacesConfig)
var (
mu sync.Mutex
wg sync.WaitGroup
errs error
)
c.mu.RLock()
hosts := make([]string, 0, len(c.devices))
for h := range c.devices {
hosts = append(hosts, h)
}
c.mu.RUnlock()
for _, host := range hosts {
wg.Go(func() {
res, err := c.GetInterfaces(ctx, host)
if err != nil {
mu.Lock()
errs = errors.Join(errs, err)
mu.Unlock()
return
}
mu.Lock()
results[host] = res
mu.Unlock()
})
}
wg.Wait()
return results, errs
}
// GetSystem retrieves the system info for a specific device from the config data.
func (c *Client) GetSystem(ctx context.Context, host string) (*SystemConfig, error) {
config, err := c.GetConfig(ctx, host)
if err != nil {
return nil, err
}
return &config.System, nil
}
// GetAllSystems retrieves system info for all devices.
func (c *Client) GetAllSystems(ctx context.Context) (map[string]*SystemConfig, error) {
results := make(map[string]*SystemConfig)
var (
mu sync.Mutex
wg sync.WaitGroup
errs error
)
c.mu.RLock()
hosts := make([]string, 0, len(c.devices))
for h := range c.devices {
hosts = append(hosts, h)
}
c.mu.RUnlock()
for _, host := range hosts {
wg.Go(func() {
res, err := c.GetSystem(ctx, host)
if err != nil {
mu.Lock()
errs = errors.Join(errs, err)
mu.Unlock()
return
}
mu.Lock()
results[host] = res
mu.Unlock()
})
}
wg.Wait()
return results, errs
}
// GetEdgeOS retrieves all information for a specific device,
// combining AuthInfo and Config.
func (c *Client) GetEdgeOS(ctx context.Context, host string) (*EdgeOS, error) {
_, err := c.getDeviceByHost(host)
if err != nil {
return nil, err
}
eos := &EdgeOS{}
var (
mu sync.Mutex
wg sync.WaitGroup
errs error
)
// Fetch auth info and config in parallel
wg.Go(func() {
res, err := c.GetAuthInfo(ctx, host)
mu.Lock()
defer mu.Unlock()
if err != nil {
errs = errors.Join(errs, err)
return
}
eos.AuthInfo = res
})
wg.Go(func() {
res, err := c.GetConfig(ctx, host)
mu.Lock()
defer mu.Unlock()
if err != nil {
errs = errors.Join(errs, err)
return
}
eos.Config = res
})
wg.Wait()
return eos, errs
}
// GetAllEdgeOS retrieves all information for all devices.
func (c *Client) GetAllEdgeOS(ctx context.Context) (map[string]*EdgeOS, error) {
results := make(map[string]*EdgeOS)
var (
mu sync.Mutex
wg sync.WaitGroup
errs error
)
c.mu.RLock()
hosts := make([]string, 0, len(c.devices))
for h := range c.devices {
hosts = append(hosts, h)
}
c.mu.RUnlock()
for _, host := range hosts {
wg.Go(func() {
res, err := c.GetEdgeOS(ctx, host)
if err != nil {
mu.Lock()
errs = errors.Join(errs, err)
mu.Unlock()
return
}
mu.Lock()
results[host] = res
mu.Unlock()
})
}
wg.Wait()
return results, errs
}