Check backend hosts only when the source fact is enabled, compare them case-insensitively
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful

This commit is contained in:
2026-10-09 23:49:42 +11:00
parent a43e5481f0
commit b1d68f5c80
4 changed files with 31 additions and 13 deletions
+4 -1
View File
@@ -296,7 +296,7 @@ func backendHost(raw string) string {
if err != nil {
return ""
}
return u.Hostname()
return strings.ToLower(u.Hostname())
}
func (c Config) Validate() error {
@@ -314,6 +314,9 @@ func (c Config) Validate() error {
return fmt.Errorf("duplicate backend name %q", b.Name)
}
seen[b.Name] = true
if !c.SourceFactEnabled {
continue
}
host := backendHost(b.URL)
if host == "" {
return fmt.Errorf("backend %q url %q has no host", b.Name, b.URL)
+21
View File
@@ -234,6 +234,15 @@ func TestValidate(t *testing.T) {
{"url without host", func(c *Config) { c.Backends[0].URL = "localhost:18080" }, true},
{"shared host on another port", func(c *Config) { c.Backends[1].URL = "http://localhost:18081" }, true},
{"same host differing by scheme", func(c *Config) { c.Backends[1].URL = "https://localhost" }, true},
{"same host differing by case", func(c *Config) { c.Backends[1].URL = "http://LocalHost:18081" }, true},
{"shared host while source fact disabled", func(c *Config) {
c.SourceFactEnabled = false
c.Backends[1].URL = "http://localhost:18081"
}, false},
{"url without host while source fact disabled", func(c *Config) {
c.SourceFactEnabled = false
c.Backends[0].URL = "localhost:18080"
}, false},
{"bad merge", func(c *Config) { c.Merge = "wrong" }, true},
{"zero timeout", func(c *Config) { c.Timeout = 0 }, true},
{"empty source fact while enabled", func(c *Config) { c.SourceFact = "" }, true},
@@ -515,3 +524,15 @@ func clearEnv(t *testing.T) {
t.Setenv(envPrefix+k, "")
}
}
func TestBackendHost(t *testing.T) {
for raw, want := range map[string]string{
"https://PuppetDB.Example:8081/x": "puppetdb.example",
"http://[::1]:8080": "::1",
"localhost:8080": "",
} {
if got := backendHost(raw); got != want {
t.Errorf("backendHost(%q) = %q, want %q", raw, got, want)
}
}
}
+3 -10
View File
@@ -13,7 +13,7 @@ import (
// callers need no branch.
type sourceInjector struct {
name string
// hosts maps backend name to the value emitted; an unmapped name is emitted as-is.
// hosts maps backend name to the value emitted.
hosts map[string]string
// inject is false when the query shape rules synthesis out. Suppression of an
// upstream fact of the same name does not depend on it.
@@ -38,13 +38,6 @@ func (si *sourceInjector) claims(factName string) bool {
return si != nil && factName != "" && factName == si.name
}
func (si *sourceInjector) value(backend string) string {
if h, ok := si.hosts[backend]; ok {
return h
}
return backend
}
// injects reports whether this response may carry the synthetic record.
func (si *sourceInjector) injects() bool {
return si != nil && si.inject
@@ -79,7 +72,7 @@ func (si *sourceInjector) factRecord(certname, backend, environment string) json
Environment string `json:"environment"`
Name string `json:"name"`
Value string `json:"value"`
}{Certname: certname, Environment: environment, Name: si.name, Value: si.value(backend)})
}{Certname: certname, Environment: environment, Name: si.name, Value: si.hosts[backend]})
if err != nil {
return nil
}
@@ -96,7 +89,7 @@ func (si *sourceInjector) stamp(raw json.RawMessage, backend string) json.RawMes
if json.Unmarshal(raw, &obj) != nil || obj == nil {
return raw
}
value, err := json.Marshal(si.value(backend))
value, err := json.Marshal(si.hosts[backend])
if err != nil {
return raw
}
+3 -2
View File
@@ -560,10 +560,11 @@ func TestMergeFacts_GatedSuppressesUpstream(t *testing.T) {
func TestMergeFacts_SourceOrderedAfterOwnersFacts(t *testing.T) {
a := recs(t, "a", fact("h1", "role", "web-a", ""), fact("h1", "kernel", "Linux", ""))
b := recs(t, "b", fact("h1", "role", "web-b", ""))
merged := mergeFacts([]backendResult{a, b}, nil, &sourceInjector{name: defaultSourceFact, inject: true})
si := &sourceInjector{name: defaultSourceFact, hosts: map[string]string{"a": "a.example", "b": "b.example"}, inject: true}
merged := mergeFacts([]backendResult{a, b}, nil, si)
got := factValues(t, merged)
want := []string{"h1:role=web-a", "h1:kernel=Linux", "h1:" + defaultSourceFact + "=a"}
want := []string{"h1:role=web-a", "h1:kernel=Linux", "h1:" + defaultSourceFact + "=a.example"}
if !slices.Equal(got, want) {
t.Errorf("merged = %v, want %v", got, want)
}