- **Shortcuts**: Add hostname normalization with domain stripping and hyphen folding. Include alias generation for cached hosts. - **Shell Hook**: Automate 24h cache refresh trigger with shell startup hook. Add install/uninstall commands for bash, zsh, and fish. - **Wizard**: Extend setup wizard to configure shortcuts (domains, hyphen stripping) and default SSH port. - **Cache**: Add `GetByShortcut` for resolving hosts via normalized shortcuts. Implement `NeedsRefresh` / `SetRefreshed` logic for refresh timestamps. - **Tests**: Comprehensive unit tests for shortcuts, hook installation, cache refresh, and alias generation. - **Docs**: Update README with shortcuts, shell hook, and default SSH port configuration.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package shortcuts
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/config"
|
||||
)
|
||||
|
||||
// Normalize strips configured domain suffixes and optionally hyphens from a hostname.
|
||||
// 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
|
||||
}
|
||||
}
|
||||
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 and optionally hyphens) then
|
||||
// replaces any remaining dots with underscores so the result is a valid identifier.
|
||||
func AliasName(name string, cfg config.ShortcutsConfig) string {
|
||||
s := Normalize(name, cfg)
|
||||
return strings.ReplaceAll(s, ".", "_")
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package shortcuts_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/config"
|
||||
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/shortcuts"
|
||||
)
|
||||
|
||||
func TestNormalize(t *testing.T) {
|
||||
cfg := config.ShortcutsConfig{
|
||||
Domains: []string{".example.com", ".example.de"},
|
||||
StripHyphens: true,
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{"fsn1-web01.example.com", "fsn1web01"},
|
||||
{"fsn1-web01.example.de", "fsn1web01"},
|
||||
{"FSN1-WEB01.EXAMPLE.COM", "fsn1web01"},
|
||||
{"fsn1-web01", "fsn1web01"},
|
||||
{"web01.example.com", "web01"},
|
||||
{"web01.other.com", "web01.other.com"}, // unknown domain not stripped
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
got := shortcuts.Normalize(c.input, cfg)
|
||||
if got != c.want {
|
||||
t.Errorf("Normalize(%q) = %q, want %q", c.input, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeNoHyphenStrip(t *testing.T) {
|
||||
cfg := config.ShortcutsConfig{
|
||||
Domains: []string{".example.com"},
|
||||
StripHyphens: false,
|
||||
}
|
||||
|
||||
got := shortcuts.Normalize("fsn1-web01.example.com", cfg)
|
||||
want := "fsn1-web01"
|
||||
if got != want {
|
||||
t.Errorf("Normalize = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAliasName_WithDomainAndHyphens(t *testing.T) {
|
||||
cfg := config.ShortcutsConfig{
|
||||
Domains: []string{".example.com"},
|
||||
StripHyphens: true,
|
||||
}
|
||||
got := shortcuts.AliasName("fsn1-web01.example.com", cfg)
|
||||
want := "fsn1web01"
|
||||
if got != want {
|
||||
t.Errorf("AliasName = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAliasName_DotReplacement(t *testing.T) {
|
||||
cfg := config.ShortcutsConfig{
|
||||
Domains: []string{".example.com"},
|
||||
}
|
||||
// "web01.other.com" — domain not stripped, remaining dots → underscores
|
||||
got := shortcuts.AliasName("web01.other.com", cfg)
|
||||
want := "web01_other_com"
|
||||
if got != want {
|
||||
t.Errorf("AliasName = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAliasName_NoConfig(t *testing.T) {
|
||||
cfg := config.ShortcutsConfig{}
|
||||
got := shortcuts.AliasName("web01.example.com", cfg)
|
||||
want := "web01_example_com"
|
||||
if got != want {
|
||||
t.Errorf("AliasName = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user