Fix: gate resource convergence on TLS issuance terminal state - #65
Merged
Conversation
A TLS port publishes no external address while its certificate is still issuing, but nothing held Converged back — the summary mirrored the workload's own convergence. The hub saw a live release with empty public URLs. The svc reconciler now files a not-ready verdict for the issuing stage, so the same tri-state that gates URL population gates convergence. The grace period still bounds it: a certificate that never resolves falls back to http:// and converges.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom (seen hub-side)
The hub observed a live release with empty public URLs — it bit the preview-comment flow, which reads
Status.ExternalAddressoff a converged resource.Root cause: ordering
svcReconcileralready computes a TLS tri-state (certIssuanceStageIssuing/Ready/Unavailable) and uses it to decide what to publish:Ready→https://addressUnavailable(cert-manager failure, or 2-minute grace period elapsed) →http://fallbackIssuing→ publish nothing, so a user is never handed an https URL serving Traefik's self-signed defaultBut that tri-state gated only URL population.
deriveSummaryStatussets the summaryStackResourceConvergedcondition by mirroringStackResourceWorkloadConvergedwhenever no verdict was filed — so a resource whose pods had rolled out flipped Converged=True whileExternalAddresswas still empty.StackResourceConvergedis the right thing to gate:internal/controller/stack/aggregate.gocounts children by that condition, and itsresourcesConvergedresult is what stampsStack.Status.LastConverged(revision + releaseID) — which is exactly what the hub'spkg/worker/release/converge.goandmodels.release_live_statusread to call a release live.The gate
One call in
svcReconciler.reconcile: theIssuingstage now files the existing retriable not-ready verdict, using the stage's own reason/message (CertificateIssuing).deriveNotReadythen writes Converged=False. No new timing logic, no duplicated state.It cannot wedge
The gate reuses
certGracePeriod(2 minutes), measured fromTLSConfigured'sLastTransitionTime. Once it elapsesclassifyCertificatereturnsUnavailable— http:// fallback, no verdict, convergence proceeds. The pre-existing deferred requeue wakes the reconciler at expiry, so a silently stalled certificate (which produces no Certificate watch event) still unblocks on time rather than waiting for an unrelated event.Only TLS-on-a-public-port resources are affected. No exposed port, no TLS on the port, or an unresolvable ClusterIssuer all yield a stage that is not
Issuing, so they converge exactly as before.Tests
internal/controller/stackresource/svc_reconciler_test.go, newDescribedriving the fullreconcilepass against a mocked client, each case seeded withWorkloadConverged=Trueso the gate is what decides:CertificateIssuing, no address, deferred requeue bounded by the grace periodhttps://addressFailedIssuanceAttempts > 0→ converged,http://addresshttp://addressVerification
go build ./...,go vet ./...cleanmake test-unit: only pre-existingpkg/portcheckfailures, which self-describe as environmental (they need a dial to192.0.2.1to hang; this network answers ICMP unreachable). Untouched by this change.reportNotReadyline removed and pass with it — it reproduces the bug.make lintnot run: the pinnedgolangci-lintv1.54.2 fails to typecheck this Go version repo-wide (pre-existing, unrelated to this diff).