mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-09 16:00:59 +00:00
Adopt the agent's preferred host when re-registering a matched node
The resolved-identity match in canonical auto-register always preserved the stored host, so the route-aware IP preference added to the agent in022f170dfcould never take effect for an already-registered node: a reinstall re-matched the node and kept the stale short-DNS host forever. Preserve the stored host only when it is absent from the agent's ordered candidate list (an admin-managed endpoint the agent cannot see); when the agent itself lists the stored host as a lower-priority candidate, adopt the newly selected host. Identity continuity (same node record, same token) is unchanged. Note: commitc21693489carries this same message by mistake; it actually contains concurrent OIDC/SAML mapping work from a parallel session that was staged when the shared index raced. This commit is the real change.
This commit is contained in:
parent
c21693489a
commit
f850099134
2 changed files with 66 additions and 2 deletions
|
|
@ -424,6 +424,22 @@ func canonicalAutoRegisterMatchMessage(reason string) string {
|
|||
return "Canonical auto-register matched existing node by " + reason
|
||||
}
|
||||
|
||||
// shouldPreserveExistingAutoRegisterHost reports whether an identity-matched
|
||||
// node keeps its stored host on re-registration. The agent orders
|
||||
// candidateHosts by preference, so an existing host that appears anywhere in
|
||||
// that list was deliberately outranked by the selected host and is replaced.
|
||||
// A host absent from the list is an admin-managed endpoint the agent cannot
|
||||
// see; keep it.
|
||||
func shouldPreserveExistingAutoRegisterHost(existingHost string, candidateHosts []string) bool {
|
||||
existing := strings.TrimSpace(existingHost)
|
||||
for _, candidate := range candidateHosts {
|
||||
if strings.EqualFold(strings.TrimSpace(candidate), existing) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func canonicalAutoRegisterCompletionPayloadMessage() string {
|
||||
return "Incomplete canonical auto-register token completion payload"
|
||||
}
|
||||
|
|
@ -1314,10 +1330,11 @@ func (h *ConfigHandlers) handleCanonicalAutoRegister(w http.ResponseWriter, r *h
|
|||
}
|
||||
if hostsShareResolvedIdentity(node.Host, host) {
|
||||
existingIndex = i
|
||||
preserveHost = true
|
||||
preserveHost = shouldPreserveExistingAutoRegisterHost(node.Host, candidateHosts)
|
||||
log.Info().
|
||||
Str("existingHost", node.Host).
|
||||
Str("newHost", host).
|
||||
Bool("preserveHost", preserveHost).
|
||||
Str("type", "pve").
|
||||
Msg(canonicalAutoRegisterMatchMessage("resolved host identity"))
|
||||
break
|
||||
|
|
@ -1391,10 +1408,11 @@ func (h *ConfigHandlers) handleCanonicalAutoRegister(w http.ResponseWriter, r *h
|
|||
}
|
||||
if hostsShareResolvedIdentity(node.Host, host) {
|
||||
existingIndex = i
|
||||
preserveHost = true
|
||||
preserveHost = shouldPreserveExistingAutoRegisterHost(node.Host, candidateHosts)
|
||||
log.Info().
|
||||
Str("existingHost", node.Host).
|
||||
Str("newHost", host).
|
||||
Bool("preserveHost", preserveHost).
|
||||
Str("type", "pbs").
|
||||
Msg(canonicalAutoRegisterMatchMessage("resolved host identity"))
|
||||
break
|
||||
|
|
|
|||
46
internal/api/config_setup_handlers_test.go
Normal file
46
internal/api/config_setup_handlers_test.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package api
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestShouldPreserveExistingAutoRegisterHost(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
existingHost string
|
||||
candidateHosts []string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "existing host outranked in candidate list is replaced",
|
||||
existingHost: "https://pve02:8006",
|
||||
candidateHosts: []string{"https://192.168.1.12:8006", "https://pve02:8006"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "existing host matches candidate case-insensitively",
|
||||
existingHost: "https://PVE02:8006",
|
||||
candidateHosts: []string{"https://192.168.1.12:8006", "https://pve02:8006"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "admin-managed host absent from candidates is preserved",
|
||||
existingHost: "https://pve02.internal.example.com:8006",
|
||||
candidateHosts: []string{"https://192.168.1.12:8006", "https://pve02:8006"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty candidate list preserves existing host",
|
||||
existingHost: "https://pve02:8006",
|
||||
candidateHosts: nil,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := shouldPreserveExistingAutoRegisterHost(tt.existingHost, tt.candidateHosts); got != tt.want {
|
||||
t.Fatalf("shouldPreserveExistingAutoRegisterHost(%q, %v) = %v, want %v",
|
||||
tt.existingHost, tt.candidateHosts, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue