Files
ssh-netbox-wrapper/internal/shortcuts/shortcuts.go
T
Sebastian UnterschützandClaude Opus 5.5 55e7a5106b fix: interface_name strategy, instance hosts in sftp/scp, alias rewrites
Found by the new Docker test environment against a real NetBox 4.7:

- The interface_name strategy filtered IP addresses with interface_name
  and vminterface_name, which NetBox ignores, so it returned the first
  address of the host instead of the named interface's. Use the real
  filters interface and vminterface; a missing interface (HTTP 400)
  falls through to the next strategy.
- sftp and scp took instance-qualified hosts (prod/web01:/path) for
  local paths, because a "/" comes before the ":". Such arguments are
  remote when the prefix is a configured NetBox instance.
- Shell aliases of instance-qualified hosts ran the shortcut rules on
  "instance/host", so anchored rewrite rules never matched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 12:30:24 +01:00

70 lines
2.0 KiB
Go

package shortcuts
import (
"regexp"
"strings"
"sync"
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/config"
)
// compiled caches rewrite patterns: Normalize runs for every cache entry on each lookup.
var compiled sync.Map // pattern → *regexp.Regexp
func rewritePattern(pattern string) *regexp.Regexp {
if re, ok := compiled.Load(pattern); ok {
return re.(*regexp.Regexp)
}
re, err := regexp.Compile(pattern)
if err != nil {
return nil // rejected by config.Load already
}
compiled.Store(pattern, re)
return re
}
// Normalize strips configured domain suffixes, applies rewrite rules in order, and
// optionally strips hyphens. The result is lowercased for case-insensitive comparison.
func Normalize(name string, cfg config.ShortcutsConfig) string {
s := strings.ToLower(name)
for _, domain := range cfg.Domains {
suffix := strings.ToLower(domain)
if !strings.HasPrefix(suffix, ".") {
suffix = "." + suffix
}
if strings.HasSuffix(s, suffix) {
s = s[:len(s)-len(suffix)]
break
}
}
for _, rewrite := range cfg.Rewrites {
if re := rewritePattern(rewrite.Pattern); re != nil {
s = re.ReplaceAllString(s, rewrite.Replace)
}
}
if cfg.StripHyphens {
s = strings.ReplaceAll(s, "-", "")
}
return s
}
// MakeNormalizer returns a closure bound to cfg, suitable for Cache.GetByShortcut.
func MakeNormalizer(cfg config.ShortcutsConfig) func(string) string {
return func(name string) string {
return Normalize(name, cfg)
}
}
// AliasName returns a shell-safe alias name for the given host.
// It normalizes the name (strips configured domains, applies rewrites, optionally strips hyphens) then
// replaces any remaining dots with underscores so the result is a valid identifier.
func AliasName(name string, cfg config.ShortcutsConfig) string {
// Shorten only the hostname: anchored rewrite rules must not see "instance/".
prefix := ""
if source, host, ok := strings.Cut(name, "/"); ok {
prefix, name = strings.ToLower(source)+"_", host
}
s := prefix + Normalize(name, cfg)
return strings.NewReplacer(".", "_", "/", "_").Replace(s)
}