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
+31
-20
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -412,13 +413,9 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, nil // discard stale result
|
||||
}
|
||||
m.loading = false
|
||||
if msg.err != nil {
|
||||
m.err = msg.err
|
||||
return m, nil
|
||||
}
|
||||
m.err = msg.err
|
||||
m.lastResults = msg.entries
|
||||
m.updateListItems(msg.entries)
|
||||
m.err = nil
|
||||
return m, nil
|
||||
}
|
||||
|
||||
@@ -495,9 +492,15 @@ func (m *Model) viewContent() string {
|
||||
|
||||
if m.loading {
|
||||
sb.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color("240")).Render(" searching…") + "\n")
|
||||
} else if m.err != nil {
|
||||
sb.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Render(" error: "+m.err.Error()) + "\n")
|
||||
} else {
|
||||
if m.err != nil {
|
||||
warning := " warning: " + strings.ReplaceAll(m.err.Error(), "\n", "; ")
|
||||
style := lipgloss.NewStyle().Foreground(lipgloss.Color("9"))
|
||||
if m.width > 0 {
|
||||
style = style.MaxWidth(m.width)
|
||||
}
|
||||
sb.WriteString(style.Render(warning) + "\n")
|
||||
}
|
||||
if m.recentMode && m.input.Value() == "" {
|
||||
if len(m.list.Items()) > 0 {
|
||||
sb.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color("240")).Render(" Recent connections") + "\n")
|
||||
@@ -534,25 +537,30 @@ func (m *Model) startDebounce() tea.Cmd {
|
||||
func (m *Model) doSearch(query string, seq int) tea.Cmd {
|
||||
opts := m.netboxSearchOpts()
|
||||
return func() tea.Msg {
|
||||
// Return cache hits immediately without a network round-trip.
|
||||
var cached []netbox.HostEntry
|
||||
if m.cache != nil {
|
||||
if cached := m.cache.Search(query); len(cached) > 0 {
|
||||
entries := make([]netbox.HostEntry, len(cached))
|
||||
for i, c := range cached {
|
||||
entries[i] = netbox.HostEntry{Name: c.Name, PrimaryIP4: c.IP, Kind: c.Kind, Tags: c.Tags}
|
||||
}
|
||||
return searchResultMsg{query: query, seq: seq, entries: entries}
|
||||
for _, entry := range m.cache.Search(query) {
|
||||
source, name := netbox.SplitTarget(entry.Name)
|
||||
cached = append(cached, netbox.HostEntry{Source: source, Name: name, PrimaryIP4: entry.IP, Kind: entry.Kind, Tags: entry.Tags})
|
||||
}
|
||||
}
|
||||
|
||||
if m.client == nil {
|
||||
return searchResultMsg{query: query, seq: seq, entries: nil}
|
||||
if m.client == nil || (len(cached) > 0 && !m.client.MultipleSources()) {
|
||||
return searchResultMsg{query: query, seq: seq, entries: cached}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
entries, err := m.client.Search(ctx, query, opts)
|
||||
// A cached hit in one instance must not hide live hosts in other instances.
|
||||
seen := make(map[string]bool)
|
||||
for _, e := range entries {
|
||||
seen[e.Target()+"\x00"+e.Kind] = true
|
||||
}
|
||||
for _, e := range cached {
|
||||
if !seen[e.Target()+"\x00"+e.Kind] {
|
||||
entries = append(entries, e)
|
||||
}
|
||||
}
|
||||
sort.SliceStable(entries, func(i, j int) bool { return entries[i].Target() < entries[j].Target() })
|
||||
return searchResultMsg{query: query, seq: seq, entries: entries, err: err}
|
||||
}
|
||||
}
|
||||
@@ -577,7 +585,7 @@ func (m *Model) updateListItems(entries []netbox.HostEntry) {
|
||||
if ip == "" {
|
||||
ip = e.PrimaryIP6
|
||||
}
|
||||
items[i] = hostItem{id: e.ID, name: e.Name, ip: ip, kind: e.Kind, tags: e.Tags}
|
||||
items[i] = hostItem{id: e.ID, name: e.Target(), ip: ip, kind: e.Kind, tags: e.Tags}
|
||||
}
|
||||
m.list.SetItems(items)
|
||||
m.resizeList()
|
||||
@@ -589,6 +597,9 @@ func (m *Model) resizeList() {
|
||||
return
|
||||
}
|
||||
extraRows := 5 // title, blank line, search, footer separator, footer
|
||||
if m.err != nil {
|
||||
extraRows++
|
||||
}
|
||||
if m.recentMode && m.input.Value() == "" && len(m.list.Items()) > 0 {
|
||||
extraRows++
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user