Skip to content

test: gate sample-app DNS wait on ingress readiness (ARO-29937) - #7670

Open
Moises Cassidy (moisescassidy) wants to merge 1 commit into
Azure:mainfrom
moisescassidy:fix/sample-app-dns-readiness-gate
Open

Moises Cassidy (moisescassidy) wants to merge 1 commit into
Azure:mainfrom
moisescassidy:fix/sample-app-dns-readiness-gate

Conversation

@moisescassidy

@moisescassidy Moises Cassidy (moisescassidy) commented Oct 21, 2026 •

Copy link
Copy Markdown

ARO-29937

What

  • Gate the sample-app DNS wait on two readiness checks: the ingress ClusterOperator reporting Available=True (waitForClusterOperatorCondition), and openshift-ingress/router-default reporting a load-balancer entry with an assigned external IP (waitForRouterDefaultExternalIP). Both gates poll through the package's shared pollUntilReady, so they get its delta logging, elapsed reporting, and observation preservation across the deadline race.
  • On gate failure, name the actual blocker instead of surfacing it as DNS: the operator condition (reason/message), the missing external IP on timeout, the caller's context error reported distinctly as a cancellation rather than a timeout, and the last API error preserved when no condition or Service state was ever observed. The router gate also dumps the router-default diagnostics (Service, events, ingress operator conditions) when it times out, via pollUntilReady's diagnose hook.
  • Classify every failed DNS poll in WaitForDNSResolution (not-found vs. timeout/transient vs. other) and include the tally in the timeout error, so a timeout distinguishes "record not published yet" from "resolver not answering".

Why

This PR is to improve DNS/ingress readiness to prevent the verifySimpleWebApp from starting DNS resolution before published ingress is available. As of 10/27 this issue is now in INT and Prod.
During a Control Plane and Node Pool install the guest cluster apps route DNS never resolves (10m timeout).
This is due to verifySimpleWebApp starts its DNS wait right after deploying the app, but the DNS record is only published once ingress is Available and router-default has a load balancer IP.

Additional details below:
The teste2e-parallel presubmits fail ~1.5% of DEV runs with DNS for route host ... did not resolve within 10m0s (lookup ... on 172.30.0.10:53: i/o timeout). verifySimpleWebApp starts its DNS wait right after deploying the app, but the DNS record is only published once ingress is Available and router-default has a load balancer IP — a forming ingress therefore burns the whole DNS budget and the failure points at DNS instead of ingress readiness. Under the subscription-level ARM throttling caused by synchronized cluster creations, the guest cloud-controller-manager can take ~20 minutes to ensure the router-default load balancer (measured 20m03s from Service creation to "Ensured load balancer" in run 2104551230880616448).

Each readiness gate uses ingressReadinessTimeout = 25m — 2.5× the 10m DNS budget, sized above the 20m03s throttled LB-ensure — and polls at verifiers.DefaultPollInterval with a per-request 10s client timeout and a nil-config guard, so a single hung GET cannot consume the whole gate. The three waits run sequentially, so the verifier's worst-case wall clock grows 10m → ~60m, only on runs already failing; on healthy runs both gates pass on the first poll.

Testing

Unit tests for both gates via httptest fake API servers — happy path with exact request-path assertions, unavailable operator, missing condition, persistent API errors, interrupted requests preserving the last observation, gate timeout collecting router-default diagnostics, the gate clients' always-allow rate limiter, nil config, invalid interval (timeout and cancellation-between-polls pairing are inherited from pollUntilReady and pinned by poll_test.go), and caller cancellation — and for the DNS poll-outcome tally including nonzero, fully-classified poll counts.

  • Unit tests
  • Integration tests — not applicable: no test-integration surface is touched.
  • E2E tests — no new spec; the changed verifier runs as part of the existing sample-app specs in e2e-parallel presubmits.

gofmt, go build ./..., go vet ./... (including -tags E2Etests), go test ./util/framework/ ./util/verifiers/... (including -race), and golangci-lint on both changed packages pass.

Special notes for your reviewer

  • Cluster-creation start pacing is deliberately out of scope and ships as a separate PR (per review feedback and CONTRIBUTING.md scope guidance): this PR no longer changes creation-start timing, and the default-on pacing policy gets its own CI validation and sign-off there.
  • The unreachable in-cluster DNS (possibly ARO-30017) is still under investigation — this PR improves failure attribution, not the root cause; a run where ingress is ready and the resolver is still unreachable will now say so.

PR Checklist

  • PR is scoped to a single task (no mixed concerns)
  • Title follows Conventional Commits format
  • Summary explains the "Why" behind the change
  • Linked to relevant ticket/issue
  • Screenshots included (if dashboards or other UI changes) — not applicable, test-framework only
  • Self-reviewed the diff
  • CI/CD checks are passing (ignore Tide) — e2e-parallel pending on the split revision (the run on the pre-split head failed in environment provisioning before any test executed)
  • Draft PR used for WIP (if applicable) — not WIP
  • Commit history is clean (rebased/squashed)
  • Tricky code blocks are commented
  • Specific reviewers tagged
  • All comment threads resolved before merge

If E2E tests are included:

  • E2E tests follow Principles of Good E2E Test Case Design
  • If new E2E use case is covered (via a new test or new check/verifier), demonstrate that the test is able to detect a defect/error and fail with proper error message and logs which communicates nature of the problem — the readiness gates are new verifier checks whose unit tests assert the failure surfaces (operator condition reason/message, missing external IP, cancellation abort, persistent API error)

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings October 21, 2026 19:42
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification

This PR uses the pipeline controller for second-stage tests. Selection and triggering follow the repository configuration.

Use /test ? to list jobs and /pipeline help for commands.

@openshift-ci openshift-ci Bot added area/test Automatically applied by owners-label for area/test needs-ok-to-test labels Oct 21, 2026
@openshift-ci

openshift-ci Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Hi Moises Cassidy (@moisescassidy). Thanks for your PR.

I'm waiting for a Azure member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The router readiness gate can succeed without an assigned IP, starting the DNS wait prematurely.

1 open issue
What changed in this PR

Improves sample-app failure diagnosis by waiting for ingress readiness before starting the DNS timeout.

Changes:

  • Adds separate readiness waits for the ingress operator and router load balancer.
  • Adds fake-API unit tests for readiness transitions and timeout failures.
File Description
test/​util/​verifiers/​serving_app.go Gates DNS polling on ingress readiness.
test/​util/​verifiers/​serving_app_readiness_test.go Tests both readiness helpers.
test/​util/​verifiers/​clusteroperator.go Adds single-operator condition polling.

Review effort: Balanced

Comment thread test/util/verifiers/serving_app.go Outdated
Copilot AI balanced review requested due to automatic review settings October 22, 2026 23:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The available evidence does not fully establish approval readiness, and repository-level verification was unavailable.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 23, 2026 03:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The documented timeout budget materially understates the implemented sequential waits and must be reconciled before approval.

1 open issue

Review effort: Balanced

Comment thread test/util/verifiers/serving_app.go Outdated
Copilot AI balanced review requested due to automatic review settings October 23, 2026 04:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Lock acquisition can bypass cancellation and pacing deadlines, and leaked global test state causes repeated test executions to fail.

3 open issues

Review effort: Balanced

Comment thread test/util/framework/cluster_create_pacing.go Outdated
Comment thread test/util/framework/cluster_create_pacing_test.go Outdated
Copilot AI balanced review requested due to automatic review settings October 23, 2026 04:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Pacing enforcement gaps and a resolver-dependent test failure remain unresolved.

3 open issues
3 previously missed issues

In code that hasn't changed since last review

Medium severity RFC3339 formatting truncates fractional pacing timestamps

test/​util/​framework/​cluster_create_pacing.go:281

time.RFC3339 formatting drops fractional seconds, but the parser accepts subsecond windows. With 1/500ms, a start at 12:00:00.900 is stored as 12:00:00; an immediate second call treats it as expired and admits another start without waiting. Record timestamps with time.RFC3339Nano to preserve the configured window. The existing RFC3339 parser accepts fractional seconds. Add a regression case with a fractional-second start time.

Medium severity Use absolute DNS name to prevent search-suffix expansion

test/​util/​framework/​dns_test.go:182

Without a trailing dot, LookupHost can try configured DNS search suffixes. If a search domain has a wildcard record, aro-29937-reserved.invalid.<search-domain> can resolve, making this timeout test fail even though .invalid itself does not resolve. Use an absolute DNS name to prevent search-suffix expansion.

Medium severity Asynchronous cluster creation bypasses pacing

test/​util/​framework/​helpers_v20240610preview.go:1119

Pacing only this creation path leaves BeginCreateHCPCluster20240610 unpaced: it calls the SDK directly and is used for two starts in clusters_sharing_resgroup.go and another in admin_credential_lifecycle.go. Those starts are neither delayed nor recorded, so they can exceed the configured limit while the shared window is full. Apply pacing to the asynchronous helper too, and move admission ahead of any caller-created provisioning timeout so waiting does not consume that budget.

Review effort: Balanced

Moises Cassidy (moisescassidy) added a commit to moisescassidy/ARO-HCP that referenced this pull request Oct 24, 2026
…efault interval (ARO-29937)

Review follow-ups on PR Azure#7670:

- Pace HCP cluster-creation starts in BeginCreateHCPCluster20240610, which
  called the SDK directly and let three e2e starts bypass the pacer entirely;
  admission moves ahead of caller-armed provisioning timeouts via the exported
  framework.PaceHCPClusterCreateStart.
- Bound pacer lock acquisition (in-process mutex and cross-process flock) with
  non-blocking try-locks retried on a 250ms cadence: a stalled lock holder can
  neither stall a creation past maxClusterCreatePacingWait nor swallow context
  cancellation, and the pacing deadline is now shared with the admission wait.
- Record pacing starts as RFC3339Nano so a start at a fractional second keeps
  its precision; parsing already accepts fractional seconds, and stale pure
  RFC3339 records stay readable.
- Drop stared entries in the process-global pacedClusterCreates memo via
  t.Cleanup so repeated test execution (-count=2) does not bypass admission,
  with a regression test that a fractional-second start is not truncated.
- Make the DNS timeout-test hostname absolute (*.invalid.) so a wildcard DNS
  search suffix cannot satisfy the lookup.
- Poll the ingress readiness gates at verifiers.DefaultPollInterval per the
  verifier polling convention instead of a hardcoded 30s interval.
Copilot AI balanced review requested due to automatic review settings October 24, 2026 05:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Admission caching can bypass unfinished or cancelled waits, and the batching behavior differs from the advertised steady pacing.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity Cache admission state allows duplicate starts and persists failures

test/​util/​framework/​cluster_create_pacing.go:212

The cache marks a cluster as paced before admission completes, so a concurrent call for the same name can start creation while the first call is still waiting. If the first wait is cancelled, a later retry also bypasses pacing because the failed admission remains cached. Track the in-flight result, make duplicate callers wait for it, and remove entries when admission returns an error.

Medium severity Default pacing batches admissions instead of providing smooth refill

test/​util/​framework/​cluster_create_pacing.go:351

The default does not provide the advertised initial burst of 12 followed by roughly one start every 30 seconds. With 58 queued creations, this rule admits batches at 0, 6, 12, 18, and 24 minutes as timestamps expire together, retaining synchronized bring-up waves. Resolve the scheduling contract: if smooth pacing is intended, persist refill/next-admission state and add a backlog test with max > 1; otherwise, correct the PR description and default-setting comment to describe batching.

2 resolved since last review

Review effort: Balanced

@garrickdabbs

Copy link
Copy Markdown
Collaborator

/ok-to-test

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes mainly for the pacer semantics and admission memo.

The ingress/DNS readiness direction looks right, but the error handling and edge-case tests should be tightened. Non-blocking note: the 20m gate is just below the 20m03s measured recovery cited in the comment; consider 25m or a combined readiness poll.

Local focused tests, build, vet, and gofmt pass. Relevant Prow jobs were still pending when reviewed.

Comment thread test/util/framework/cluster_create_pacing.go Outdated
Comment thread test/util/framework/cluster_create_pacing.go Outdated
Comment thread test/util/verifiers/clusteroperator.go Outdated
Comment thread test/util/verifiers/clusteroperator.go Outdated
Comment thread test/util/verifiers/serving_app.go Outdated
Comment thread test/util/verifiers/serving_app_readiness_test.go
Moises Cassidy (moisescassidy) added a commit to moisescassidy/ARO-HCP that referenced this pull request Oct 26, 2026
… errors (ARO-29937)

Address PR Azure#7670 review feedback:

- Pacing refill smoothing: the sliding window alone re-admitted the next
  batch of max starts when the initial burst aged out together, so the
  documented "burst of 12, then one per 30s" contract did not hold. Persist
  a NextAdmission timestamp that, once the window has filled, spaces
  starts at least window/max apart, refilling freed capacity one start at
  a time. Backlog test with max > 1 asserts the 30s spacing.
- Singleflight admission memo: pacedClusterCreates marked a name paced
  before admission completed, so a concurrent same-name call started
  unpaced beside the in-flight wait and a retry after cancellation
  bypassed pacing entirely. Track the in-flight call, make duplicates
  wait for its result (a completed result wins over a cancelled caller
  context), and drop failed entries so retries re-pace. Concurrent
  same-name, cancel-then-retry, and follower-cancellation tests included.
- Readiness gate error surfaces: both gates now report caller-side
  cancellation as an abort (distinct from a gate timeout), preserve the
  last API error when no condition or Service state was ever observed
  (errors.Join with the wait error), and the operator gate gains the
  per-request 10s timeout and nil-config guard the Service gate already
  had. Cancellation, persistent-API-error, missing-condition, nil-config
  and invalid-timing tests added for both gates, plus exact request-path
  assertions; the DNS tally test now asserts a nonzero, fully classified
  poll count.
- ingressReadinessTimeout 20m -> 25m: the measured throttled recovery was
  20m03s, so a 20-minute gate would fail a replay of that exact run.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 18:52
@moisescassidy

Copy link
Copy Markdown
Author

/ok-to-test

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Security scan: no blocking findings. No .claude//.vscode/, CI/pipeline changes, or new executable scripts. This is all test code; no production service code is modified.

The earlier feedback is mostly addressed: readiness checks require an assigned IP, limits and cancellation/error reporting are explicit, asynchronous create is paced, memoization uses in-flight results and cluster identity, lock acquisition is bounded, fractional timestamps and smoothing are handled, and there is broad regression coverage. The timeout/runtime description is now consistent with the 25m + 25m + 10m sequential maximum (~60m). I consider those earlier findings resolved.

Remaining feedback

  1. Split scope (CONTRIBUTING.md:83-85). This PR combines ingress/DNS diagnosis (readiness gates and poll tally) with a separate, default-on, cross-process cluster-creation pacing mechanism. They address related symptoms, but can be reviewed and shipped independently. Please split the pacing into a separate PR, or explain why both must land together.

  2. Verify pacing behavior in its target CI. The ci/prow/e2e-parallel check is still pending. Since pacing changes create-start timing and is enabled by default, it is important to get that representative run green before merge. Other reported Prow checks are green; Tide is not a CI check.

  3. Clarify early-exit max-wait semantics. The README says waits exceeding 30m fail open, but the loop checks the deadline after tryRecordStart returns. If tryRecordStart records successfully after acquiring a contended lock beyond the deadline, it returns success before the fail-open check. Consider checking the deadline before committing the admission (or document that an admission that becomes available at the deadline can still proceed paced).

The default-on pacing policy and its estimated suite impact are described, but should get explicit CI-owner sign-off. The PR otherwise follows the title, rationale, tracking-ticket, and targeted-reviewer guidance in CONTRIBUTING.md. The remaining open review threads should be resolved or explicitly answered before merge.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

@mbukatov

Copy link
Copy Markdown
Collaborator

/assign mbukatov

@mbukatov

Martin Bukatovic (mbukatov) commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

I'm going to check the PR, but let me provide early feedback:

We have a PR template in the project, which this PR ignores. Having a single template helps us to synchronize on assumptions, and helps the review understand the scope and reasoning behind the PR. Could we rephrase the PR accordingly? Moreover the "why" section doesn't actually provide good reasoning for all the changes, but rather explain the issue.

I don't see any unit tests in the PR. Could we make sure we add unit tests and change the design so that the code unit testable as needed?

Moises Cassidy (moisescassidy) added a commit to moisescassidy/ARO-HCP that referenced this pull request Oct 27, 2026
Per review feedback on Azure#7670 (CONTRIBUTING.md scope guidance), the
default-on, cross-process cluster-creation pacing mechanism is reviewable
and shippable independently of the ingress/DNS readiness gates it was
diagnosed alongside. It now lives in its own PR; this branch keeps only
the readiness gates and the DNS poll tally.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 27, 2026 20:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Polling can mask the caller’s cancellation or deadline error after an unavailable observation, preventing errors.Is from recognizing context termination.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread test/util/verifiers/clusteroperator.go
Copilot AI balanced review requested due to automatic review settings October 27, 2026 20:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are identified for the ingress-readiness and DNS-diagnostics changes.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Count DNS timeouts when IsTemporary is false

test/​util/​framework/​dns.go:86

net.DNSError can have IsTimeout=true with IsTemporary=false; its Temporary() method still returns true in that case. This branch counts such a timeout as other, so the diagnostic can report zero timeout/transient failures for a timed-out lookup. Check IsTimeout as well, and add a timeout-only case to TestDNSPollTallyRecord.

Review effort: Balanced

@moisescassidy

Copy link
Copy Markdown
Author

Review summary

Security scan: no blocking findings. No .claude//.vscode/, CI/pipeline changes, or new executable scripts. This is all test code; no production service code is modified.

The earlier feedback is mostly addressed: readiness checks require an assigned IP, limits and cancellation/error reporting are explicit, asynchronous create is paced, memoization uses in-flight results and cluster identity, lock acquisition is bounded, fractional timestamps and smoothing are handled, and there is broad regression coverage. The timeout/runtime description is now consistent with the 25m + 25m + 10m sequential maximum (~60m). I consider those earlier findings resolved.

Remaining feedback

  1. Split scope (CONTRIBUTING.md:83-85). This PR combines ingress/DNS diagnosis (readiness gates and poll tally) with a separate, default-on, cross-process cluster-creation pacing mechanism. They address related symptoms, but can be reviewed and shipped independently. Please split the pacing into a separate PR, or explain why both must land together.
  2. Verify pacing behavior in its target CI. The ci/prow/e2e-parallel check is still pending. Since pacing changes create-start timing and is enabled by default, it is important to get that representative run green before merge. Other reported Prow checks are green; Tide is not a CI check.
  3. Clarify early-exit max-wait semantics. The README says waits exceeding 30m fail open, but the loop checks the deadline after tryRecordStart returns. If tryRecordStart records successfully after acquiring a contended lock beyond the deadline, it returns success before the fail-open check. Consider checking the deadline before committing the admission (or document that an admission that becomes available at the deadline can still proceed paced).

The default-on pacing policy and its estimated suite impact are described, but should get explicit CI-owner sign-off. The PR otherwise follows the title, rationale, tracking-ticket, and targeted-reviewer guidance in CONTRIBUTING.md. The remaining open review threads should be resolved or explicitly answered before merge.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

Moises Cassidy (moisescassidy) added a commit to moisescassidy/ARO-HCP that referenced this pull request Oct 28, 2026
e2e-parallel presubmits start dozens of cluster-creating specs within
seconds of each other; each reaches its ARM-heavy phase roughly ten
minutes later, and the synchronized wave saturates the subscription-level
ARM read quota. Under that throttling the guest cloud-controller-manager
cannot ensure the router-default load balancer for ~20 minutes
(ARO-29937: measured 20m03s from Service creation to "Ensured load
balancer"), which the sample-app verifier then misreports as a DNS
failure.

Pace HCP cluster-creation starts with ARO_HCP_E2E_CLUSTER_CREATE_PACING
("12/6m" default): a shared sliding window in an ARTIFACT_DIR state file
limits starts to max per trailing window across every spec subprocess of
the run, and a persisted next-admission timestamp spaces starts at least
window/max apart once the window has filled, so the capacity the initial
burst frees refills one start at a time instead of re-forming the wave.
The trailing window stays the hard cap.

The pacer fails open — it is storm mitigation, never a correctness gate:
state-file trouble, a lock that does not become available within the
pacing deadline, or an admission wait exceeding maxClusterCreatePacingWait
(30m) all proceed unpaced, with the deadline checked before each
admission attempt so no start is ever recorded past the bound. Only
context cancellation while waiting aborts the creation. Pacer lock
acquisition (in-process mutex and cross-process flock) is non-blocking
and deadline-bounded, so a stalled holder can neither stall a creation
nor swallow cancellation.

Admission is memoized per resource group and cluster name
singleflight-style: concurrent paces of the same cluster wait for the
in-flight admission, and a failed admission is dropped so a retry
re-paces. Pacing covers the synchronous CreateHCPClusterFromParam and
CreateHCPClusterAndWait helpers and the asynchronous
BeginCreateHCPCluster helpers; framework.PaceHCPClusterCreateStart lets
callers admit a start before arming their own provisioning timeout.

Split out of Azure#7670 per review feedback (CONTRIBUTING.md scope guidance):
the ingress/DNS readiness gates remain there; this change is the
default-on pacing policy and should get its own CI validation and
sign-off.

Unit tests cover parsing, admission, pruning, smoothing, the fail-open
bound (including capacity freeing past the deadline), lock contention
(mutex and flock), cancellation, and the memo's singleflight semantics,
run with -count=2 -race.

ARO-29937

Co-Authored-By: Claude Code <noreply@anthropic.com>
@moisescassidy
Moises Cassidy (moisescassidy) force-pushed the fix/sample-app-dns-readiness-gate branch from 796b237 to 2398bb3 Compare October 28, 2026 21:25
@openshift-ci

openshift-ci Bot commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: moisescassidy
Once this PR has been reviewed and has the lgtm label, please ask for approval from mbukatov. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

e2e-parallel presubmits fail ~1.5% of DEV runs with "DNS for route host ...
did not resolve within 10m0s": verifySimpleWebApp starts its DNS wait right
after deploying the app, but the DNS record is only published once ingress
is Available and router-default has a load balancer IP. Under the
subscription-level ARM throttling caused by synchronized cluster creations
the guest cloud-controller-manager can take ~20 minutes to ensure the
router-default load balancer (measured 20m03s in ARO-29937), so a forming
ingress burns the whole DNS budget and the failure points at DNS instead of
ingress readiness.

- Gate the DNS wait on the ingress ClusterOperator reporting Available=True
  and on openshift-ingress/router-default reporting a load-balancer entry
  with an assigned external IP, so an ingress with entries but no IP yet
  also keeps waiting. Both gates poll through the package's shared
  pollUntilReady (delta logging, elapsed reporting, cancellation-vs-timeout
  split, observation preservation across the deadline race), each with a 25m
  ingressReadinessTimeout sized above the 20m03s throttled LB-ensure, the
  default poll interval, a per-request 10s client timeout with a nil-config
  guard, and an always-allow rate limiter so a deadline-adjacent request
  cannot mask the last observation. On gate failure the verifier reports
  the actual blocker - the operator condition (reason/message), the missing
  external IP on timeout, the caller's context error reported as a
  cancellation, and the last API error preserved via errors.Join when no
  condition or Service state was ever observed - and a gate timeout dumps
  the router-default diagnostics (Service, events, ingress operator
  conditions) via pollUntilReady's diagnose hook.
- Tally DNS poll outcomes in WaitForDNSResolution (not-found vs.
  timeout/transient vs. other) and include the tally in the timeout error,
  so a timeout distinguishes "record not published yet" from "resolver not
  answering".
- Keep the caller's cancellation identifiable when the context ends between
  polls: an observation recorded while the context was still live is paired
  with the context's error on the cancelled exit (the same pairing the
  in-request interruption path uses), so errors.Is(err, ctx.Err()) keeps
  holding, while an error observed after the context had ended is retained
  alone so a genuine API failure is not re-classified as a cancellation.
- Unit tests via httptest fake API servers for both gates (happy path with
  exact request-path assertions, unavailable operator, missing condition,
  persistent API errors, nil config, invalid interval, interrupted requests
  preserving the last observation, gate timeout collecting router-default
  diagnostics, the gate clients' always-allow limiter, caller cancellation)
  and for the DNS poll-outcome tally including nonzero, fully-classified
  poll counts.

Cluster-creation start pacing is deliberately out of scope and ships as a
separate change (per review feedback and CONTRIBUTING.md scope guidance).

Link: https://redhat.atlassian.net/browse/ARO-29937

Co-Authored-By: Claude Code <noreply@anthropic.com>
@moisescassidy
Moises Cassidy (moisescassidy) force-pushed the fix/sample-app-dns-readiness-gate branch from 2398bb3 to c483b0d Compare October 28, 2026 22:51
Copilot AI balanced review requested due to automatic review settings October 28, 2026 22:51
@moisescassidy

Copy link
Copy Markdown
Author

/ok-to-test

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the ingress-readiness and DNS-diagnostics changes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-parallel

@moisescassidy

Copy link
Copy Markdown
Author

/retest-required

@openshift-ci

openshift-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Moises Cassidy (@moisescassidy): The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-parallel c483b0d link true /test e2e-parallel

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/test Automatically applied by owners-label for area/test ok-to-test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants