From 916485e119a28916d864edcd567384f1aaaca6b8 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Sat, 11 Oct 2025 10:49:05 +0200 Subject: [PATCH] Fix retry on error Signed-off-by: Bryan Frimin --- pkg/certmanager/provisioner.go | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/pkg/certmanager/provisioner.go b/pkg/certmanager/provisioner.go index caaaee759..4b0e949bd 100644 --- a/pkg/certmanager/provisioner.go +++ b/pkg/certmanager/provisioner.go @@ -17,6 +17,7 @@ package certmanager import ( "context" "fmt" + "strings" "time" "github.com/getprobo/probo/pkg/coredata" @@ -111,6 +112,44 @@ func (p *Provisioner) checkPendingDomains(ctx context.Context) error { ) } +func isChallengeFailedError(err error) bool { + if err == nil { + return false + } + + errStr := strings.ToLower(err.Error()) + + // These errors indicate the challenge/order is no longer valid + return strings.Contains(errStr, "authorization must be pending") || + strings.Contains(errStr, "order") && strings.Contains(errStr, "invalid") || + strings.Contains(errStr, "authorization") && strings.Contains(errStr, "invalid") || + strings.Contains(errStr, "challenge") && strings.Contains(errStr, "invalid") +} + +func (p *Provisioner) resetDomainToRetry( + ctx context.Context, + conn pg.Conn, + domain *coredata.CustomDomain, +) error { + fullDomain := &coredata.CustomDomain{} + if err := fullDomain.LoadByIDForUpdate(ctx, conn, coredata.NewNoScope(), p.encryptionKey, domain.ID); err != nil { + return fmt.Errorf("cannot load domain for update: %w", err) + } + + fullDomain.HTTPChallengeToken = nil + fullDomain.HTTPChallengeKeyAuth = nil + fullDomain.HTTPChallengeURL = nil + fullDomain.HTTPOrderURL = nil + + fullDomain.SSLStatus = coredata.CustomDomainSSLStatusPending + + if err := fullDomain.Update(ctx, conn, coredata.NewNoScope(), p.encryptionKey); err != nil { + return fmt.Errorf("cannot update domain: %w", err) + } + + return nil +} + func (p *Provisioner) provisionDomainCertificate( ctx context.Context, conn pg.Conn, @@ -172,6 +211,32 @@ func (p *Provisioner) provisionDomainCertificate( log.Error(err), ) + // Check if the error indicates the challenge/order has failed + // and needs to be reset for a fresh attempt + if isChallengeFailedError(err) { + p.logger.InfoCtx( + ctx, + "challenge or order is no longer valid, resetting domain to retry with fresh challenge", + log.String("domain", domain.Domain), + ) + + if resetErr := p.resetDomainToRetry(ctx, conn, domain); resetErr != nil { + p.logger.ErrorCtx( + ctx, + "cannot reset domain for retry", + log.String("domain", domain.Domain), + log.Error(resetErr), + ) + return resetErr + } + + p.logger.InfoCtx( + ctx, + "domain reset to pending, will retry with new challenge on next cycle", + log.String("domain", domain.Domain), + ) + } + return nil }