Skip to content

MCO-2208: MCO-2125: Migrate mco registry units#6079

Open
ptalgulk01 wants to merge 3 commits into
openshift:mainfrom
ptalgulk01:migrate-mco-registry-units
Open

MCO-2208: MCO-2125: Migrate mco registry units#6079
ptalgulk01 wants to merge 3 commits into
openshift:mainfrom
ptalgulk01:migrate-mco-registry-units

Conversation

@ptalgulk01
Copy link
Copy Markdown
Contributor

@ptalgulk01 ptalgulk01 commented May 21, 2026

Summary

Migrate 10 test cases from openshift-tests-private to machine-config-operator repo:

  • 9 registry tests from mco_registry.go
  • 1 units test from mco_units.go

This PR continues the migration effort started in #6021 and #5902.

Tests Migrated

Registry Tests (mco_registry.go - 9 tests)

  • 43405: node drain is not needed for mirror config change in container registry
  • 42682: change container registry config on ocp 4.6+
  • 42680: change pull secret in the openshift-config namespace
  • 52520: Configure unqualified-search-registries in Image.config resource
  • 57595: Use empty pull-secret
  • 61555: ImageDigestMirrorSet test
  • 61558: ImageTagMirrorSet test
  • 66046: Check image registry certificates
  • 68736: machine config server supports bootstrap with IR certs

Units Test (mco_units.go - 1 test)

  • 53960: No failed units in the bootstrap machine (AWS/Azure only)

Infrastructure Added

Bootstrap Package (from PR #6027)

  • test/extended-priv/util/bootstrap/bootstrap.go - Core bootstrap SSH infrastructure
  • test/extended-priv/util/bootstrap/aws.go - AWS instance discovery
  • test/extended-priv/util/bootstrap/azure.go - Azure instance discovery
  • test/extended-priv/util/ssh_client.go - SSH client utilities

Helper Functions & Methods Added

test/extended-priv/util/clusters.go

  • GetClusterVersion() - Returns cluster version and build

test/extended-priv/util.go

  • NewImageTagMirrorSet() - Create ImageTagMirrorSet resource
  • skipTestIfExtensionsAreUsed() - Skip tests when extensions are present
  • GetImageRegistryCertificates() - Retrieve image registry certificates
  • GetManagedMergedTrustedImageRegistryCertificates() - Get merged trusted certificates
  • GetDataFromConfigMap() - Extract data from ConfigMaps

test/extended-priv/mco.go

  • skipTestIfClusterVersion() - Skip tests based on cluster version

test/extended-priv/machineconfig.go

  • GetExtensions() - Get extensions configured in MachineConfig

Constants Added

test/extended-priv/const.go

  • MCDCrioReloadedRegexp - Regex for detecting CRI-O reloads
  • NodeDisruptionPolicyFiles - "files"
  • NodeDisruptionPolicyUnits - "units"
  • NodeDisruptionPolicySshkey - "sshkey"

Build Verification

make machine-config-tests-ext
./_output/linux/amd64/machine-config-tests-ext list | grep -E "PolarionID:(43405|42682|42680|52520|57595|61555|61558|66046|68736|53960)"

All 10 tests successfully built and appear in test listing.



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Tests**
* Added comprehensive test suite validating Machine Config Operator behavior with container registry configurations, image mirrors, pull secrets, and certificate handling across different cluster versions.
* Added test verifying bootstrap machine has no failed systemd units.

* **Chores**
* Added bootstrap machine discovery infrastructure supporting AWS and Azure environments for testing purposes.
* Added test utility helpers for cluster version retrieval and image registry certificate management.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

ptalgulk01 and others added 3 commits May 21, 2026 22:55
Migrated 9 test cases from mco_registry.go:
- 43405: node drain is not needed for mirror config change
- 42682: change container registry config on ocp 4.6+
- 42680: change pull secret in the openshift-config namespace
- 52520: Configure unqualified-search-registries
- 57595: Use empty pull-secret
- 61555: ImageDigestMirrorSet test
- 61558: ImageTagMirrorSet test
- 66046: Check image registry certificates
- 68736: machine config server supports bootstrap with IR certs

Added helper functions and utilities:
- Added MCDCrioReloadedRegexp constant to const.go
- Added GetClusterVersion to util/clusters.go
- Added NewImageTagMirrorSet, skipTestIfExtensionsAreUsed,
  GetImageRegistryCertificates, GetManagedMergedTrustedImageRegistryCertificates,
  and GetDataFromConfigMap to util.go
- Added skipTestIfClusterVersion to mco.go
- Added GetExtensions method to MachineConfig in machineconfig.go

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added bootstrap package for SSH connectivity to bootstrap nodes:
- util/bootstrap/bootstrap.go: Core bootstrap infrastructure
- util/bootstrap/aws.go: AWS-specific bootstrap instance discovery
- util/bootstrap/azure.go: Azure-specific bootstrap instance discovery
- util/ssh_client.go: SSH client utilities for remote command execution

Migrated test case from mco_units.go:
- 53960: No failed units in the bootstrap machine
  - Platform-specific test for AWS and Azure
  - Validates systemd units status on bootstrap machine
  - Uses SSH to connect and run systemctl commands

This infrastructure enables testing bootstrap machine state and
configuration, particularly for validating systemd unit health
during cluster deployment.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Adjusted function order to match otp3 source files:
- mco.go: Moved skipTestIfClusterVersion to come after skipTestIfRHELVersion
  (was at end of file, now follows source order from mco.go line 1424)
- machineconfig.go: Moved GetExtensions to come before GetIgnitionVersion
  (follows source order from machineconfig.go line 117)

This maintains consistency with the source repository structure
and makes future migrations easier to track.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@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-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 21, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented May 21, 2026

@ptalgulk01: This pull request references MCO-2208 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 story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate 10 test cases from openshift-tests-private to machine-config-operator repo:

  • 9 registry tests from mco_registry.go
  • 1 units test from mco_units.go

This PR continues the migration effort started in #6021 and #5902.

Tests Migrated

Registry Tests (mco_registry.go - 9 tests)

  • 43405: node drain is not needed for mirror config change in container registry
  • 42682: change container registry config on ocp 4.6+
  • 42680: change pull secret in the openshift-config namespace
  • 52520: Configure unqualified-search-registries in Image.config resource
  • 57595: Use empty pull-secret
  • 61555: ImageDigestMirrorSet test
  • 61558: ImageTagMirrorSet test
  • 66046: Check image registry certificates
  • 68736: machine config server supports bootstrap with IR certs

Units Test (mco_units.go - 1 test)

  • 53960: No failed units in the bootstrap machine (AWS/Azure only)

Infrastructure Added

Bootstrap Package (from PR #6027)

  • test/extended-priv/util/bootstrap/bootstrap.go - Core bootstrap SSH infrastructure
  • test/extended-priv/util/bootstrap/aws.go - AWS instance discovery
  • test/extended-priv/util/bootstrap/azure.go - Azure instance discovery
  • test/extended-priv/util/ssh_client.go - SSH client utilities

Helper Functions & Methods Added

test/extended-priv/util/clusters.go

  • GetClusterVersion() - Returns cluster version and build

test/extended-priv/util.go

  • NewImageTagMirrorSet() - Create ImageTagMirrorSet resource
  • skipTestIfExtensionsAreUsed() - Skip tests when extensions are present
  • GetImageRegistryCertificates() - Retrieve image registry certificates
  • GetManagedMergedTrustedImageRegistryCertificates() - Get merged trusted certificates
  • GetDataFromConfigMap() - Extract data from ConfigMaps

test/extended-priv/mco.go

  • skipTestIfClusterVersion() - Skip tests based on cluster version

test/extended-priv/machineconfig.go

  • GetExtensions() - Get extensions configured in MachineConfig

Constants Added

test/extended-priv/const.go

  • MCDCrioReloadedRegexp - Regex for detecting CRI-O reloads
  • NodeDisruptionPolicyFiles - "files"
  • NodeDisruptionPolicyUnits - "units"
  • NodeDisruptionPolicySshkey - "sshkey"

Build Verification

make machine-config-tests-ext
./_output/linux/amd64/machine-config-tests-ext list | grep -E "PolarionID:(43405|42682|42680|52520|57595|61555|61558|66046|68736|53960)"

All 10 tests successfully built and appear in test listing.

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
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

Walkthrough

This PR introduces comprehensive test infrastructure for the Machine Config Operator, adding bootstrap machine discovery and SSH utilities, version-aware test skipping, and a large registry configuration test suite covering ImageContentSourcePolicy, mirrors, pull-secrets, and certificates.

Changes

MCO Registry and Bootstrap Test Infrastructure

Layer / File(s) Summary
Test helper constants and utilities
test/extended-priv/const.go, test/extended-priv/machineconfig.go, test/extended-priv/mco.go, test/extended-priv/util.go, test/extended-priv/util/clusters.go
New constants for node disruption policies and crio reload detection; GetExtensions() method on MachineConfig; skipTestIfClusterVersion() helper for conditional test skipping; helpers to check for extensions and retrieve image-registry certificate ConfigMap data; GetClusterVersion() to extract major.minor version from cluster.
Bootstrap discovery and SSH infrastructure
test/extended-priv/util/ssh_client.go, test/extended-priv/util/bootstrap/bootstrap.go, test/extended-priv/util/bootstrap/aws.go, test/extended-priv/util/bootstrap/azure.go
Complete SshClient with thread-safe output buffering for remote SSH command execution; BSInfoProvider interface for platform-specific bootstrap IP lookup; GetBootstrap() orchestrator that selects provider, retrieves IPs, and returns configured bootstrap instance; AWS provider implementation querying EC2 for bootstrap instance IPs; Azure provider stub (unimplemented).
MCO registry configuration test suite
test/extended-priv/mco_registry.go
Nine disruptive and serial tests validating MCO behavior when changing registry configuration via ImageContentSourcePolicy, /etc/containers/registries.conf, pull-secrets, cluster image.config, ImageDigestMirrorSet, ImageTagMirrorSet, and registry certificates; asserts drain/reboot/crio-reload events, node state transitions, and configuration persistence; includes helpers to skip on ImageContentSourcePolicy existence and validate default removal events.
Bootstrap systemd units test
test/extended-priv/mco_units.go
New Ginkgo test retrieving the bootstrap instance and verifying no failed systemd units via SSH with eventual retry logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

lgtm, approved, verified

Suggested reviewers

  • pablintino
  • cheesesashimi
  • dkhater-redhat
🚥 Pre-merge checks | ✅ 6 | ❌ 6

❌ Failed checks (5 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ⚠️ Warning Code quality issues: format specifiers broken, assertion messages wrong, missing format args, wrong node references, missing offset helpers, bounds check vulnerability. Fix format specifiers and assertion messages; add missing format arguments; correct node references; add ExpectWithOffset; add bounds checking; use net.JoinHostPort; handle errors properly.
Microshift Test Compatibility ⚠️ Warning Multiple new tests use unavailable OpenShift APIs (config.openshift.io/v1 resources like ImageDigestMirrorSet, ImageTagMirrorSet, Image config; ClusterVersion) without MicroShift protections. Add [apigroup:config.openshift.io] tags to affected tests or guard with exutil.IsMicroShiftCluster() checks, as MicroShift doesn't serve config.openshift.io APIs.
Single Node Openshift (Sno) Test Compatibility ⚠️ Warning Tests 43405, 42682, 42680, 52520 in mco_registry.go assume multi-node clusters: they iterate over master/worker node lists and validate cordoning/taints across multiple nodes, incompatible with SNO. Add [Skipped:SingleReplicaTopology] labels to all 9 tests in mco_registry.go. These test multi-node configurations (node draining, cordoning, taint validation, multiple master/worker pools).
Ipv6 And Disconnected Network Test Compatibility ⚠️ Warning SSH address construction in ssh_client.go:66 uses fmt.Sprintf without IPv6 bracket notation, failing on IPv6-only clusters. Bootstrap test will fail when connecting to IPv6 bootstrap machines. Use net.JoinHostPort(Host, port) instead of fmt.Sprintf for IPv6-compatible address construction in ssh_client.go RunOutput method.
Title check ❓ Inconclusive The title references MCO-2208 and MCO-2125 (Jira tickets) but lacks clarity on the primary change; it mentions 'Migrate mco registry units' which partially reflects the substantial registry test migration, but the PR also adds bootstrap infrastructure and SSH utilities not clearly conveyed in the title. Consider rephrasing to clarify the main deliverable, such as 'Migrate MCO registry and units tests with bootstrap infrastructure' to better reflect both the test migration and new utility additions.
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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 All test titles in mco_registry.go and mco_units.go use stable static text with Polarion IDs; no dynamic content (pod names, timestamps, UUIDs, node names) found in titles.
Topology-Aware Scheduling Compatibility ✅ Passed All changes are test code and testing utilities in test/extended-priv/. No deployment manifests, operator code, or controllers with scheduling constraints are introduced.
Ote Binary Stdout Contract ✅ Passed PR code contains no process-level stdout writes. All logging uses logext package redirected to GinkgoWriter, and test suites properly use Ginkgo's module-level patterns.

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

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

Command failed


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 requested review from RishabhSaini and pablintino May 21, 2026 17:42
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 21, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ptalgulk01
Once this PR has been reviewed and has the lgtm label, please assign djoshy 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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (1)
test/extended-priv/mco_registry.go (1)

185-185: ⚡ Quick win

Avoid the bash -c shell wrapper for the file copy.

secretFile/newSecretFile are generated locally, so this is not exploitable today, but invoking bash -c "cp …" with string concatenation is a footgun if either path ever contains a space or shell metacharacter, and it tripped the static analyzer (coderabbit.command-injection.go-exec-command). Invoke cp directly (or use io.Copy over os.Open/os.Create).

♻️ Proposed refactor
-		_, copyErr := exec.Command("bash", "-c", "cp "+secretFile+" "+newSecretFile).Output()
+		_, copyErr := exec.Command("cp", secretFile, newSecretFile).Output()
🤖 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 `@test/extended-priv/mco_registry.go` at line 185, Replace the unsafe
shell-invocation exec.Command call that builds a "bash -c" string with a direct
file-copy implementation: either call exec.Command("cp", secretFile,
newSecretFile) to invoke cp without a shell or, preferably, open secretFile and
newSecretFile with os.Open/os.Create and copy contents using io.Copy; update the
site where exec.Command("bash", "-c", "cp "+secretFile+" "+newSecretFile) is
used to reference secretFile and newSecretFile directly to avoid shell
interpolation and satisfy the static analyzer.
🤖 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/extended-priv/mco_registry.go`:
- Around line 66-67: The assertion message uses a malformed format verb ("%") so
the node name from node.GetName() will not be printed and fmt will error; update
the format string in the o.Expect(...).To(o.BeFalse(...)) call to use a proper
verb (e.g. "%s") or otherwise build the message with the node name, referencing
the existing call sites node.IsCordoned(), o.Expect, o.BeFalse(), and
node.GetName() so the node name is interpolated correctly into the error
message.
- Around line 545-547: The failure message for the assertion using nodeEvents
and HaveEventsSequence("Drain") is inverted; update the message passed to
o.Expect(...).To(HaveEventsSequence("Drain"), ...) to reflect that we expected a
Drain event but none occurred (e.g. "Error, expected a Drain event to be
triggered but it wasn't") so the log correctly describes the failing condition
for the positive assertion in the nodeEvents/HaveEventsSequence call.
- Around line 627-636: The assertion messages for the checks using
GetManagedMergedTrustedImageRegistryCertificates reference "%s" but don't supply
certFile, causing missing-format tokens; update the
o.Eventually(...).Should(...) and the final o.Expect(...).To(...) calls to
include the certFile in their failure messages (e.g., pass certFile as the
format arg or pre-format the message with fmt.Sprintf), ensure the message still
names merged-trusted-image-registry-ca and the certFile/ certValue variables are
used to construct the assertion text, and keep using
GetManagedMergedTrustedImageRegistryCertificates(oc.AsAdmin()) with the separate
explicit call that checks err as shown.
- Around line 324-334: The master assertions incorrectly reference the worker
and omit format args: in the HaveEventsSequence assertion replace
firstUpdatedWorker.GetName() with firstUpdatedMaster.GetName(), and for the two
o.Expect(...BeTemporally(...)) failure messages add the missing node name
arguments—pass firstUpdatedWorker.GetName() to the worker uptime assertion and
firstUpdatedMaster.GetName() to the master uptime assertion so the "%s"
placeholders are satisfied; look for symbols firstUpdatedMaster.GetEvents,
HaveEventsSequence, firstUpdatedWorker.GetUptime, and
firstUpdatedMaster.GetUptime to locate the lines to edit.

In `@test/extended-priv/mco.go`:
- Around line 86-95: The helper skipTestIfClusterVersion currently calls
o.Expect(err).NotTo(...), which reports failures at this helper; change it to
use o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) so failures point to the
caller; keep the rest of the logic (calls to exutil.GetClusterVersion,
CompareVersions and g.Skip with clusterVersion, operator, constraintVersion)
unchanged.

In `@test/extended-priv/util/bootstrap/azure.go`:
- Around line 19-22: The code discards the error returned by
oc.WithoutNamespace().AsAdmin().Run("get").Args(...).Output(), which can leave
infraName empty and produce a misleading bootstrapName and InstanceNotFound
name; change the call that assigns infraName to capture the error (e.g.,
infraName, err := ...Output()), check err and if non-nil log it with context via
logger.Errorf or return a more accurate error, and only construct bootstrapName
and return &InstanceNotFound{bootstrapName} when you have a reliable infraName
(or fall back to a clear placeholder like "<unknown-infra>"); update references
to infraName, bootstrapName, and the InstanceNotFound return accordingly.

In `@test/extended-priv/util/clusters.go`:
- Around line 23-32: GetClusterVersion currently splits clusterBuild into
splitValues and directly indexes [0] and [1], which can panic if the version is
malformed; add bounds checking after strings.Split to verify len(splitValues) >=
2 and return a descriptive error (including clusterBuild) if not, otherwise
construct clusterVersion from splitValues[0] + "." + splitValues[1] and return
as before; ensure you still return the original err (or nil) on success.

In `@test/extended-priv/util/ssh_client.go`:
- Around line 60-86: The SSH dial address in SshClient.RunOutput is built with
fmt.Sprintf("%v:%v", sshClient.Host, sshClient.Port) which breaks for IPv6;
change the address construction to use net.JoinHostPort(sshClient.Host,
strconv.Itoa(sshClient.Port)) (importing net and strconv) and pass that result
to ssh.Dial so IPv4 and IPv6 hosts are handled correctly.

---

Nitpick comments:
In `@test/extended-priv/mco_registry.go`:
- Line 185: Replace the unsafe shell-invocation exec.Command call that builds a
"bash -c" string with a direct file-copy implementation: either call
exec.Command("cp", secretFile, newSecretFile) to invoke cp without a shell or,
preferably, open secretFile and newSecretFile with os.Open/os.Create and copy
contents using io.Copy; update the site where exec.Command("bash", "-c", "cp
"+secretFile+" "+newSecretFile) is used to reference secretFile and
newSecretFile directly to avoid shell interpolation and satisfy the static
analyzer.
🪄 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: a7674f12-1469-4c50-9a47-96179fd4fc59

📥 Commits

Reviewing files that changed from the base of the PR and between 9bd4e4f and 853ccf5.

📒 Files selected for processing (11)
  • test/extended-priv/const.go
  • test/extended-priv/machineconfig.go
  • test/extended-priv/mco.go
  • test/extended-priv/mco_registry.go
  • test/extended-priv/mco_units.go
  • test/extended-priv/util.go
  • test/extended-priv/util/bootstrap/aws.go
  • test/extended-priv/util/bootstrap/azure.go
  • test/extended-priv/util/bootstrap/bootstrap.go
  • test/extended-priv/util/clusters.go
  • test/extended-priv/util/ssh_client.go

Comment on lines +66 to +67
o.Expect(node.IsCordoned()).To(o.BeFalse(), "% is tainted and cordoned. There should be no cordoned worker node after applying the configuration.",
node.GetName())
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Broken format specifier in assertion message.

The format string uses % (without verb) instead of %s, so the node name will not be rendered and Go's fmt will report a malformed verb on failure.

🐛 Proposed fix
-			o.Expect(node.IsCordoned()).To(o.BeFalse(), "% is tainted and cordoned. There should be no cordoned worker node after applying the configuration.",
-				node.GetName())
+			o.Expect(node.IsCordoned()).To(o.BeFalse(), "%s is tainted and cordoned. There should be no cordoned worker node after applying the configuration.",
+				node.GetName())
📝 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
o.Expect(node.IsCordoned()).To(o.BeFalse(), "% is tainted and cordoned. There should be no cordoned worker node after applying the configuration.",
node.GetName())
o.Expect(node.IsCordoned()).To(o.BeFalse(), "%s is tainted and cordoned. There should be no cordoned worker node after applying the configuration.",
node.GetName())
🤖 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 `@test/extended-priv/mco_registry.go` around lines 66 - 67, The assertion
message uses a malformed format verb ("%") so the node name from node.GetName()
will not be printed and fmt will error; update the format string in the
o.Expect(...).To(o.BeFalse(...)) call to use a proper verb (e.g. "%s") or
otherwise build the message with the node name, referencing the existing call
sites node.IsCordoned(), o.Expect, o.BeFalse(), and node.GetName() so the node
name is interpolated correctly into the error message.

Comment on lines +324 to +334
exutil.By("Verify that a drain and reboot events were triggered for master node")
mEvents, meErr := firstUpdatedMaster.GetEvents()
o.Expect(meErr).ShouldNot(o.HaveOccurred(), "Error getting drain events for node %s", firstUpdatedMaster.GetName())
o.Expect(mEvents).To(HaveEventsSequence("Drain", "Reboot"),
"Error, the expected sequence of events is not found in node %s", firstUpdatedWorker.GetName())

exutil.By("Verify that the node was actually rebooted")
o.Expect(firstUpdatedWorker.GetUptime()).Should(o.BeTemporally(">", startTime),
"The node %s should have been rebooted after the configurion. Uptime didnt happen after start config time.")
o.Expect(firstUpdatedMaster.GetUptime()).Should(o.BeTemporally(">", startTime),
"The node %s should have been rebooted after the configurion. Uptime didnt happen after start config time.")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Master assertions reference the worker node and miss format args.

Two issues:

  • Line 328: failure message for the master event sequence reports firstUpdatedWorker.GetName() — should be firstUpdatedMaster.GetName().
  • Lines 332 and 334: the messages contain %s but no arguments are passed, so failures will print a %!s(MISSING) token instead of the node name.
🐛 Proposed fix
 	o.Expect(mEvents).To(HaveEventsSequence("Drain", "Reboot"),
-		"Error, the expected sequence of events is not found in node %s", firstUpdatedWorker.GetName())
+		"Error, the expected sequence of events is not found in node %s", firstUpdatedMaster.GetName())

 	exutil.By("Verify that the node was actually rebooted")
 	o.Expect(firstUpdatedWorker.GetUptime()).Should(o.BeTemporally(">", startTime),
-		"The node %s should have been rebooted after the configurion. Uptime didnt happen after start config time.")
+		"The node %s should have been rebooted after the configuration. Uptime didn't happen after start config time.",
+		firstUpdatedWorker.GetName())
 	o.Expect(firstUpdatedMaster.GetUptime()).Should(o.BeTemporally(">", startTime),
-		"The node %s should have been rebooted after the configurion. Uptime didnt happen after start config time.")
+		"The node %s should have been rebooted after the configuration. Uptime didn't happen after start config time.",
+		firstUpdatedMaster.GetName())
📝 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
exutil.By("Verify that a drain and reboot events were triggered for master node")
mEvents, meErr := firstUpdatedMaster.GetEvents()
o.Expect(meErr).ShouldNot(o.HaveOccurred(), "Error getting drain events for node %s", firstUpdatedMaster.GetName())
o.Expect(mEvents).To(HaveEventsSequence("Drain", "Reboot"),
"Error, the expected sequence of events is not found in node %s", firstUpdatedWorker.GetName())
exutil.By("Verify that the node was actually rebooted")
o.Expect(firstUpdatedWorker.GetUptime()).Should(o.BeTemporally(">", startTime),
"The node %s should have been rebooted after the configurion. Uptime didnt happen after start config time.")
o.Expect(firstUpdatedMaster.GetUptime()).Should(o.BeTemporally(">", startTime),
"The node %s should have been rebooted after the configurion. Uptime didnt happen after start config time.")
exutil.By("Verify that a drain and reboot events were triggered for master node")
mEvents, meErr := firstUpdatedMaster.GetEvents()
o.Expect(meErr).ShouldNot(o.HaveOccurred(), "Error getting drain events for node %s", firstUpdatedMaster.GetName())
o.Expect(mEvents).To(HaveEventsSequence("Drain", "Reboot"),
"Error, the expected sequence of events is not found in node %s", firstUpdatedMaster.GetName())
exutil.By("Verify that the node was actually rebooted")
o.Expect(firstUpdatedWorker.GetUptime()).Should(o.BeTemporally(">", startTime),
"The node %s should have been rebooted after the configuration. Uptime didn't happen after start config time.",
firstUpdatedWorker.GetName())
o.Expect(firstUpdatedMaster.GetUptime()).Should(o.BeTemporally(">", startTime),
"The node %s should have been rebooted after the configuration. Uptime didn't happen after start config time.",
firstUpdatedMaster.GetName())
🤖 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 `@test/extended-priv/mco_registry.go` around lines 324 - 334, The master
assertions incorrectly reference the worker and omit format args: in the
HaveEventsSequence assertion replace firstUpdatedWorker.GetName() with
firstUpdatedMaster.GetName(), and for the two o.Expect(...BeTemporally(...))
failure messages add the missing node name arguments—pass
firstUpdatedWorker.GetName() to the worker uptime assertion and
firstUpdatedMaster.GetName() to the master uptime assertion so the "%s"
placeholders are satisfied; look for symbols firstUpdatedMaster.GetEvents,
HaveEventsSequence, firstUpdatedWorker.GetUptime, and
firstUpdatedMaster.GetUptime to locate the lines to edit.

Comment on lines +545 to +547
exutil.By("Check that drain events were triggered")
o.Expect(nodeEvents).To(HaveEventsSequence("Drain"), "Error, a Drain event was triggered but it shouldn't")
logger.Infof("OK!\n")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inverted assertion message.

The assertion verifies a Drain event was triggered, but the failure message reads "a Drain event was triggered but it shouldn't" — that wording belongs to the opposite case (NotTo). On failure this will mislead the triage.

🐛 Proposed fix
-		o.Expect(nodeEvents).To(HaveEventsSequence("Drain"), "Error, a Drain event was triggered but it shouldn't")
+		o.Expect(nodeEvents).To(HaveEventsSequence("Drain"), "Error, a Drain event was expected but none was triggered")
🤖 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 `@test/extended-priv/mco_registry.go` around lines 545 - 547, The failure
message for the assertion using nodeEvents and HaveEventsSequence("Drain") is
inverted; update the message passed to
o.Expect(...).To(HaveEventsSequence("Drain"), ...) to reflect that we expected a
Drain event but none occurred (e.g. "Error, expected a Drain event to be
triggered but it wasn't") so the log correctly describes the failing condition
for the positive assertion in the nodeEvents/HaveEventsSequence call.

Comment on lines +627 to +636
exutil.By(fmt.Sprintf("Check that the file %s has been added to the managed merged trusted image registry configmap", certFile))

o.Eventually(GetManagedMergedTrustedImageRegistryCertificates, "20s", "10s").WithArguments(oc.AsAdmin()).Should(o.HaveKey(certFile),
"The certificate for file %s has not been included in the configmap merged-trusted-image-registry-ca -n openshift-config-managed")

mmtImageRegistryCert, err := GetManagedMergedTrustedImageRegistryCertificates(oc.AsAdmin())
o.Expect(err).NotTo(o.HaveOccurred(), "Error getting managed merged trusted image registry certificates values")

o.Expect(mmtImageRegistryCert[certFile] == certValue).To(o.BeTrue(),
"The certificate in file %s was added to configmap merged-trusted-image-registry-ca -n openshift-config-managed but it has the wrong content")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing format arguments in assertion messages.

The messages at lines 630 and 636 include %s but pass no arguments, so failures will print %!s(MISSING) tokens instead of the certificate filename. Also note the Eventually at line 629 passes GetManagedMergedTrustedImageRegistryCertificates whose error return is being asserted on a HaveKey matcher — confirm this works as intended (the second return value error is ignored by Eventually's polled-function form, which is acceptable here, but worth a quick sanity check).

🐛 Proposed fix
-			o.Eventually(GetManagedMergedTrustedImageRegistryCertificates, "20s", "10s").WithArguments(oc.AsAdmin()).Should(o.HaveKey(certFile),
-				"The certificate for file %s has not been included in the configmap merged-trusted-image-registry-ca -n openshift-config-managed")
+			o.Eventually(GetManagedMergedTrustedImageRegistryCertificates, "20s", "10s").WithArguments(oc.AsAdmin()).Should(o.HaveKey(certFile),
+				"The certificate for file %s has not been included in the configmap merged-trusted-image-registry-ca -n openshift-config-managed", certFile)
@@
-			o.Expect(mmtImageRegistryCert[certFile] == certValue).To(o.BeTrue(),
-				"The certificate in file %s was added to configmap merged-trusted-image-registry-ca -n openshift-config-managed but it has the wrong content")
+			o.Expect(mmtImageRegistryCert[certFile] == certValue).To(o.BeTrue(),
+				"The certificate in file %s was added to configmap merged-trusted-image-registry-ca -n openshift-config-managed but it has the wrong content", certFile)
🤖 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 `@test/extended-priv/mco_registry.go` around lines 627 - 636, The assertion
messages for the checks using GetManagedMergedTrustedImageRegistryCertificates
reference "%s" but don't supply certFile, causing missing-format tokens; update
the o.Eventually(...).Should(...) and the final o.Expect(...).To(...) calls to
include the certFile in their failure messages (e.g., pass certFile as the
format arg or pre-format the message with fmt.Sprintf), ensure the message still
names merged-trusted-image-registry-ca and the certFile/ certValue variables are
used to construct the assertion text, and keep using
GetManagedMergedTrustedImageRegistryCertificates(oc.AsAdmin()) with the separate
explicit call that checks err as shown.

Comment thread test/extended-priv/mco.go
Comment on lines +86 to +95
// skipTestIfClusterVersion skips the test case if the provided version matches the constraints.
func skipTestIfClusterVersion(oc *exutil.CLI, operator, constraintVersion string) {
clusterVersion, _, err := exutil.GetClusterVersion(oc)
o.Expect(err).NotTo(o.HaveOccurred())

if CompareVersions(clusterVersion, operator, constraintVersion) {
g.Skip(fmt.Sprintf("Test case skipped because current cluster version %s %s %s",
clusterVersion, operator, constraintVersion))
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use ExpectWithOffset(1, ...) for clearer failure context.

This helper function uses o.Expect without an offset, which means test failures will report the line inside this helper rather than the caller's location. For consistency with other helpers in this file (e.g., skipTestIfRHELVersion on line 79), use o.ExpectWithOffset(1, err) instead.

📍 Proposed fix
 func skipTestIfClusterVersion(oc *exutil.CLI, operator, constraintVersion string) {
 	clusterVersion, _, err := exutil.GetClusterVersion(oc)
-	o.Expect(err).NotTo(o.HaveOccurred())
+	o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())
 
 	if CompareVersions(clusterVersion, operator, constraintVersion) {
 		g.Skip(fmt.Sprintf("Test case skipped because current cluster version %s %s %s",
 			clusterVersion, operator, constraintVersion))
 	}
 }
📝 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
// skipTestIfClusterVersion skips the test case if the provided version matches the constraints.
func skipTestIfClusterVersion(oc *exutil.CLI, operator, constraintVersion string) {
clusterVersion, _, err := exutil.GetClusterVersion(oc)
o.Expect(err).NotTo(o.HaveOccurred())
if CompareVersions(clusterVersion, operator, constraintVersion) {
g.Skip(fmt.Sprintf("Test case skipped because current cluster version %s %s %s",
clusterVersion, operator, constraintVersion))
}
}
// skipTestIfClusterVersion skips the test case if the provided version matches the constraints.
func skipTestIfClusterVersion(oc *exutil.CLI, operator, constraintVersion string) {
clusterVersion, _, err := exutil.GetClusterVersion(oc)
o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred())
if CompareVersions(clusterVersion, operator, constraintVersion) {
g.Skip(fmt.Sprintf("Test case skipped because current cluster version %s %s %s",
clusterVersion, operator, constraintVersion))
}
}
🤖 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 `@test/extended-priv/mco.go` around lines 86 - 95, The helper
skipTestIfClusterVersion currently calls o.Expect(err).NotTo(...), which reports
failures at this helper; change it to use o.ExpectWithOffset(1,
err).NotTo(o.HaveOccurred()) so failures point to the caller; keep the rest of
the logic (calls to exutil.GetClusterVersion, CompareVersions and g.Skip with
clusterVersion, operator, constraintVersion) unchanged.

Comment on lines +19 to +22
infraName, _ := oc.WithoutNamespace().AsAdmin().Run("get").Args("infrastructure", "cluster", "-o=jsonpath={.status.infrastructureName}").Output()
bootstrapName := infraName + "-bootstrap"
logger.Infof("Azure bootstrap discovery is not yet implemented, skipping bootstrap machine: %s", bootstrapName)
return nil, &InstanceNotFound{bootstrapName}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Discarded error can produce a misleading bootstrap name in logs.

The error from the infrastructure get is silently dropped on Line 19. On failure, infraName will be empty and the log on Line 21 will say "skipping bootstrap machine: -bootstrap", and the returned InstanceNotFound.name will likewise be -bootstrap. Since this stub always returns InstanceNotFound, it's not a correctness bug today, but a small fix would make the log/diagnostic accurate.

Proposed fix
-	infraName, _ := oc.WithoutNamespace().AsAdmin().Run("get").Args("infrastructure", "cluster", "-o=jsonpath={.status.infrastructureName}").Output()
+	infraName, err := oc.WithoutNamespace().AsAdmin().Run("get").Args("infrastructure", "cluster", "-o=jsonpath={.status.infrastructureName}").Output()
+	if err != nil {
+		return nil, err
+	}
 	bootstrapName := infraName + "-bootstrap"
📝 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
infraName, _ := oc.WithoutNamespace().AsAdmin().Run("get").Args("infrastructure", "cluster", "-o=jsonpath={.status.infrastructureName}").Output()
bootstrapName := infraName + "-bootstrap"
logger.Infof("Azure bootstrap discovery is not yet implemented, skipping bootstrap machine: %s", bootstrapName)
return nil, &InstanceNotFound{bootstrapName}
infraName, err := oc.WithoutNamespace().AsAdmin().Run("get").Args("infrastructure", "cluster", "-o=jsonpath={.status.infrastructureName}").Output()
if err != nil {
return nil, err
}
bootstrapName := infraName + "-bootstrap"
logger.Infof("Azure bootstrap discovery is not yet implemented, skipping bootstrap machine: %s", bootstrapName)
return nil, &InstanceNotFound{bootstrapName}
🤖 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 `@test/extended-priv/util/bootstrap/azure.go` around lines 19 - 22, The code
discards the error returned by
oc.WithoutNamespace().AsAdmin().Run("get").Args(...).Output(), which can leave
infraName empty and produce a misleading bootstrapName and InstanceNotFound
name; change the call that assigns infraName to capture the error (e.g.,
infraName, err := ...Output()), check err and if non-nil log it with context via
logger.Errorf or return a more accurate error, and only construct bootstrapName
and return &InstanceNotFound{bootstrapName} when you have a reliable infraName
(or fall back to a clear placeholder like "<unknown-infra>"); update references
to infraName, bootstrapName, and the InstanceNotFound return accordingly.

Comment on lines +23 to +32
// GetClusterVersion returns the cluster version as string value (Ex: 4.8) and cluster build (Ex: 4.8.0-0.nightly-2021-09-28-165247)
func GetClusterVersion(oc *CLI) (string, string, error) {
clusterBuild, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("clusterversion", "-o", "jsonpath={..desired.version}").Output()
if err != nil {
return "", "", err
}
splitValues := strings.Split(clusterBuild, ".")
clusterVersion := splitValues[0] + "." + splitValues[1]
return clusterVersion, clusterBuild, err
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add bounds checking to prevent index out of range panic.

Lines 29-30 split the cluster version string and access splitValues[0] and splitValues[1] without validating the slice length. If the cluster version string has fewer than two dots (e.g., malformed version), this will panic with an index out of range error.

🛡️ Proposed fix
 func GetClusterVersion(oc *CLI) (string, string, error) {
 	clusterBuild, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("clusterversion", "-o", "jsonpath={..desired.version}").Output()
 	if err != nil {
 		return "", "", err
 	}
 	splitValues := strings.Split(clusterBuild, ".")
+	if len(splitValues) < 2 {
+		return "", "", fmt.Errorf("invalid cluster version format: %s", clusterBuild)
+	}
 	clusterVersion := splitValues[0] + "." + splitValues[1]
 	return clusterVersion, clusterBuild, err
 }
📝 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
// GetClusterVersion returns the cluster version as string value (Ex: 4.8) and cluster build (Ex: 4.8.0-0.nightly-2021-09-28-165247)
func GetClusterVersion(oc *CLI) (string, string, error) {
clusterBuild, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("clusterversion", "-o", "jsonpath={..desired.version}").Output()
if err != nil {
return "", "", err
}
splitValues := strings.Split(clusterBuild, ".")
clusterVersion := splitValues[0] + "." + splitValues[1]
return clusterVersion, clusterBuild, err
}
// GetClusterVersion returns the cluster version as string value (Ex: 4.8) and cluster build (Ex: 4.8.0-0.nightly-2021-09-28-165247)
func GetClusterVersion(oc *CLI) (string, string, error) {
clusterBuild, err := oc.AsAdmin().WithoutNamespace().Run("get").Args("clusterversion", "-o", "jsonpath={..desired.version}").Output()
if err != nil {
return "", "", err
}
splitValues := strings.Split(clusterBuild, ".")
if len(splitValues) < 2 {
return "", "", fmt.Errorf("invalid cluster version format: %s", clusterBuild)
}
clusterVersion := splitValues[0] + "." + splitValues[1]
return clusterVersion, clusterBuild, err
}
🤖 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 `@test/extended-priv/util/clusters.go` around lines 23 - 32, GetClusterVersion
currently splits clusterBuild into splitValues and directly indexes [0] and [1],
which can panic if the version is malformed; add bounds checking after
strings.Split to verify len(splitValues) >= 2 and return a descriptive error
(including clusterBuild) if not, otherwise construct clusterVersion from
splitValues[0] + "." + splitValues[1] and return as before; ensure you still
return the original err (or nil) on success.

Comment on lines +60 to +86
func (sshClient *SshClient) RunOutput(cmd string) (string, error) {
config, err := sshClient.getConfig()
if err != nil {
return "", fmt.Errorf("failed to get SSH config: %v", err)
}

connection, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", sshClient.Host, sshClient.Port), config)
if err != nil {
return "", fmt.Errorf("failed to dial %s:%d: %v", sshClient.Host, sshClient.Port, err)
}
defer connection.Close()

session, err := connection.NewSession()
if err != nil {
return "", fmt.Errorf("failed to create session: %v", err)
}
defer session.Close()

buf := newSynchronizedBuffer()
session.Stdout = buf
session.Stderr = buf

if err := session.Run(cmd); err != nil {
return "", fmt.Errorf("failed to run cmd '%s': %v\n%s", cmd, err, buf.String())
}
return buf.String(), nil
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Use net.JoinHostPort for IPv6 compatibility.

Line 66 constructs the SSH address using fmt.Sprintf("%v:%v", sshClient.Host, sshClient.Port), which does not properly handle IPv6 addresses. IPv6 addresses must be wrapped in brackets (e.g., [2001:db8::1]:22). Use net.JoinHostPort instead to ensure both IPv4 and IPv6 addresses work correctly.

🌐 Proposed fix for IPv6 support
+import (
+	"net"
+	"strconv"
+)
+
 func (sshClient *SshClient) RunOutput(cmd string) (string, error) {
 	config, err := sshClient.getConfig()
 	if err != nil {
 		return "", fmt.Errorf("failed to get SSH config: %v", err)
 	}
 
-	connection, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", sshClient.Host, sshClient.Port), config)
+	address := net.JoinHostPort(sshClient.Host, strconv.Itoa(sshClient.Port))
+	connection, err := ssh.Dial("tcp", address, config)
 	if err != nil {
 		return "", fmt.Errorf("failed to dial %s:%d: %v", sshClient.Host, sshClient.Port, err)
 	}

As per coding guidelines: "Use net.JoinHostPort() for URL construction instead" when building addresses that may contain IPv6 hosts.

🤖 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 `@test/extended-priv/util/ssh_client.go` around lines 60 - 86, The SSH dial
address in SshClient.RunOutput is built with fmt.Sprintf("%v:%v",
sshClient.Host, sshClient.Port) which breaks for IPv6; change the address
construction to use net.JoinHostPort(sshClient.Host,
strconv.Itoa(sshClient.Port)) (importing net and strconv) and pass that result
to ssh.Dial so IPv4 and IPv6 hosts are handled correctly.

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 21, 2026

@ptalgulk01: 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/verify 853ccf5 link true /test verify

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

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants