Skip to content

OCPBUGS-82443: fix(cpo): deduplicate VPC endpoint subnets by AZ - #8651

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
reedcort:OCPBUGS-82443
Jun 11, 2026
Merged

OCPBUGS-82443: fix(cpo): deduplicate VPC endpoint subnets by AZ#8651
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
reedcort:OCPBUGS-82443

Conversation

@reedcort

@reedcort reedcort commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

When a HCP cluster has multiple NodePools with subnets in the same AWS availability zone, the CPO's VPC endpoint
reconciliation fails indefinitely with DuplicateSubnetsInSameZone. AWS VPC endpoints allow at most one subnet
per AZ, but listSubnetIDs() only deduplicates by subnet ID, not by AZ.

This PR adds AZ-aware subnet deduplication in the CPO's ensureVPCEndpoint path:

  • deduplicateSubnetsByAZ() — calls DescribeSubnets to resolve AZ membership, groups subnets by AZ, and
    picks one per AZ (lexicographically first for determinism)
  • In-memory cache — the subnet-to-AZ mapping is cached on the reconciler struct using a sync.RWMutex to
    avoid redundant DescribeSubnets calls on subsequent reconciles. The cache is rebuilt on CPO restart.
  • Graceful degradation — if DescribeSubnets fails (e.g. missing IAM permission), the controller proceeds
    with the original subnet list, preserving existing behavior
  • IAM policies — adds ec2:DescribeSubnets to the three CPO policies in iam.go. The ROSA-managed
    ROSAControlPlaneOperatorPolicy requires a separate update with AWS (tracked in ROSAENG-57993)

Files changed

File Change
control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go Add deduplicateSubnetsByAZ method, in-memory cache on reconciler, integrate in ensureVPCEndpoint
control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go 8 unit test cases
cmd/infra/aws/iam.go Add ec2:DescribeSubnets to 3 IAM policies

Which issue(s) this PR fixes:

Fixes OCPBUGS-82443

Related: ROSAENG-57993 (ROSA managed policy update)

Special notes for your reviewer:

  • The fix uses an in-memory cache instead of a Status field to simplify backporting (no API/CRD changes needed)
  • The cache is rebuilt from scratch on CPO restart (one DescribeSubnets call for ~2-3 subnets)
  • In SharedVPC mode, the CPO assumes the sharedVPCEndpointRole for all EC2 operations, so that role also needs ec2:DescribeSubnets
  • ROSA clusters using the AWS-managed ROSAControlPlaneOperatorPolicy won't get the fix until AWS adds
    ec2:DescribeSubnets to that policy — the graceful degradation ensures no regression

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 2, 2026
@openshift-ci

openshift-ci Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci-robot openshift-ci-robot added jira/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jun 2, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@reedcort: This pull request references Jira Issue OCPBUGS-82443, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

What this PR does / why we need it:

When a HCP cluster has multiple NodePools with subnets in the same AWS availability zone, the CPO's VPC endpoint
reconciliation fails indefinitely with DuplicateSubnetsInSameZone. AWS VPC endpoints allow at most one subnet
per AZ, but listSubnetIDs() only deduplicates by subnet ID, not by AZ.

This PR adds AZ-aware subnet deduplication in the CPO's ensureVPCEndpoint path:

  • deduplicateSubnetsByAZ() — calls DescribeSubnets to resolve AZ membership, groups subnets by AZ, and
    picks one per AZ (lexicographically first for determinism)
  • EndpointSubnetAZs status field — caches the subnet-to-AZ mapping to avoid redundant DescribeSubnets
    calls on subsequent reconciles (every 5 minutes)
  • Graceful degradation — if DescribeSubnets fails (e.g. missing IAM permission), the controller proceeds
    with the original subnet list, preserving existing behavior
  • IAM policies — adds ec2:DescribeSubnets to the three CPO policies in iam.go. The ROSA-managed
    ROSAControlPlaneOperatorPolicy requires a separate update with AWS

Files changed

File Change
api/hypershift/v1beta1/endpointservice_types.go Add EndpointSubnetAZs to Status
api/hypershift/v1beta1/endpointservice_types_test.go N-1/N+1 serialization compatibility test
control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go deduplicateSubnetsByAZ, integrate in ensureVPCEndpoint, clear cache on endpoint reset
control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go 9 unit test cases
cmd/infra/aws/iam.go Add ec2:DescribeSubnets to 3 IAM policies

Which issue(s) this PR fixes:

Fixes OCPBUGS-82443

Special notes for your reviewer:

  • The fix is in the CPO (not hypershift-operator) because it has the guest VPC credentials needed for DescribeSubnets
  • The deduplication mutates only the in-memory copy of Spec.SubnetIDs — the CPO never writes Spec back
  • ROSA clusters using the AWS-managed ROSAControlPlaneOperatorPolicy won't get the fix until AWS adds
    ec2:DescribeSubnets to that policy. The graceful degradation ensures no regression — the existing
    DuplicateSubnetsInSameZone error continues to surface as before

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

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 openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request introduces subnet-to-availability-zone (AZ) tracking for AWS VPC endpoints. The feature adds an EndpointSubnetAZs map field to the endpoint status, implements deduplication logic to ensure at most one subnet per AZ (selecting lexicographically), grants required IAM permissions for subnet discovery via EC2 API, and integrates the deduplication into the reconciliation loop. The new status field clears when an endpoint is not found or becomes invalid.

Sequence Diagram(s)

sequenceDiagram
    participant Controller
    participant deduplicateSubnetsByAZ
    participant AZCache
    participant EC2DescribeSubnets
    participant ReconciliationFlow

    Controller->>deduplicateSubnetsByAZ: Call with SubnetIDs + CachedAZs
    deduplicateSubnetsByAZ->>AZCache: Check cached AZ mappings
    alt Missing AZ mappings
        deduplicateSubnetsByAZ->>EC2DescribeSubnets: Query missing subnets
        EC2DescribeSubnets-->>deduplicateSubnetsByAZ: Return AZ data
    else All AZs cached
        deduplicateSubnetsByAZ->>deduplicateSubnetsByAZ: Use cache only
    end
    deduplicateSubnetsByAZ->>deduplicateSubnetsByAZ: Group by AZ, select lexicographic first
    deduplicateSubnetsByAZ->>deduplicateSubnetsByAZ: Prune stale cache entries
    deduplicateSubnetsByAZ-->>Controller: Return DeduplicatedIDs + UpdatedAZMap
    Controller->>ReconciliationFlow: Update Spec.SubnetIDs
    Controller->>ReconciliationFlow: Update Status.EndpointSubnetAZs
Loading

Suggested reviewers

  • csrwng
  • devguyio
  • Nirshal
🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: deduplicating VPC endpoint subnets by availability zone in the control-plane-operator, which directly addresses the root cause of the DuplicateSubnetsInSameZone failure mentioned in the PR objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PR contains only standard Go tests (testing.T), not Ginkgo tests. Custom check for Ginkgo test stability is not applicable to this PR.
Test Structure And Quality ✅ Passed PR introduces standard Go unit tests (testing.T), not Ginkgo tests. The custom check is specific to Ginkgo test code, making it not applicable to this PR.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies AWS VPC endpoint management, not Kubernetes pod scheduling. No pod affinity, topology spread, node selectors, or scheduling constraints are introduced.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No Ginkgo e2e tests added in this PR. The test files contain only standard Go unit tests (testing.T), not Ginkgo-based e2e tests. Check not applicable.
No-Weak-Crypto ✅ Passed No weak crypto found. PR adds subnet deduplication, status field, and IAM permissions with no MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB, custom crypto, or insecure comparison.
Container-Privileges ✅ Passed PR modifies only Go source and test files, not container/K8s manifests; no privileged container configurations detected.
No-Sensitive-Data-In-Logs ✅ Passed deduplicateSubnetsByAZ() has no logging; EndpointSubnetAZs field never logged; error handling avoids exposing sensitive data
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci Bot added area/api Indicates the PR includes changes for the API area/cli Indicates the PR includes changes for CLI area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release area/platform/aws PR/issue for AWS (AWSPlatform) platform and removed do-not-merge/needs-area labels Jun 2, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
cmd/infra/aws/iam.go (1)

679-680: Note the graceful degradation behavior for ROSA clusters.

The ec2:DescribeSubnets permission has been added to three CPO-managed policies. However, ROSA clusters using the AWS-managed ROSAControlPlaneOperatorPolicy will not receive this permission until AWS updates their managed policy. For these clusters, the controller will fall back to the original behavior (proceed with duplicate subnets, AWS rejects with DuplicateSubnetsInSameZone). This graceful degradation is intentional and preserves existing behavior until the AWS-managed policy is updated.

Also applies to: 706-707, 781-782

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/infra/aws/iam.go` around lines 679 - 680, Add a clear in-code comment
where the EC2 permissions list includes "ec2:DescribeSubnets" that explains ROSA
clusters using the AWS-managed ROSAControlPlaneOperatorPolicy will not
immediately receive this new permission until AWS updates their managed policy,
and that the controller intentionally falls back to the original behavior
(proceeding with duplicate subnets and allowing AWS to reject with
DuplicateSubnetsInSameZone) to preserve existing behavior; place the same
explanatory comment near the other two occurrences where "ec2:DescribeSubnets"
was added (the blocks corresponding to the other CPO-managed policies) so future
maintainers see the graceful-degradation note.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/hypershift/v1beta1/endpointservice_types_test.go`:
- Around line 87-95: The test is missing a check for SecurityGroupID when
round-tripping the N-1 struct; in the verification block that compares
roundTripped to tt.nMinus1Result (alongside EndpointServiceName, EndpointID, and
EndpointSubnetAZs), add an assertion that roundTripped.SecurityGroupID equals
tt.nMinus1Result.SecurityGroupID to ensure
awsEndpointServiceStatusNMinus1.SecurityGroupID is preserved during
deserialization into the current struct; place this check next to the existing
EndpointServiceName/EndpointID comparisons and use the same t.Errorf style for
mismatch reporting.

In `@api/hypershift/v1beta1/endpointservice_types.go`:
- Around line 95-100: Remove the restrictive validation on the EndpointSubnetAZs
field by deleting the +kubebuilder:validation:MinProperties=1 tag on the
EndpointSubnetAZs map in endpointservice_types.go; this allows the cache to
become empty (nil-equivalent) after pruning in deduplicateSubnetsByAZ
(awsprivatelink_controller.go) without failing validation, and adjust any
related comments if needed to reflect that an empty map is valid.

---

Nitpick comments:
In `@cmd/infra/aws/iam.go`:
- Around line 679-680: Add a clear in-code comment where the EC2 permissions
list includes "ec2:DescribeSubnets" that explains ROSA clusters using the
AWS-managed ROSAControlPlaneOperatorPolicy will not immediately receive this new
permission until AWS updates their managed policy, and that the controller
intentionally falls back to the original behavior (proceeding with duplicate
subnets and allowing AWS to reject with DuplicateSubnetsInSameZone) to preserve
existing behavior; place the same explanatory comment near the other two
occurrences where "ec2:DescribeSubnets" was added (the blocks corresponding to
the other CPO-managed policies) so future maintainers see the
graceful-degradation note.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: acf96909-54f8-477d-a418-510c4ac9c45b

📥 Commits

Reviewing files that changed from the base of the PR and between 1146767 and 3fc916c.

⛔ Files ignored due to path filters (5)
  • api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/awsendpointservices.hypershift.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/awsendpointservices.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/endpointservice_types.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (5)
  • api/hypershift/v1beta1/endpointservice_types.go
  • api/hypershift/v1beta1/endpointservice_types_test.go
  • cmd/infra/aws/iam.go
  • control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
  • control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go

Comment thread api/hypershift/v1beta1/endpointservice_types_test.go Outdated
Comment thread api/hypershift/v1beta1/endpointservice_types.go Outdated
@codecov

codecov Bot commented Jun 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.41558% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.47%. Comparing base (fce95fc) to head (45183ae).
⚠️ Report is 106 commits behind head on main.

Files with missing lines Patch % Lines
cmd/infra/aws/iam.go 0.00% 6 Missing ⚠️
...ollers/awsprivatelink/awsprivatelink_controller.go 91.54% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8651      +/-   ##
==========================================
+ Coverage   40.69%   41.47%   +0.78%     
==========================================
  Files         755      756       +1     
  Lines       93373    93721     +348     
==========================================
+ Hits        37994    38867     +873     
+ Misses      52646    52133     -513     
+ Partials     2733     2721      -12     
Files with missing lines Coverage Δ
cmd/infra/aws/iam.go 28.91% <0.00%> (-0.12%) ⬇️
...ollers/awsprivatelink/awsprivatelink_controller.go 38.54% <91.54%> (+4.20%) ⬆️

... and 47 files with indirect coverage changes

Flag Coverage Δ
cmd-support 34.87% <0.00%> (+0.16%) ⬆️
cpo-hostedcontrolplane 43.50% <ø> (+1.69%) ⬆️
cpo-other 43.02% <91.54%> (+1.63%) ⬆️
hypershift-operator 51.57% <ø> (+0.72%) ⬆️
other 31.64% <ø> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

SecurityGroupID string `json:"securityGroupID,omitempty"`

// endpointSubnetAZs maps subnet IDs used by the VPC endpoint to their
// availability zones. Used to avoid redundant DescribeSubnets calls.

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.

It makes more sense to define why we actually need this, something like "We need to keep track of which Availability Zones we have endpoints in, as AWS only supports 1 per AZ."

Comment thread cmd/infra/aws/iam.go
"ec2:DescribeSecurityGroups",
"ec2:DescribeVpcs"
"ec2:DescribeVpcs",
"ec2:DescribeSubnets"

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.

Can we confirm we need this for the sharedVPCPolicyBinding? I am not sure, just curious

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes — in SharedVPC mode the CPO assumes the sharedVPCEndpointRole for all EC2 operations.

return
}

func deduplicateSubnetsByAZ(ctx context.Context, ec2Client awsapi.EC2API, subnetIDs []string, cachedAZs map[string]string) ([]string, map[string]string, error) {

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.

There is a lot going on here, would be good to add a comment laying out the business logic a bit for future readers.

Comment on lines +587 to +589
if len(subnetIDs) <= 1 {
return subnetIDs, cachedAZs, nil
}

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.

If a cluster has 2 subnets, then goes down to 1, the cachedAZs would include the subnet that was removed, right? I can't think of a clean way to prevent that, but as soon as they add a second subnet, the dedupe logic would prune it from the cache. Generally, that's fine, but wanted to note it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah good callout — the <= 1 short-circuit skips pruning so the old entry lingers. Since it's just unused cache data in Status it does no actual harm. We could have it prune on every reconcile if we really don't want to have stale data in the status

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.

No worries, we want to keep the reconcile fast and no-op as much as possible, so I think given how unlikely it is to go from >1 subnet down to 1, it's fine.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I could foresee a future where customers start using additional subnets as a "testing ground", where they have a static cluster and then add a new machine pool and subnet for a day, then destroy it later. Would this cause an issue?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

With the new in-memory cache approach no. When the NodePool is deleted, the hypershift-operator removes that subnet from AWSEndpointService.Spec.SubnetIDs. The dedup function only looks at subnets in subnetIDs — the stale cache entry for the removed subnet is never read. The only effect is a few bytes of orphaned cache entries in memory, which clear on CPO restart.

@reedcort
reedcort force-pushed the OCPBUGS-82443 branch 2 times, most recently from dcdaf62 to 1a398ba Compare June 2, 2026 20:46
@openshift-ci openshift-ci Bot added the area/testing Indicates the PR includes changes for e2e testing label Jun 2, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/privatelink_subnet_dedup_test.go`:
- Around line 99-124: The cleanup loop currently creates waitCtx from the test's
ctx and breaks on any List error, so it can exit prematurely; change waitCtx to
be derived from context.Background() (e.g.,
context.WithTimeout(context.Background(), 3*time.Minute)) so test cancellation
doesn't abort cleanup, keep the defer cancel, and replace the unconditional
break on mgtClient.List error with retry logic: log the error and continue the
loop (or short backoff) so transient API errors don't stop waiting for
AWSEndpointServiceList items to be reconciled; keep using
AWSEndpointServiceList, mgtClient.List, waitCtx and newSubnetID to locate the
right objects and preserve the timeout check via waitCtx.Err().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: f4b7c384-2a40-4def-aa4a-12975eaa1e7c

📥 Commits

Reviewing files that changed from the base of the PR and between dcdaf62 and 1a398ba.

⛔ Files ignored due to path filters (5)
  • api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/awsendpointservices.hypershift.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/awsendpointservices.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/endpointservice_types.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (7)
  • api/hypershift/v1beta1/endpointservice_types.go
  • api/hypershift/v1beta1/endpointservice_types_test.go
  • cmd/infra/aws/iam.go
  • control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
  • control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
  • test/e2e/create_cluster_test.go
  • test/e2e/privatelink_subnet_dedup_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • api/hypershift/v1beta1/endpointservice_types.go
  • cmd/infra/aws/iam.go
  • control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
  • control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
  • api/hypershift/v1beta1/endpointservice_types_test.go

Comment thread test/e2e/privatelink_subnet_dedup_test.go Outdated
…SubnetsInSameZone

When a HCP cluster has multiple NodePools with subnets in the same AWS
availability zone, the CPO's VPC endpoint reconciliation fails with
DuplicateSubnetsInSameZone because AWS allows at most one subnet per AZ
per endpoint.

Add a deduplicateSubnetsByAZ method on the reconciler that calls
DescribeSubnets to resolve AZ membership, groups subnets by AZ, and
picks one per AZ (lexicographically first for determinism). The
subnet-to-AZ mapping is cached in an in-memory map on the reconciler
to avoid redundant AWS API calls across reconcile loops.

On DescribeSubnets failure the controller gracefully degrades by
proceeding with the original subnet list, preserving existing behavior.

Also adds ec2:DescribeSubnets to the three CPO IAM policies that lacked
it. The ROSA-managed ROSAControlPlaneOperatorPolicy requires a separate
update with AWS (tracked in ROSAENG-57993).

Signed-off-by: Cortney Reed <creed@redhat.com>
Commit-Message-Assisted-by: Claude (via Claude Code)
@reedcort
reedcort marked this pull request as ready for review June 5, 2026 17:20
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 5, 2026
@openshift-ci
openshift-ci Bot requested review from bryan-cox and sdminonne June 5, 2026 17:20
@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jun 8, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@reedcort: This pull request references Jira Issue OCPBUGS-82443, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

/jira refresh

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 openshift-eng/jira-lifecycle-plugin repository.

@Nirshal

Nirshal commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jun 9, 2026
@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-aks
/test e2e-aws
/test e2e-aws-upgrade-hypershift-operator
/test e2e-azure-self-managed
/test e2e-azure-v2-self-managed
/test e2e-kubevirt-aws-ovn-reduced
/test e2e-v2-aws
/test e2e-v2-gke

@Nirshal

Nirshal commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

/assign @sjenning

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor

Test Failure Analysis Complete

Job Information

  • Prow Job: pull-ci-openshift-hypershift-main-e2e-aws
  • Build ID: 2064257294132056064
  • Target: e2e-aws
  • Result: 575 tests, 29 skipped, 11 failures (3 unique leaf failures across 3 independent hosted clusters)

Test Failure Analysis

Error

1. TestAutoscaling/Main/TestAutoscalerRespectsNodePoolPause (45.04s):
   Post "https://api-autoscaling-tjdnp.service.ci.hypershift.devcluster.openshift.com:443/apis/batch/v1/namespaces/default/jobs": http2: client connection lost

2. TestKarpenter/Main/Billing_vCPUs,_consolidation,_and_cluster_deletion_with_blocking_PDB (840.24s):
   Post "https://api-karpenter-kjjh4.service.ci.hypershift.devcluster.openshift.com:443/apis/policy/v1/namespaces/default/poddisruptionbudgets": http2: client connection lost

3. TestCreateCluster/Main/EnsureGlobalPullSecret/When_management-cluster_hostedCluster.Spec.PullSecret_is_updated_in-place_it_should_propagate_to_guest_without_rollout (1205.08s):
   failed to wait for DaemonSet global-pull-secret-syncer to be ready: context deadline exceeded
   (DaemonSet stuck at 2/3 pods ready for the entire timeout period)

4. TestCreateCluster/Main/EnsureGlobalPullSecret/Check_if_the_config.json_is_correct_in_all_of_the_nodes (0.02s):
   daemonsets.apps "kubelet-config-verifier" already exists (cascade failure from #3)

Summary

All 3 test failures are unrelated to the PR changes and represent pre-existing flaky test behavior. The PR modifies awsprivatelink_controller.go (VPC endpoint subnet AZ deduplication) and iam.go (adds ec2:DescribeSubnets permission) — neither code path is exercised by the failing tests. Critically, both TestCreateClusterPrivate and TestCreateClusterPrivateWithRouteKAS — the tests that actually exercise the PR's PrivateLink code — passed successfully. The failures are: (1) transient HTTP/2 connection drops to two independent hosted cluster API servers (autoscaling-tjdnp and karpenter-kjjh4), and (2) a global-pull-secret-syncer DaemonSet that could only schedule 2 of 3 pods, timing out after ~20 minutes. All three hosted clusters reported valid conditions with no unexpected operator degradation.

Root Cause

Failure 1 & 2 — http2: client connection lost (TestAutoscaling, TestKarpenter):
These are transient HTTP/2 connection drops between the test client and the hosted cluster kube-apiservers. Each test uses a completely separate hosted cluster (autoscaling-tjdnp on cluster e2e-clusters-ms989, karpenter-kjjh4 on cluster e2e-clusters-b6h2k). The connection loss occurs during API POST calls (creating a Job and a PodDisruptionBudget respectively). This is a known pattern of CI infrastructure flakiness — the hosted cluster API servers are accessed via service.ci.hypershift.devcluster.openshift.com endpoints, and transient network disruptions between the CI pod and these endpoints cause HTTP/2 connections to drop. The hosted cluster conditions were all valid (no unexpected conditions), confirming the clusters themselves were healthy.

Failure 3 — global-pull-secret-syncer DaemonSet timeout (TestCreateCluster):
The global-pull-secret-syncer DaemonSet in the create-cluster-gjhs5 hosted cluster could only achieve 2/3 pod readiness. The DaemonSet requires one pod per node (3 nodes), but one pod could never reach ready state. This ran for the full 20-minute timeout before failing. The root cause is likely a node-level scheduling or readiness issue on one of the three worker nodes — the third pod could not schedule or pass its readiness probe. This is a known intermittent issue in CI environments.

Failure 4 — kubelet-config-verifier already exists (TestCreateCluster, cascade):
This is a direct cascade from Failure 3. The prior subtest (When_management-cluster...) left the kubelet-config-verifier DaemonSet behind (created during its execution but never cleaned up due to the timeout). The next subtest (Check_if_the_config.json...) tried to create the same DaemonSet and got a 409 Conflict. This is a test isolation issue in the EnsureGlobalPullSecret test suite.

No relation to PR #8651: The PR changes awsprivatelink_controller.go and iam.go — both PrivateLink-specific code paths. The tests that exercise these paths (TestCreateClusterPrivate, TestCreateClusterPrivateWithRouteKAS) both passed. None of the failing tests (autoscaling, Karpenter, global pull secret) invoke any AWS PrivateLink or VPC endpoint code.

Recommendations
  1. Re-trigger the e2e-aws job — all failures are transient/flaky and unrelated to the PR. A /retest should pass.
  2. No code changes needed — the PR's functional tests (TestCreateClusterPrivate, TestCreateClusterPrivateWithRouteKAS) both passed, confirming the VPC endpoint subnet deduplication logic works correctly.
  3. Existing flakiness to track separately:
    • The http2: client connection lost pattern in TestAutoscaling and TestKarpenter is a recurring CI infrastructure issue with hosted cluster API connectivity.
    • The global-pull-secret-syncer DaemonSet readiness timeout (2/3 pods) suggests intermittent node-level issues in the CI cluster.
    • The kubelet-config-verifier already exists cascade indicates the EnsureGlobalPullSecret test suite could benefit from better cleanup between subtests.
Evidence
Evidence Detail
PR changed files cmd/infra/aws/iam.go, control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go, awsprivatelink_controller_test.go
PR-relevant tests PASSED TestCreateClusterPrivate (1597s), TestCreateClusterPrivateWithRouteKAS (1757s)
TestAutoscaling failure http2: client connection lost on POST to api-autoscaling-tjdnp... (batch/v1 jobs endpoint)
TestKarpenter failure http2: client connection lost on POST to api-karpenter-kjjh4... (policy/v1 PDB endpoint)
TestCreateCluster failure global-pull-secret-syncer stuck at 2/3 pods ready for ~20min, then context deadline exceeded
Hosted cluster health All 3 hosted clusters had valid conditions — no unexpected operator degradation
Overall test results 575 tests, 29 skipped, 11 failures (3 unique leaf failures), 535 passed
Recent main merge (PR #8489) e2e-aws passed — same job is not systematically broken
Failure isolation 3 independent hosted clusters with 3 independent failure modes, none involving PrivateLink code

@reedcort

reedcort commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

/test e2e-aws
/test e2e-v2-gke

@bryan-cox bryan-cox left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/approve

@openshift-ci

openshift-ci Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bryan-cox, reedcort

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

The pull request process is described 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-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 10, 2026
@reedcort

Copy link
Copy Markdown
Contributor Author

Test Evidence

Tested on a ROSA HCP staging cluster with two subnets in the same AZ (us-east-2a).

AWSEndpointService spec shows both subnets:

subnetIDs: ["subnet-004ce799aaae2a8cc","subnet-08ff0d0fd8d9988d9"]

Before — graceful degradation without ec2:DescribeSubnets in managed policy

The CPO attempts to deduplicate but DescribeSubnets is denied. It falls back to the original subnet list, and ModifyVpcEndpoint fails with DuplicateSubnetsInSameZone. This is the existing fallback behavior — no regression when the ROSA managed policy hasn't been updated yet.

{"level":"error","ts":"2026-06-11T13:40:26Z","msg":"failed to deduplicate subnets by AZ, proceeding with original list","controller":"awsendpointservice","controllerKind":"AWSEndpointService","name":"private-router","error":"failed to describe subnets for AZ deduplication: operation error EC2: DescribeSubnets, https response error StatusCode: 403, api error UnauthorizedOperation: You are not authorized to perform this operation."}
{"level":"error","ts":"2026-06-11T13:40:27Z","msg":"failed to modify vpc endpoint","controller":"awsendpointservice","controllerKind":"AWSEndpointService","name":"private-router","id":"vpce-0bd1027432e3e1746","addSubnets":["subnet-08ff0d0fd8d9988d9"],"removeSubnets":[],"addSG":[],"error":"operation error EC2: ModifyVpcEndpoint, https response error StatusCode: 400, api error DuplicateSubnetsInSameZone: Found another VPC endpoint subnet in the availability zone of subnet-08ff0d0fd8d9988d9."}

Condition:

AWSEndpointAvailable=False  failed to modify vpc endpoint: DuplicateSubnetsInSameZone

After — with ec2:DescribeSubnets added to the CPO IAM role

After adding ec2:DescribeSubnets to the CPO role, the dedup resolves both subnets to us-east-2a, picks one, and the endpoint reconciles successfully.

{"level":"info","ts":"2026-06-11T13:46:28Z","msg":"endpoint exists","controller":"awsendpointservice","controllerKind":"AWSEndpointService","name":"private-router","endpointID":"vpce-0bd1027432e3e1746"}
{"level":"info","ts":"2026-06-11T13:46:28Z","msg":"endpoint subnets are unchanged","controller":"awsendpointservice","controllerKind":"AWSEndpointService","name":"private-router"}

Condition:

AWSEndpointAvailable=True

@reedcort

Copy link
Copy Markdown
Contributor Author

/verified by @reedcort — tested on ROSA HCP staging cluster with two subnets in same AZ

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Jun 11, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@reedcort: This PR has been marked as verified by @reedcort — tested on ROSA HCP staging cluster with two subnets in same AZ.

Details

In response to this:

/verified by @reedcort — tested on ROSA HCP staging cluster with two subnets in same AZ

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci

openshift-ci Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

@reedcort: all tests passed!

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.

@openshift-merge-bot
openshift-merge-bot Bot merged commit 2f6b004 into openshift:main Jun 11, 2026
42 checks passed
@openshift-ci-robot

Copy link
Copy Markdown

@reedcort: Jira Issue Verification Checks: Jira Issue OCPBUGS-82443
✔️ This pull request was pre-merge verified.
✔️ All associated pull requests have merged.
✔️ All associated, merged pull requests were pre-merge verified.

Jira Issue OCPBUGS-82443 has been moved to the MODIFIED state and will move to the VERIFIED state when the change is available in an accepted nightly payload. 🕓

Details

In response to this:

What this PR does / why we need it:

When a HCP cluster has multiple NodePools with subnets in the same AWS availability zone, the CPO's VPC endpoint
reconciliation fails indefinitely with DuplicateSubnetsInSameZone. AWS VPC endpoints allow at most one subnet
per AZ, but listSubnetIDs() only deduplicates by subnet ID, not by AZ.

This PR adds AZ-aware subnet deduplication in the CPO's ensureVPCEndpoint path:

  • deduplicateSubnetsByAZ() — calls DescribeSubnets to resolve AZ membership, groups subnets by AZ, and
    picks one per AZ (lexicographically first for determinism)
  • In-memory cache — the subnet-to-AZ mapping is cached on the reconciler struct using a sync.RWMutex to
    avoid redundant DescribeSubnets calls on subsequent reconciles. The cache is rebuilt on CPO restart.
  • Graceful degradation — if DescribeSubnets fails (e.g. missing IAM permission), the controller proceeds
    with the original subnet list, preserving existing behavior
  • IAM policies — adds ec2:DescribeSubnets to the three CPO policies in iam.go. The ROSA-managed
    ROSAControlPlaneOperatorPolicy requires a separate update with AWS (tracked in ROSAENG-57993)

Files changed

File Change
control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go Add deduplicateSubnetsByAZ method, in-memory cache on reconciler, integrate in ensureVPCEndpoint
control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go 8 unit test cases
cmd/infra/aws/iam.go Add ec2:DescribeSubnets to 3 IAM policies

Which issue(s) this PR fixes:

Fixes OCPBUGS-82443

Related: ROSAENG-57993 (ROSA managed policy update)

Special notes for your reviewer:

  • The fix uses an in-memory cache instead of a Status field to simplify backporting (no API/CRD changes needed)
  • The cache is rebuilt from scratch on CPO restart (one DescribeSubnets call for ~2-3 subnets)
  • In SharedVPC mode, the CPO assumes the sharedVPCEndpointRole for all EC2 operations, so that role also needs ec2:DescribeSubnets
  • ROSA clusters using the AWS-managed ROSAControlPlaneOperatorPolicy won't get the fix until AWS adds
    ec2:DescribeSubnets to that policy — the graceful degradation ensures no regression

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

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 openshift-eng/jira-lifecycle-plugin repository.

@reedcort

Copy link
Copy Markdown
Contributor Author

/cherry-pick release-4.22
/cherry-pick release-4.21
/cherry-pick release-4.20

@openshift-cherrypick-robot

Copy link
Copy Markdown

@reedcort: #8651 failed to apply on top of branch "release-4.20":

Applying: fix(cpo): deduplicate VPC endpoint subnets by AZ to prevent DuplicateSubnetsInSameZone
Using index info to reconstruct a base tree...
M	cmd/infra/aws/iam.go
M	control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
M	control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
Falling back to patching base and 3-way merge...
Auto-merging cmd/infra/aws/iam.go
Auto-merging control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
CONFLICT (content): Merge conflict in control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
Auto-merging control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 fix(cpo): deduplicate VPC endpoint subnets by AZ to prevent DuplicateSubnetsInSameZone

Details

In response to this:

/cherry-pick release-4.22
/cherry-pick release-4.21
/cherry-pick release-4.20

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.

@openshift-cherrypick-robot

Copy link
Copy Markdown

@reedcort: #8651 failed to apply on top of branch "release-4.21":

Applying: fix(cpo): deduplicate VPC endpoint subnets by AZ to prevent DuplicateSubnetsInSameZone
Using index info to reconstruct a base tree...
M	cmd/infra/aws/iam.go
M	control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
M	control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
Falling back to patching base and 3-way merge...
Auto-merging cmd/infra/aws/iam.go
Auto-merging control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
CONFLICT (content): Merge conflict in control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
Auto-merging control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 fix(cpo): deduplicate VPC endpoint subnets by AZ to prevent DuplicateSubnetsInSameZone

Details

In response to this:

/cherry-pick release-4.22
/cherry-pick release-4.21
/cherry-pick release-4.20

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.

@openshift-cherrypick-robot

Copy link
Copy Markdown

@reedcort: #8651 failed to apply on top of branch "release-4.22":

Applying: fix(cpo): deduplicate VPC endpoint subnets by AZ to prevent DuplicateSubnetsInSameZone
Using index info to reconstruct a base tree...
M	control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
M	control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
Falling back to patching base and 3-way merge...
Auto-merging control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
CONFLICT (content): Merge conflict in control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller.go
Auto-merging control-plane-operator/controllers/awsprivatelink/awsprivatelink_controller_test.go
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 fix(cpo): deduplicate VPC endpoint subnets by AZ to prevent DuplicateSubnetsInSameZone

Details

In response to this:

/cherry-pick release-4.22
/cherry-pick release-4.21
/cherry-pick release-4.20

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.

@openshift-merge-robot

Copy link
Copy Markdown
Contributor

Fix included in release 5.0.0-0.nightly-2026-06-12-141614

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/api Indicates the PR includes changes for the API area/cli Indicates the PR includes changes for CLI area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release area/platform/aws PR/issue for AWS (AWSPlatform) platform area/testing Indicates the PR includes changes for e2e testing jira/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants