Skip to content

MGMT-24693: Normalize unbracketed IPv6 ignition endpoint URLs before …#10570

Draft
andrej1991 wants to merge 3 commits into
openshift:masterfrom
andrej1991:ipv6UrlFormating
Draft

MGMT-24693: Normalize unbracketed IPv6 ignition endpoint URLs before …#10570
andrej1991 wants to merge 3 commits into
openshift:masterfrom
andrej1991:ipv6UrlFormating

Conversation

@andrej1991

@andrej1991 andrej1991 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

…validation

The edge CAPI disconnected test
pull-ci-openshift-assisted-service-master-edge-e2e-ai-operator-disconnected-capi started failing after PR #10396 upgraded assisted-service to Go 1.26.

Go 1.26 tightened net/url.Parse: URLs with an unbracketed IPv6 host and port are now rejected (urlstrictcolons). Hypershift builds ignition endpoints as host:port without brackets (e.g. fd2e:6f44:5dd8:c956::14:31187), and cluster-api-provider-agent copies that into AgentClusterInstall. The operator then syncs the URL to the backend, where ValidateHTTPFormat fails:

parse "https://fd2e:6f44:5dd8:c956::14:31187": invalid port
":6f44:5dd8:c956::14:31187" after host

That surfaces as ACI SpecSynced=False (InputError), the worker agent stays insufficient (ignition-downloadable pending), and the test times out waiting for a day-2 worker node. The same IPv6 lab and URL format passed on Go 1.25 (e.g. PR #10319, Jun 2026); the regression correlates with the toolchain bump, not with the OCP 5.0 payload shift.

Add NormalizeHTTPURL to bracket IPv6 literal hosts via net.JoinHostPort. Apply it in ValidateHTTPFormat and in parseIgnitionEndpoint so URLs from ACI are normalized before API validation and storage.

The root cause is upstream in Hypershift URL construction; this change is a defensive fix on the assisted-service side. A companion fix in cluster-api-provider-agent normalizes the URL when writing ACI.

List all the issues related to this PR

  • New Feature
  • Enhancement
  • Bug fix
  • Tests
  • Documentation
  • CI/CD

What environments does this code impact?

  • Automation (CI, tools, etc)
  • Cloud
  • Operator Managed Deployments
  • None

How was this code tested?

  • assisted-test-infra environment
  • dev-scripts environment
  • Reviewer's test appreciated
  • Waiting for CI to do a full test run
  • Manual (Elaborate on how it was tested)
  • No tests needed

Checklist

  • Title and description added to both, commit and PR.
  • Relevant issues have been associated (see CONTRIBUTING guide)
  • This change does not require a documentation update (docstring, docs, README, etc)
  • Does this change include unit-tests (note that code changes require unit-tests)

Reviewers Checklist

  • Are the title and description (in both PR and commit) meaningful and clear?
  • Is there a bug required (and linked) for this change?
  • Should this PR be backported?

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of HTTP/HTTPS ignition endpoint URLs that use unbracketed IPv6 literals by normalizing them before validation, parsing, storage, and ignition URL generation (including with or without paths).
  • New Features
    • Added retryable execution for disconnected image mirroring steps to better handle intermittent mirror failures.
  • Tests
    • Added unit and Ginkgo coverage for IPv6 URL normalization and expanded valid URL test cases.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 1, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 1, 2026

Copy link
Copy Markdown

@andrej1991: This pull request references MGMT-24693 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

…validation

The edge CAPI disconnected test
pull-ci-openshift-assisted-service-master-edge-e2e-ai-operator-disconnected-capi started failing after PR #10396 upgraded assisted-service to Go 1.26.

Go 1.26 tightened net/url.Parse: URLs with an unbracketed IPv6 host and port are now rejected (urlstrictcolons). Hypershift builds ignition endpoints as host:port without brackets (e.g. fd2e:6f44:5dd8:c956::14:31187), and cluster-api-provider-agent copies that into AgentClusterInstall. The operator then syncs the URL to the backend, where ValidateHTTPFormat fails:

parse "https://fd2e:6f44:5dd8:c956::14:31187": invalid port
":6f44:5dd8:c956::14:31187" after host

That surfaces as ACI SpecSynced=False (InputError), the worker agent stays insufficient (ignition-downloadable pending), and the test times out waiting for a day-2 worker node. The same IPv6 lab and URL format passed on Go 1.25 (e.g. PR #10319, Jun 2026); the regression correlates with the toolchain bump, not with the OCP 5.0 payload shift.

Add NormalizeHTTPURL to bracket IPv6 literal hosts via net.JoinHostPort. Apply it in ValidateHTTPFormat and in parseIgnitionEndpoint so URLs from ACI are normalized before API validation and storage.

The root cause is upstream in Hypershift URL construction; this change is a defensive fix on the assisted-service side. A companion fix in cluster-api-provider-agent normalizes the URL when writing ACI.

List all the issues related to this PR

  • New Feature
  • Enhancement
  • Bug fix
  • Tests
  • Documentation
  • CI/CD

What environments does this code impact?

  • Automation (CI, tools, etc)
  • Cloud
  • Operator Managed Deployments
  • None

How was this code tested?

  • assisted-test-infra environment
  • dev-scripts environment
  • Reviewer's test appreciated
  • Waiting for CI to do a full test run
  • Manual (Elaborate on how it was tested)
  • No tests needed

Checklist

  • Title and description added to both, commit and PR.
  • Relevant issues have been associated (see CONTRIBUTING guide)
  • This change does not require a documentation update (docstring, docs, README, etc)
  • Does this change include unit-tests (note that code changes require unit-tests)

Reviewers Checklist

  • Are the title and description (in both PR and commit) meaningful and clear?
  • Is there a bug required (and linked) for this change?
  • Should this PR be backported?

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 added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 1, 2026
@openshift-ci

openshift-ci Bot commented Jul 1, 2026

Copy link
Copy Markdown

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

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6c9bffd0-4f76-4254-bbac-3016f2be4d78

📥 Commits

Reviewing files that changed from the base of the PR and between fd6c432 and 213bb6c.

📒 Files selected for processing (3)
  • deploy/operator/capi/deploy_capi_cluster.sh
  • deploy/operator/mirror_utils.sh
  • deploy/operator/setup_hive.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • deploy/operator/mirror_utils.sh

Walkthrough

The PR normalizes unbracketed IPv6 HTTP URLs for ignition endpoint handling and updates disconnected operator mirroring commands to run through a retry wrapper.

Changes

IPv6 URL normalization

Layer / File(s) Summary
Normalization helper and validation
pkg/validations/validations.go, pkg/validations/validations_test.go
Adds NormalizeHTTPURL, applies it before HTTP format parsing, and extends validation tests for unbracketed IPv6 inputs.
Ignition endpoint consumers
internal/controller/controllers/clusterdeployments_controller.go, internal/bminventory/inventory.go, internal/host/hostutil/host_utils.go, internal/bminventory/inventory_ignition_endpoint_unit_test.go, internal/host/hostutil/host_utils_ignition_url_test.go, internal/host/hostutil/host_utils_test.go
Normalizes Ignition endpoint URLs before storing, validating, or parsing them, with tests covering unbracketed IPv6 endpoint handling.

Mirror command retries

Layer / File(s) Summary
Retry helper implementation
deploy/operator/mirror_utils.sh
Adds output-based mirror failure detection, command-name logging, and a retry wrapper for mirror commands.
Mirror call sites
deploy/operator/setup_hive.sh, deploy/operator/capi/deploy_capi_cluster.sh
Sources the helper and routes disconnected image, catalog, release, and isc mirror commands through the retry wrapper.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MirrorCaller
  participant run_mirror_command_with_retry
  participant mirror_command_succeeded
  participant MirrorCommand
  MirrorCaller->>run_mirror_command_with_retry: mirror command
  run_mirror_command_with_retry->>MirrorCommand: execute and tee output
  MirrorCommand-->>run_mirror_command_with_retry: exit status and log output
  run_mirror_command_with_retry->>mirror_command_succeeded: inspect output for failures
  mirror_command_succeeded-->>run_mirror_command_with_retry: success or failure
  run_mirror_command_with_retry-->>MirrorCaller: return after success or retries
Loading
🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change by calling out IPv6 ignition endpoint URL normalization.
Description check ✅ Passed The description includes motivation, context, issue reference, and testing notes, and it mostly follows the template.
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 New/changed test titles are static and descriptive; none include dynamic IDs, IPs, timestamps, or generated names.
Test Structure And Quality ✅ Passed Added tests are focused, use existing BeforeEach/AfterEach DB cleanup, and include no cluster waits or resource leaks; unit tests use clear failure messages.
Microshift Test Compatibility ✅ Passed New Ginkgo specs are unit tests only and do not reference MicroShift-unsupported OpenShift APIs or features.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The added Ginkgo tests only verify ignition URL formatting and host role paths; they don’t count nodes, require HA, or depend on multi-node scheduling.
Topology-Aware Scheduling Compatibility ✅ Passed Changes only add retry wrappers to mirroring scripts; no pod specs, replicas, affinity, node selectors, or PDBs were introduced.
Ote Binary Stdout Contract ✅ Passed No process-level stdout writes were added; the touched code is URL logic/tests, and suite setup uses GinkgoWriter/loggers instead of stdout.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The changed Ginkgo tests are local unit/spec tests in internal packages; they don’t use external services, and the new IPv6 case only checks URL formatting.
No-Weak-Crypto ✅ Passed The changed hunks only normalize ignition URLs and add mirror retries; I found no added MD5/SHA1/DES/RC4/etc. or secret/token comparisons in the patch.
Container-Privileges ✅ Passed HEAD only changes shell scripts; no container/K8s manifests or privileged flags (privileged, hostPID/Network/IPC, SYS_ADMIN, allowPrivilegeEscalation) were present.
No-Sensitive-Data-In-Logs ✅ Passed New log lines only report mirror attempts/failures and command names; the URL normalization changes add no new logging of sensitive values.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jul 1, 2026
@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@openshift-ci

openshift-ci Bot commented Jul 1, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: andrej1991
Once this PR has been reviewed and has the lgtm label, please assign pastequo for approval. 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

@andrej1991

Copy link
Copy Markdown
Contributor Author

@coderabbitai help

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai rate limit to show your current review rate limit status.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
  • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
  • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai emit path instructions to emit generated path-specific review instructions for this repository.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@andrej1991

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

4 similar comments
@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@openshift-ci openshift-ci Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jul 2, 2026
@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (4)
internal/bminventory/inventory_ignition_endpoint_unit_test.go (1)

1-22: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

New file mixes plain testing.T with the package's existing Ginkgo/Gomega convention.

This adds a stdlib-style unit test in a package that otherwise uses Ginkgo/Gomega for tests (see internal/host/hostutil/host_utils_test.go for a similar pattern). Consider folding this coverage into the existing Ginkgo suite for consistency, unless there's a specific reason to keep it framework-independent.

🤖 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 `@internal/bminventory/inventory_ignition_endpoint_unit_test.go` around lines 1
- 22, The new validation coverage in
TestValidateIgnitionEndpointNormalizesUnbracketedIPv6 is using plain testing.T,
but this package’s tests follow the Ginkgo/Gomega style. Move this case into the
existing bminventory Ginkgo suite and express the same validateIgnitionEndpoint
and IgnitionEndpoint URL normalization assertions with Gomega, keeping the
behavior coverage while matching the surrounding test convention.
internal/host/hostutil/host_utils_ignition_url_test.go (1)

1-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate test coverage with host_utils_test.go (lines 160-168).

This file's TestGetIgnitionEndpointAndCertUnbracketedIPv6CustomEndpoint and the new It("for cluster with unbracketed IPv6 custom IgnitionEndpoint", ...) block in host_utils_test.go test the same input/output using two different test frameworks (stdlib testing here vs. Ginkgo/Gomega there). Consider dropping one to avoid duplicate maintenance and mixed test-framework conventions in the same package.

🤖 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 `@internal/host/hostutil/host_utils_ignition_url_test.go` around lines 1 - 31,
The new unbracketed IPv6 custom IgnitionEndpoint scenario is duplicated between
TestGetIgnitionEndpointAndCertUnbracketedIPv6CustomEndpoint and the Ginkgo case
in host_utils_test.go, so remove one of the two tests to avoid redundant
coverage and mixed testing styles in the hostutil package. Keep the remaining
test aligned with GetIgnitionEndpointAndCert behavior and ensure it still covers
the same URL normalization and nil cert expectation.
deploy/operator/capi/deploy_capi_cluster.sh (1)

83-83: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Preserve substitution failures and quote path expansions.

Line 83 masks get_image_repository_only failures through export, and Line 101 can split $PWD when constructing the workspace URL.

Proposed fix
-      export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/$(get_image_repository_only ${PROVIDER_IMAGE}):capi"
+      provider_image_repo="$(get_image_repository_only "${PROVIDER_IMAGE}")"
+      export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/${provider_image_repo}:capi"
...
-    run_mirror_command_with_retry oc-mirror --config isc.yaml --authfile "${PULL_SECRET_FILE}" --workspace file://$PWD/mirror docker://"${OCP_MIRROR_REGISTRY}" --v2
+    run_mirror_command_with_retry oc-mirror --config isc.yaml --authfile "${PULL_SECRET_FILE}" --workspace "file://${PWD}/mirror" docker://"${OCP_MIRROR_REGISTRY}" --v2

Also applies to: 101-101

🤖 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 `@deploy/operator/capi/deploy_capi_cluster.sh` at line 83, The provider image
assignment currently hides failures from get_image_repository_only because the
command substitution is wrapped directly in export; assign the substitution to
PROVIDER_LOCAL_IMAGE first (or otherwise preserve its exit status) and then
export it so errors are not masked. Also update the workspace URL construction
to quote the PWD expansion so the path in the URL is not split or globbed. Use
the existing get_image_repository_only and PROVIDER_LOCAL_IMAGE / workspace URL
setup in deploy_capi_cluster.sh to make the change.

Source: Linters/SAST tools

deploy/operator/setup_hive.sh (1)

6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Quote the sourced helper path.

This avoids word splitting if the checkout path contains spaces and clears the ShellCheck finding.

Proposed fix
-source ${__dir}/mirror_utils.sh
+# shellcheck source=deploy/operator/mirror_utils.sh
+source "${__dir}/mirror_utils.sh"
🤖 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 `@deploy/operator/setup_hive.sh` at line 6, The helper source statement in
setup_hive.sh should quote the path to avoid word splitting when __dir contains
spaces. Update the source call that pulls in mirror_utils.sh to use a quoted
path, keeping the same __dir variable and sourced helper name so the shellcheck
warning is resolved.

Source: Linters/SAST tools

🤖 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 `@deploy/operator/mirror_utils.sh`:
- Line 19: The mirror attempt log in the helper that prints "Mirror attempt" is
exposing full command arguments via $*, which can leak internal hostnames and
customer data. Update the logging in the mirror utility to keep only the attempt
counters and the command name, or redact the arguments before printing, so the
mirror call sites do not surface local registry or environment details.
- Around line 21-24: The logging helper is changing the caller’s shell options
by always re-enabling pipefail after the command runs. In the script’s
`mirror_utils.sh` helper around the `"$@" 2>&1 | tee "${log_file}"` block,
capture whether pipefail was set before modifying it, then restore that original
state after recording `PIPESTATUS[0]` so sourced callers keep their prior shell
settings.

---

Nitpick comments:
In `@deploy/operator/capi/deploy_capi_cluster.sh`:
- Line 83: The provider image assignment currently hides failures from
get_image_repository_only because the command substitution is wrapped directly
in export; assign the substitution to PROVIDER_LOCAL_IMAGE first (or otherwise
preserve its exit status) and then export it so errors are not masked. Also
update the workspace URL construction to quote the PWD expansion so the path in
the URL is not split or globbed. Use the existing get_image_repository_only and
PROVIDER_LOCAL_IMAGE / workspace URL setup in deploy_capi_cluster.sh to make the
change.

In `@deploy/operator/setup_hive.sh`:
- Line 6: The helper source statement in setup_hive.sh should quote the path to
avoid word splitting when __dir contains spaces. Update the source call that
pulls in mirror_utils.sh to use a quoted path, keeping the same __dir variable
and sourced helper name so the shellcheck warning is resolved.

In `@internal/bminventory/inventory_ignition_endpoint_unit_test.go`:
- Around line 1-22: The new validation coverage in
TestValidateIgnitionEndpointNormalizesUnbracketedIPv6 is using plain testing.T,
but this package’s tests follow the Ginkgo/Gomega style. Move this case into the
existing bminventory Ginkgo suite and express the same validateIgnitionEndpoint
and IgnitionEndpoint URL normalization assertions with Gomega, keeping the
behavior coverage while matching the surrounding test convention.

In `@internal/host/hostutil/host_utils_ignition_url_test.go`:
- Around line 1-31: The new unbracketed IPv6 custom IgnitionEndpoint scenario is
duplicated between TestGetIgnitionEndpointAndCertUnbracketedIPv6CustomEndpoint
and the Ginkgo case in host_utils_test.go, so remove one of the two tests to
avoid redundant coverage and mixed testing styles in the hostutil package. Keep
the remaining test aligned with GetIgnitionEndpointAndCert behavior and ensure
it still covers the same URL normalization and nil cert expectation.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ffcaec83-1085-4e5d-8bef-fa4f6ae04a39

📥 Commits

Reviewing files that changed from the base of the PR and between 6781f15 and 2adef12.

📒 Files selected for processing (8)
  • deploy/operator/capi/deploy_capi_cluster.sh
  • deploy/operator/mirror_utils.sh
  • deploy/operator/setup_hive.sh
  • internal/bminventory/inventory.go
  • internal/bminventory/inventory_ignition_endpoint_unit_test.go
  • internal/host/hostutil/host_utils.go
  • internal/host/hostutil/host_utils_ignition_url_test.go
  • internal/host/hostutil/host_utils_test.go

Comment thread deploy/operator/mirror_utils.sh Outdated
Comment thread deploy/operator/mirror_utils.sh Outdated
@andrej1991

Copy link
Copy Markdown
Contributor Author

/test edge-e2e-ai-operator-disconnected-capi

@andrej1991

Copy link
Copy Markdown
Contributor Author

/retest

@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 44.51%. Comparing base (5b647d5) to head (2adef12).
⚠️ Report is 2 commits behind head on master.

⚠️ Current head 2adef12 differs from pull request most recent head 213bb6c

Please upload reports for the commit 213bb6c to get more accurate results.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #10570      +/-   ##
==========================================
+ Coverage   44.48%   44.51%   +0.02%     
==========================================
  Files         423      423              
  Lines       73327    73353      +26     
==========================================
+ Hits        32622    32652      +30     
+ Misses      37798    37794       -4     
  Partials     2907     2907              
Files with missing lines Coverage Δ
internal/bminventory/inventory.go 71.80% <100.00%> (+0.05%) ⬆️
...oller/controllers/clusterdeployments_controller.go 73.50% <100.00%> (ø)
internal/host/hostutil/host_utils.go 56.10% <100.00%> (+0.19%) ⬆️
pkg/validations/validations.go 96.61% <100.00%> (+0.86%) ⬆️

... and 1 file with indirect coverage changes

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

…validation

The edge CAPI disconnected test
pull-ci-openshift-assisted-service-master-edge-e2e-ai-operator-disconnected-capi
started failing after PR openshift#10396 upgraded assisted-service to Go 1.26.

Go 1.26 tightened net/url.Parse: URLs with an unbracketed IPv6 host and port
are now rejected (urlstrictcolons). Hypershift builds ignition endpoints as
host:port without brackets (e.g. fd2e:6f44:5dd8:c956::14:31187), and
cluster-api-provider-agent copies that into AgentClusterInstall. The operator
then syncs the URL to the backend, where ValidateHTTPFormat fails:

  parse "https://fd2e:6f44:5dd8:c956::14:31187": invalid port
  ":6f44:5dd8:c956::14:31187" after host

That surfaces as ACI SpecSynced=False (InputError), the worker agent stays
insufficient (ignition-downloadable pending), and the test times out waiting
for a day-2 worker node. The same IPv6 lab and URL format passed on Go 1.25
(e.g. PR openshift#10319, Jun 2026); the regression correlates with the toolchain bump,
not with the OCP 5.0 payload shift.

Add NormalizeHTTPURL to bracket IPv6 literal hosts via net.JoinHostPort.
Apply it in ValidateHTTPFormat and in parseIgnitionEndpoint so URLs from ACI
are normalized before API validation and storage.

The root cause is upstream in Hypershift URL construction; this change is a
defensive fix on the assisted-service side. A companion fix in
cluster-api-provider-agent normalizes the URL when writing ACI.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@deploy/operator/capi/deploy_capi_cluster.sh`:
- Line 101: The oc-mirror invocation in deploy_capi_cluster.sh uses an unquoted
$PWD in the --workspace argument, which triggers shellcheck SC2086. Update the
run_mirror_command_with_retry call to quote the workspace path so the shell
treats the full file URL as a single argument; use the existing oc-mirror
command in deploy_capi_cluster.sh as the place to apply the fix.
- Line 83: The PROVIDER_LOCAL_IMAGE export combines command substitution with an
unquoted PROVIDER_IMAGE expansion, triggering shellcheck SC2155/SC2086. Update
the assignment in deploy_capi_cluster.sh so the image repository lookup is
performed safely with PROVIDER_IMAGE quoted inside get_image_repository_only,
and avoid masking the command substitution result by separating the export from
the variable construction if needed; use the existing get_image_repository_only
and PROVIDER_LOCAL_IMAGE symbols to locate the fix.

In `@deploy/operator/setup_hive.sh`:
- Line 6: The source statement in setup_hive.sh uses __dir unquoted, which can
break when the path contains spaces or special characters. Update the source
line to quote the __dir expansion so mirror_utils.sh is loaded safely, and keep
the change localized to the source invocation that references __dir.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 79364b9e-4d67-4431-a9ea-0fc727962457

📥 Commits

Reviewing files that changed from the base of the PR and between 2adef12 and fd6c432.

📒 Files selected for processing (11)
  • deploy/operator/capi/deploy_capi_cluster.sh
  • deploy/operator/mirror_utils.sh
  • deploy/operator/setup_hive.sh
  • internal/bminventory/inventory.go
  • internal/bminventory/inventory_ignition_endpoint_unit_test.go
  • internal/controller/controllers/clusterdeployments_controller.go
  • internal/host/hostutil/host_utils.go
  • internal/host/hostutil/host_utils_ignition_url_test.go
  • internal/host/hostutil/host_utils_test.go
  • pkg/validations/validations.go
  • pkg/validations/validations_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/validations/validations_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • internal/bminventory/inventory.go
  • internal/host/hostutil/host_utils_test.go
  • internal/bminventory/inventory_ignition_endpoint_unit_test.go
  • internal/host/hostutil/host_utils_ignition_url_test.go
  • internal/host/hostutil/host_utils.go
  • internal/controller/controllers/clusterdeployments_controller.go
  • deploy/operator/mirror_utils.sh
  • pkg/validations/validations.go

# 3. mirrored CAPI provider agent image to local mirror registry
if [ ! -z "$PROVIDER_IMAGE" ]
then
export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/$(get_image_repository_only ${PROVIDER_IMAGE}):capi"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix shellcheck SC2155/SC2086 on PROVIDER_LOCAL_IMAGE assignment.

Command substitution's return value is masked by the export assignment, and ${PROVIDER_IMAGE} is unquoted inside $(...), risking word-splitting/globbing.

🔧 Proposed fix
-      export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/$(get_image_repository_only ${PROVIDER_IMAGE}):capi"
+      provider_repo=$(get_image_repository_only "${PROVIDER_IMAGE}")
+      export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/${provider_repo}:capi"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/$(get_image_repository_only ${PROVIDER_IMAGE}):capi"
provider_repo=$(get_image_repository_only "${PROVIDER_IMAGE}")
export PROVIDER_LOCAL_IMAGE="${LOCAL_REGISTRY}/${provider_repo}:capi"
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 83-83: Declare and assign separately to avoid masking return values.

(SC2155)


[info] 83-83: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 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 `@deploy/operator/capi/deploy_capi_cluster.sh` at line 83, The
PROVIDER_LOCAL_IMAGE export combines command substitution with an unquoted
PROVIDER_IMAGE expansion, triggering shellcheck SC2155/SC2086. Update the
assignment in deploy_capi_cluster.sh so the image repository lookup is performed
safely with PROVIDER_IMAGE quoted inside get_image_repository_only, and avoid
masking the command substitution result by separating the export from the
variable construction if needed; use the existing get_image_repository_only and
PROVIDER_LOCAL_IMAGE symbols to locate the fix.

Source: Linters/SAST tools

Comment thread deploy/operator/capi/deploy_capi_cluster.sh Outdated
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source ${__dir}/common.sh
source ${__dir}/utils.sh
source ${__dir}/mirror_utils.sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Quote ${__dir} in the source line.

🔧 Proposed fix
-source ${__dir}/mirror_utils.sh
+source "${__dir}/mirror_utils.sh"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
source ${__dir}/mirror_utils.sh
source "${__dir}/mirror_utils.sh"
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 6-6: Not following: ./mirror_utils.sh was not specified as input (see shellcheck -x).

(SC1091)


[info] 6-6: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 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 `@deploy/operator/setup_hive.sh` at line 6, The source statement in
setup_hive.sh uses __dir unquoted, which can break when the path contains spaces
or special characters. Update the source line to quote the __dir expansion so
mirror_utils.sh is loaded safely, and keep the change localized to the source
invocation that references __dir.

Source: Linters/SAST tools

@andrej1991

Copy link
Copy Markdown
Contributor Author

/retest

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

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants