package config import ( "os" "path/filepath" "testing" "time" ) func TestLoadDefaults(t *testing.T) { clearEnv(t) c, err := Load() if err != nil { t.Fatal(err) } if c.ListenAddr != ":8000" { t.Errorf("ListenAddr = %q", c.ListenAddr) } if c.CacheTTL != 30*time.Second { t.Errorf("CacheTTL = %v", c.CacheTTL) } if c.DefaultTemplate != "almalinux9" { t.Errorf("DefaultTemplate = %q", c.DefaultTemplate) } if c.PuppetServer != "puppet.query.consul" || c.PuppetCAServer != "puppetca.query.consul" { t.Errorf("puppet servers = %q / %q", c.PuppetServer, c.PuppetCAServer) } if c.UnknownMACFallback != "local" { t.Errorf("UnknownMACFallback = %q", c.UnknownMACFallback) } } func TestLoadTokenFile(t *testing.T) { clearEnv(t) dir := t.TempDir() tf := filepath.Join(dir, "token") if err := os.WriteFile(tf, []byte(" secret-token\n"), 0o600); err != nil { t.Fatal(err) } t.Setenv("BOOTAPI_NETBOX_TOKEN_FILE", tf) c, err := Load() if err != nil { t.Fatal(err) } if c.NetBoxToken != "secret-token" { t.Errorf("token = %q, want trimmed file contents", c.NetBoxToken) } } func TestLoadRejectsBadFallback(t *testing.T) { clearEnv(t) t.Setenv("BOOTAPI_UNKNOWN_MAC_FALLBACK", "bogus") if _, err := Load(); err == nil { t.Fatal("expected error for invalid fallback") } } func TestLoadListsAndTrim(t *testing.T) { clearEnv(t) t.Setenv("BOOTAPI_NAMESERVERS", " 10.0.0.1, 10.0.0.2 ,") t.Setenv("BOOTAPI_NETBOX_URL", "https://netbox.example.net/") c, err := Load() if err != nil { t.Fatal(err) } if len(c.Nameservers) != 2 || c.Nameservers[1] != "10.0.0.2" { t.Errorf("nameservers = %v", c.Nameservers) } if c.NetBoxURL != "https://netbox.example.net" { t.Errorf("NetBoxURL trailing slash not trimmed: %q", c.NetBoxURL) } } // clearEnv unsets every BOOTAPI_* var so a developer's shell can't leak into // the test. t.Setenv restores them after the test. func clearEnv(t *testing.T) { t.Helper() for _, kv := range os.Environ() { if k, _, ok := cut(kv, '='); ok && len(k) > 8 && k[:8] == "BOOTAPI_" { // t.Setenv to "" is enough: Load treats empty as unset, and the // test framework restores the original value on cleanup. t.Setenv(k, "") } } } func cut(s string, sep byte) (before, after string, found bool) { for i := 0; i < len(s); i++ { if s[i] == sep { return s[:i], s[i+1:], true } } return s, "", false }