feat: search multiple NetBox instances with isolated host identities
Release / release (push) Successful in 5m16s
Release / release (push) Successful in 5m16s
This commit is contained in:
1 parent
a2a6dd7591
commit
7f53b90266
26 files changed
+1299
-115
No files matched your search
@@ -15,6 +15,7 @@ import (
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
sources map[string]*Client
|
||||
baseURL string
|
||||
token string
|
||||
tokenVersion int
|
||||
@@ -38,6 +39,9 @@ func NewClient(baseURL, token string, tokenVersion int) *Client {
|
||||
// Search queries up to 50 devices and VMs in parallel and merges the results.
|
||||
// Use SearchOptions to restrict by kind or tag.
|
||||
func (c *Client) Search(ctx context.Context, query string, opts SearchOptions) ([]HostEntry, error) {
|
||||
if c.sources != nil {
|
||||
return c.searchSources(ctx, query, opts, false)
|
||||
}
|
||||
if opts.Kind != "" && opts.Kind != "device" && opts.Kind != "vm" {
|
||||
return nil, fmt.Errorf("invalid host kind %q", opts.Kind)
|
||||
}
|
||||
@@ -95,6 +99,9 @@ func (c *Client) Search(ctx context.Context, query string, opts SearchOptions) (
|
||||
// SearchAll paginates through all matching devices and VMs, fetching every page.
|
||||
// Intended for cache refresh; use Search for interactive queries.
|
||||
func (c *Client) SearchAll(ctx context.Context, query string, opts SearchOptions) ([]HostEntry, error) {
|
||||
if c.sources != nil {
|
||||
return c.searchSources(ctx, query, opts, true)
|
||||
}
|
||||
if opts.Kind != "" && opts.Kind != "device" && opts.Kind != "vm" {
|
||||
return nil, fmt.Errorf("invalid host kind %q", opts.Kind)
|
||||
}
|
||||
@@ -146,6 +153,13 @@ func (c *Client) SearchAll(ctx context.Context, query string, opts SearchOptions
|
||||
// GetIPs returns all IP addresses assigned to a host, used by resolver strategies
|
||||
// that need more than just the primary IP.
|
||||
func (c *Client) GetIPs(ctx context.Context, entry HostEntry) ([]string, error) {
|
||||
if c.sources != nil {
|
||||
source, host, err := c.sourceForHost(entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return source.GetIPs(ctx, host)
|
||||
}
|
||||
var apiURL string
|
||||
switch entry.Kind {
|
||||
case "device":
|
||||
@@ -170,6 +184,9 @@ func (c *Client) GetIPs(ctx context.Context, entry HostEntry) ([]string, error)
|
||||
|
||||
// GetIPsWithFilter calls /api/ipam/ip-addresses/ with arbitrary filter query parameters.
|
||||
func (c *Client) GetIPsWithFilter(ctx context.Context, filterParams string) ([]string, error) {
|
||||
if c.sources != nil {
|
||||
return nil, fmt.Errorf("IP filters require a host instance; use GetIPsWithFilterForHost")
|
||||
}
|
||||
apiURL := fmt.Sprintf("%s/api/ipam/ip-addresses/?%s&limit=100", c.baseURL, filterParams)
|
||||
var resp netboxIPListResponse
|
||||
if err := c.get(ctx, apiURL, &resp); err != nil {
|
||||
@@ -360,12 +377,13 @@ func (c *Client) FindHost(ctx context.Context, name, kind string) (HostEntry, er
|
||||
return HostEntry{}, fmt.Errorf("invalid kind %q", kind)
|
||||
}
|
||||
entries, err := c.SearchAll(ctx, name, SearchOptions{Kind: kind})
|
||||
_, hostname := SplitTarget(name)
|
||||
if err != nil {
|
||||
return HostEntry{}, err
|
||||
}
|
||||
var matches []HostEntry
|
||||
for _, e := range entries {
|
||||
if strings.EqualFold(e.Name, name) {
|
||||
if strings.EqualFold(e.Name, hostname) {
|
||||
matches = append(matches, e)
|
||||
}
|
||||
}
|
||||
@@ -373,6 +391,9 @@ func (c *Client) FindHost(ctx context.Context, name, kind string) (HostEntry, er
|
||||
return HostEntry{}, fmt.Errorf("%w: %q", ErrHostNotFound, name)
|
||||
}
|
||||
if len(matches) != 1 {
|
||||
if c.sources != nil {
|
||||
return HostEntry{}, fmt.Errorf("host %q: found %d exact matches; use instance/hostname and --kind to select a unique host", name, len(matches))
|
||||
}
|
||||
return HostEntry{}, fmt.Errorf("host %q: found %d exact matches; use --kind or a unique hostname", name, len(matches))
|
||||
}
|
||||
return matches[0], nil
|
||||
@@ -395,6 +416,13 @@ func (c *Client) hostURL(host HostEntry) (string, error) {
|
||||
}
|
||||
|
||||
func (c *Client) GetComments(ctx context.Context, host HostEntry) (string, string, error) {
|
||||
if c.sources != nil {
|
||||
source, host, err := c.sourceForHost(host)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return source.GetComments(ctx, host)
|
||||
}
|
||||
u, err := c.hostURL(host)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
@@ -407,6 +435,13 @@ func (c *Client) GetComments(ctx context.Context, host HostEntry) (string, strin
|
||||
}
|
||||
|
||||
func (c *Client) SetComments(ctx context.Context, host HostEntry, comments, etag string) error {
|
||||
if c.sources != nil {
|
||||
source, host, err := c.sourceForHost(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return source.SetComments(ctx, host, comments, etag)
|
||||
}
|
||||
u, err := c.hostURL(host)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in new issue
Block a user