agent: terminal backoff for dead credentials instead of retry loop
When ErrRefreshTokenInvalid or ErrMachineMismatch fires, the agent now waits 10 minutes between poll attempts instead of exponential backoff. These are permanent states — no amount of retrying fixes a dead refresh token or a machine_id mismatch. The agent stays alive and visible, waiting for operator intervention through the dashboard.
This commit is contained in:
parent
b017cbe222
commit
fcabaefe82
1 changed files with 11 additions and 3 deletions
|
|
@ -245,6 +245,7 @@ func RunPollingLoop(loopCtx *LoopContext) error {
|
|||
// Get commands from server
|
||||
response, err := ctx.APIClient.GetCommands(ctx.Cfg.AgentID, metrics)
|
||||
if err != nil {
|
||||
terminalBackoff := false
|
||||
if errors.Is(err, client.ErrMachineMismatch) {
|
||||
// Terminal: the server no longer recognizes this host as the one the
|
||||
// agent registered on — config moved or copied. Renewal can't fix it
|
||||
|
|
@ -253,6 +254,7 @@ func RunPollingLoop(loopCtx *LoopContext) error {
|
|||
// We keep polling rather than exit, so the agent stays visible and
|
||||
// self-heals the moment an operator rebinds it server-side.
|
||||
log.Printf("[ERROR] [agent] [auth] machine_id_mismatch identity_moved_or_copied re_registration_required agent_id=%s", ctx.Cfg.AgentID)
|
||||
terminalBackoff = true
|
||||
} else if errors.Is(err, client.ErrUnauthorized) && ctx.Cfg.RefreshToken != "" {
|
||||
log.Printf("[INFO] [agent] [auth] jwt_expired attempting_renewal agent_id=%s", ctx.Cfg.AgentID)
|
||||
renewErr := ctx.APIClient.RenewToken(ctx.Cfg.AgentID, ctx.Cfg.RefreshToken, version.Version)
|
||||
|
|
@ -277,15 +279,21 @@ func RunPollingLoop(loopCtx *LoopContext) error {
|
|||
// the agent needs re-registration. Surface it loudly; the client
|
||||
// already buffered a critical refresh_token_invalid event.
|
||||
log.Printf("[ERROR] [agent] [auth] refresh_token_invalid re_registration_required agent_id=%s error=%v", ctx.Cfg.AgentID, renewErr)
|
||||
terminalBackoff = true
|
||||
default:
|
||||
// Transient renewal failure (network, 502). Fall through to backoff and retry.
|
||||
log.Printf("[ERROR] [agent] [auth] token_renewal_failed error=%v", renewErr)
|
||||
}
|
||||
}
|
||||
consecutiveFailures++
|
||||
backoffDelay := calculateBackoff(consecutiveFailures, resolveBackoffBase(ctx.Cfg), resolveBackoffMax(ctx.Cfg))
|
||||
log.Printf("[WARNING] Server unavailable (attempt %d), retrying in %s: %v", consecutiveFailures, backoffDelay, err)
|
||||
|
||||
var backoffDelay time.Duration
|
||||
if terminalBackoff {
|
||||
backoffDelay = 10 * time.Minute
|
||||
log.Printf("[ERROR] [agent] [auth] terminal_state waiting_for_operator_intervention delay=%s agent_id=%s", backoffDelay, ctx.Cfg.AgentID)
|
||||
} else {
|
||||
backoffDelay = calculateBackoff(consecutiveFailures, resolveBackoffBase(ctx.Cfg), resolveBackoffMax(ctx.Cfg))
|
||||
log.Printf("[WARNING] Server unavailable (attempt %d), retrying in %s: %v", consecutiveFailures, backoffDelay, err)
|
||||
}
|
||||
// Non-blocking stop check during backoff
|
||||
if ctx.StopCh != nil {
|
||||
select {
|
||||
|
|
|
|||
Loading…
Reference in a new issue