Add thread-safe Add/Del methods and refactor client locking
- Add Add and Del methods to Client for dynamic host management. - Add RWMutex to Client to protect the devices map. - Add Transport to Config to allow mocking HTTP transport in tests. - Add getDeviceByHost helper to centralize device lookup locking. - Refactor GetAll* methods to snapshot host keys before iteration to avoid concurrent map read/write panic. - Add tests for thread safety and Add/Del functionality.
This commit is contained in:
@@ -3,15 +3,14 @@ package edgeos
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// GetInterfaces retrieves the interfaces for a specific device.
|
||||
func (c *Client) GetInterfaces(ctx context.Context, host string) ([]Interface, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []Interface
|
||||
@@ -31,7 +30,14 @@ func (c *Client) GetAllInterfaces(ctx context.Context) (map[string][]Interface,
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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 {
|
||||
@@ -51,9 +57,9 @@ func (c *Client) GetAllInterfaces(ctx context.Context) (map[string][]Interface,
|
||||
|
||||
// GetDevice retrieves the device info for a specific device.
|
||||
func (c *Client) GetDevice(ctx context.Context, host string) (*Device, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out Device
|
||||
@@ -73,7 +79,14 @@ func (c *Client) GetAllDevices(ctx context.Context) (map[string]*Device, error)
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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.GetDevice(ctx, host)
|
||||
if err != nil {
|
||||
@@ -93,9 +106,9 @@ func (c *Client) GetAllDevices(ctx context.Context) (map[string]*Device, error)
|
||||
|
||||
// GetSystem retrieves the system info for a specific device.
|
||||
func (c *Client) GetSystem(ctx context.Context, host string) (*System, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out System
|
||||
@@ -115,7 +128,14 @@ func (c *Client) GetAllSystems(ctx context.Context) (map[string]*System, error)
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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 {
|
||||
@@ -135,9 +155,9 @@ func (c *Client) GetAllSystems(ctx context.Context) (map[string]*System, error)
|
||||
|
||||
// GetVLANs retrieves the VLANs for a specific device.
|
||||
func (c *Client) GetVLANs(ctx context.Context, host string) (*VLANs, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out VLANs
|
||||
@@ -157,7 +177,14 @@ func (c *Client) GetAllVLANs(ctx context.Context) (map[string]*VLANs, error) {
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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.GetVLANs(ctx, host)
|
||||
if err != nil {
|
||||
@@ -177,9 +204,9 @@ func (c *Client) GetAllVLANs(ctx context.Context) (map[string]*VLANs, error) {
|
||||
|
||||
// GetServices retrieves the services for a specific device.
|
||||
func (c *Client) GetServices(ctx context.Context, host string) (*Services, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out Services
|
||||
@@ -199,7 +226,14 @@ func (c *Client) GetAllServices(ctx context.Context) (map[string]*Services, erro
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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.GetServices(ctx, host)
|
||||
if err != nil {
|
||||
@@ -219,9 +253,9 @@ func (c *Client) GetAllServices(ctx context.Context) (map[string]*Services, erro
|
||||
|
||||
// GetStatistics retrieves the statistics for a specific device.
|
||||
func (c *Client) GetStatistics(ctx context.Context, host string) ([]Statistics, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []Statistics
|
||||
@@ -241,7 +275,14 @@ func (c *Client) GetAllStatistics(ctx context.Context) (map[string][]Statistics,
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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.GetStatistics(ctx, host)
|
||||
if err != nil {
|
||||
@@ -261,9 +302,9 @@ func (c *Client) GetAllStatistics(ctx context.Context) (map[string][]Statistics,
|
||||
|
||||
// GetNeighbors retrieves the neighbors for a specific device.
|
||||
func (c *Client) GetNeighbors(ctx context.Context, host string) ([]Neighbor, error) {
|
||||
d, ok := c.devices[host]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("device not found: %s", host)
|
||||
d, err := c.getDeviceByHost(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []Neighbor
|
||||
@@ -283,7 +324,14 @@ func (c *Client) GetAllNeighbors(ctx context.Context) (map[string][]Neighbor, er
|
||||
errs error
|
||||
)
|
||||
|
||||
for host := range c.devices {
|
||||
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.GetNeighbors(ctx, host)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user