fix(cluster): Alle Placeholder-Rows bei autoRegister bereinigen

AgentRegisterPeer löschte bisher nur den neuen prenode-{fqdn}-Placeholder.
Alte pre-{timestamp}-Rows (aus Versionen vor 1.1.158) blieben stehen und
zeigten dauerhaft status=joining.

Fix: DeletePlaceholdersByFQDN löscht ALLE ha_nodes-Rows mit gleicher FQDN
außer der echten Node-ID — unabhängig vom ID-Format.

Auch preRegisterByFQDN nutzt jetzt das stabile prenode-{fqdn}-Format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-29 18:33:50 +02:00
parent 8d83de6b0f
commit 357113e7be
6 changed files with 18 additions and 11 deletions

View File

@@ -1 +1 @@
1.1.158
1.1.159

View File

@@ -60,7 +60,7 @@ import (
usersvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/users"
)
var version = "1.1.158"
var version = "1.1.159"
func main() {
addr := os.Getenv("EDGEGUARD_API_ADDR")

View File

@@ -11,7 +11,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
)
var version = "1.1.158"
var version = "1.1.159"
const usage = `edgeguard-ctl — EdgeGuard CLI

View File

@@ -41,7 +41,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
)
var version = "1.1.158"
var version = "1.1.159"
const (
// renewTickInterval — how often we re-evaluate expiring certs.

View File

@@ -115,6 +115,16 @@ func (s *Store) Delete(ctx context.Context, id string) error {
return nil
}
// DeletePlaceholdersByFQDN removes all ha_nodes rows that share the given
// FQDN but do NOT have the specified keepID. Used to clean up pre-registered
// placeholder rows (both old "pre-{timestamp}" and new "prenode-{fqdn}"
// style) after a real autoRegister arrives via mTLS.
func (s *Store) DeletePlaceholdersByFQDN(ctx context.Context, fqdn, keepID string) error {
_, err := s.Pool.Exec(ctx,
`DELETE FROM ha_nodes WHERE fqdn = $1 AND id != $2`, fqdn, keepID)
return err
}
// EnsureSelfRegistered mints the node-id if needed, builds the row
// from setup.json + os.Hostname + node.conf, and upserts it. Called
// on edgeguard-api boot AFTER the DB pool is reachable.

View File

@@ -337,7 +337,7 @@ func (h *ClusterHandler) GenerateJoinToken(c *gin.Context) {
func (h *ClusterHandler) preRegisterByFQDN(fqdn string) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
nodeID := fmt.Sprintf("pre-%x", time.Now().UnixNano())
nodeID := fmt.Sprintf("prenode-%s", strings.ReplaceAll(fqdn, ".", "-"))
n := models.HANode{
ID: nodeID,
Name: fqdn,
@@ -602,12 +602,9 @@ func (h *ClusterHandler) AgentRegisterPeer(c *gin.Context) {
return
}
// Clean up the prenode-{fqdn} placeholder that preRegisterJoiner
// created during cert issuance — the real row just took its place.
placeholderID := fmt.Sprintf("prenode-%s", strings.ReplaceAll(req.FQDN, ".", "-"))
if placeholderID != req.ID {
_ = h.Store.Delete(c.Request.Context(), placeholderID)
}
// Remove ALL placeholder rows for this FQDN (both legacy "pre-{timestamp}"
// and current "prenode-{fqdn}" style) — the real row just took their place.
_ = h.Store.DeletePlaceholdersByFQDN(c.Request.Context(), req.FQDN, req.ID)
// Firewall-Reload damit peer_ipv4-Set die neue IP aufnimmt. Best-
// effort: Fehler loggen, Response weiter durchreichen — der Peer