Skip to content

POC: Expose virtio-win ISO via virt-artifacts-server#4373

Open
tiraboschi wants to merge 1 commit into
kubevirt:mainfrom
tiraboschi:poc_virtiowin_download
Open

POC: Expose virtio-win ISO via virt-artifacts-server#4373
tiraboschi wants to merge 1 commit into
kubevirt:mainfrom
tiraboschi:poc_virtiowin_download

Conversation

@tiraboschi

@tiraboschi tiraboschi commented Jul 1, 2026

Copy link
Copy Markdown
Member

What this PR does / why we need it:
The virtio-win image is already part of the CNV payload but only referenced as a string in a ConfigMap. This change makes the ISO directly downloadable by mounting it into the virt-artifacts-server pod using a Kubernetes image volume (GA in k8s 1.36 / OCP 4.23).

The image volume approach mounts the OCI image directly as a read-only volume via the container runtime — no init container, no copy, no ephemeral storage overhead. A subPath mount exposes only the ISO file (/disk/virtio-win.iso) at the server's document root.

The virt-artifacts-server is the natural home for this artifact: despite the deployment being named "cli-download", the underlying server image is "virt-artifacts-server" — a general-purpose artifact server, not a CLI-specific one. The virtio-win ISO is a downloadable binary artifact that users need, just like virtctl. Spinning up a dedicated deployment (with its own Service, Route, TLS, ServiceAccount) for a single static file would add operational overhead without architectural benefit.

Changes:

  • Add image volume referencing the virtio-win container image
  • Mount virtio-win.iso via subPath into the server container
  • Add virtio-win ISO download link to ConsoleCLIDownload
  • Add unit tests for the deployment spec changes
  • Add e2e test to verify the ISO is downloadable

Reviewer Checklist

Reviewers are supposed to review the PR for every aspect below one by one. To check an item means the PR is either "OK" or "Not Applicable" in terms of that item. All items are supposed to be checked before merging a PR.

  • PR Message
  • Commit Messages
  • How to test
  • Unit Tests
  • Functional Tests
  • User Documentation
  • Developer Documentation
  • Upgrade Scenario
  • Uninstallation Scenario
  • Backward Compatibility
  • Troubleshooting Friendly

Jira Ticket:

https://redhat.atlassian.net/browse/CNV-42977

Release note:

Expose virtio-win ISO via virt-artifacts-server

@kubevirt-prow kubevirt-prow Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. labels Jul 1, 2026
@kubevirt-prow kubevirt-prow Bot requested review from avlitman and nunnatsa July 1, 2026 11:22
@kubevirt-prow

kubevirt-prow Bot commented Jul 1, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

@kubevirt-prow kubevirt-prow Bot added the size/L label Jul 1, 2026
@coveralls

coveralls commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 28525587818

Coverage increased (+0.7%) to 82.097%

Details

  • Coverage increased (+0.7%) from the base build.
  • Patch coverage: 23 of 23 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 13947
Covered Lines: 11450
Line Coverage: 82.1%
Coverage Strength: 2.19 hits per line

💛 - Coveralls

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2165dc96-602f-4c67-9c37-135bdf5e7216

📥 Commits

Reviewing files that changed from the base of the PR and between a9cabc2 and 48d9b56.

📒 Files selected for processing (10)
  • controllers/handlers/cliDownload.go
  • controllers/handlers/cliDownload_test.go
  • deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/operator.yaml
  • pkg/components/components.go
  • pkg/components/components_suite_test.go
  • pkg/components/components_test.go
  • tests/func-tests/cli_download_test.go
  • tools/csv-merger/csv-merger.go
✅ Files skipped from review due to trivial changes (1)
  • controllers/handlers/cliDownload.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • pkg/components/components_test.go
  • tools/csv-merger/csv-merger.go
  • pkg/components/components_suite_test.go
  • controllers/handlers/cliDownload_test.go
  • deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/operator.yaml
  • deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • pkg/components/components.go

📝 Walkthrough

Walkthrough

This PR adds a virtio-win ISO link to ConsoleCLIDownload, updates the CLI download deployment to mount that ISO from an image-backed virtio-win-data volume, updates the generated CSV/manifests to match, and extends unit, component, and functional tests to validate the new link and file-serving path.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Related PRs: None provided.

Suggested labels: enhancement, tests, area/console-cli-download

Suggested reviewers: Reviewers familiar with controllers/handlers, pkg/components, and the CLI download functional test path.

Poem:
Eight links now point where seven once did,
The ISO rides in, safely hid;
Mounts and tests now line up clean,
A compact change, precise and clean.

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 13 linked repositories, but your current plan allows 0. Analyzed ``, skipped kubevirt/kubevirt, `kubevirt/containerized-data-importer`, `kubevirt/ssp-operator`, `kubevirt/cluster-network-addons-operator`, `kubevirt/hostpath-provisioner-operator`, `kubevirt/application-aware-quota`, `kubevirt/managed-tenant-quota`, `kubevirt/hyperconverged-cluster-operator`, `kubevirt/monitoring`, `kubevirt/community`, `kubevirt/enhancements`, `kubevirt/project-infra`, `kubevirt/kubevirtci`.


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.

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/components/components.go (1)

279-347: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Extract repeated literals into shared constants.

"virtio-win-data" is duplicated three times (Lines 297, 327, 340) and "768Mi" is repeated five times across requests/limits/size-limit. SonarCloud flags the volume-name duplication; both should be shared constants to avoid drift if either value changes.

♻️ Proposed fix
+const (
+	virtioWinDataVolumeName = "virtio-win-data"
+	virtioWinISOStorageSize = "768Mi"
+)
+
 func GetDeploymentSpecCliDownloads(params *DeploymentOperatorParams) appsv1.DeploymentSpec {
 	return appsv1.DeploymentSpec{
 		...
 				InitContainers: []corev1.Container{
 					{
 						Name:            "virtio-win-init",
 						...
 						Resources: corev1.ResourceRequirements{
 							Requests: map[corev1.ResourceName]resource.Quantity{
 								corev1.ResourceCPU:              resource.MustParse("10m"),
 								corev1.ResourceMemory:           resource.MustParse("32Mi"),
-								corev1.ResourceEphemeralStorage: resource.MustParse("768Mi"),
+								corev1.ResourceEphemeralStorage: resource.MustParse(virtioWinISOStorageSize),
 							},
 							Limits: map[corev1.ResourceName]resource.Quantity{
-								corev1.ResourceEphemeralStorage: resource.MustParse("768Mi"),
+								corev1.ResourceEphemeralStorage: resource.MustParse(virtioWinISOStorageSize),
 							},
 						},
 						VolumeMounts: []corev1.VolumeMount{
 							{
-								Name:      "virtio-win-data",
+								Name:      virtioWinDataVolumeName,
 								MountPath: "/virtio-win-data",
 							},
 						},
 						...
 					},
 				},
 				Containers: []corev1.Container{
 					{
 						...
 						VolumeMounts: []corev1.VolumeMount{
 							{
-								Name:      "virtio-win-data",
+								Name:      virtioWinDataVolumeName,
 								MountPath: "/home/server/src/virtio-win",
 								ReadOnly:  true,
 							},
 						},
 						...
 					},
 				},
 				Volumes: []corev1.Volume{
 					{
-						Name: "virtio-win-data",
+						Name: virtioWinDataVolumeName,
 						VolumeSource: corev1.VolumeSource{
 							EmptyDir: &corev1.EmptyDirVolumeSource{
-								SizeLimit: ptr.To(resource.MustParse("768Mi")),
+								SizeLimit: ptr.To(resource.MustParse(virtioWinISOStorageSize)),
 							},
 						},
 					},
 				},

As per path instructions, "prefer shared constants for feature-gate names, annotation/label keys, and any repeated string literals". Also flagged by static analysis.

🤖 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 `@pkg/components/components.go` around lines 279 - 347, The pod spec in
components.go repeats the same volume name and size literals in the init
container, server container, and volume definition. Extract the duplicated
"virtio-win-data" and "768Mi" values into shared constants near the related
builders/helpers, then reference those constants from the container volume
mounts, resource requests/limits, and EmptyDir SizeLimit in the affected
pod/template construction code.

Sources: Path instructions, Linters/SAST tools

🧹 Nitpick comments (2)
tests/func-tests/cli_download_test.go (1)

81-118: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: extract the link-lookup loop into a small helper.

Lines 90-96 duplicate the "find link by substring" pattern used elsewhere in this file. A small helper (e.g., findLinkByHref(links, substr string) string) would reduce duplication if more link-specific tests are added later. As per path instructions, prefer helper functions over inline matcher-heavy logic in tests.

🤖 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 `@tests/func-tests/cli_download_test.go` around lines 81 - 118, The virtio-win
download test in the ConsoleCLIDownload checks repeats the same “find link by
substring” logic used elsewhere, so factor that lookup into a small helper and
reuse it here. Add or reuse a helper like the existing link-finding pattern near
the `ConsoleCLIDownload` test code, then call it from the `It("should expose
virtio-win ISO for download")` block instead of keeping the inline loop.

Source: Path instructions

pkg/components/components.go (1)

279-303: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider setting TerminationMessagePolicy on the init container for troubleshooting.

The server container sets TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError (Line 335) but virtio-win-init does not. If the cp command fails, defaulting to log output would help diagnose the failure faster.

🤖 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 `@pkg/components/components.go` around lines 279 - 303, The virtio-win init
container is missing a termination message policy, which makes failures harder
to troubleshoot. Update the `virtio-win-init` container definition in
`components.go` to set `TerminationMessagePolicy` the same way as the `server`
container, using `corev1.TerminationMessageFallbackToLogsOnError`, so `cp`
errors surface in logs automatically.
🤖 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 `@tests/func-tests/cli_download_test.go`:
- Around line 99-107: The ISO HEAD request in the cli download test can hang
indefinitely because the local httpClient is created without a timeout. Update
the httpClient setup in the download test to include a reasonable Timeout, using
the same pattern as the "URL Download customization" test, so the Head call on
virtioWinLink fails fast if the server is unresponsive.

---

Outside diff comments:
In `@pkg/components/components.go`:
- Around line 279-347: The pod spec in components.go repeats the same volume
name and size literals in the init container, server container, and volume
definition. Extract the duplicated "virtio-win-data" and "768Mi" values into
shared constants near the related builders/helpers, then reference those
constants from the container volume mounts, resource requests/limits, and
EmptyDir SizeLimit in the affected pod/template construction code.

---

Nitpick comments:
In `@pkg/components/components.go`:
- Around line 279-303: The virtio-win init container is missing a termination
message policy, which makes failures harder to troubleshoot. Update the
`virtio-win-init` container definition in `components.go` to set
`TerminationMessagePolicy` the same way as the `server` container, using
`corev1.TerminationMessageFallbackToLogsOnError`, so `cp` errors surface in logs
automatically.

In `@tests/func-tests/cli_download_test.go`:
- Around line 81-118: The virtio-win download test in the ConsoleCLIDownload
checks repeats the same “find link by substring” logic used elsewhere, so factor
that lookup into a small helper and reuse it here. Add or reuse a helper like
the existing link-finding pattern near the `ConsoleCLIDownload` test code, then
call it from the `It("should expose virtio-win ISO for download")` block instead
of keeping the inline loop.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b902b353-c055-403c-900a-cef42fb76524

📥 Commits

Reviewing files that changed from the base of the PR and between 7c66468 and 8f26aef.

📒 Files selected for processing (6)
  • controllers/handlers/cliDownload.go
  • controllers/handlers/cliDownload_test.go
  • pkg/components/components.go
  • pkg/components/components_suite_test.go
  • pkg/components/components_test.go
  • tests/func-tests/cli_download_test.go

Comment thread tests/func-tests/cli_download_test.go
@tiraboschi tiraboschi force-pushed the poc_virtiowin_download branch 3 times, most recently from 239691b to 326c5c2 Compare July 1, 2026 12:27

@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: 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 `@deploy/operator.yaml`:
- Around line 293-317: The new virtio-win-init initContainer is missing a
hardened root filesystem setting. Update the securityContext for the
virtio-win-init container in the deployment manifest to set
readOnlyRootFilesystem to true, alongside the existing capability drop and
privilege escalation settings, since it only writes to the mounted
virtio-win-data volume.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 64eaa81b-1cd7-417e-a8fb-639b53641583

📥 Commits

Reviewing files that changed from the base of the PR and between 896ef84 and 326c5c2.

📒 Files selected for processing (9)
  • controllers/handlers/cliDownload.go
  • controllers/handlers/cliDownload_test.go
  • deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/operator.yaml
  • pkg/components/components.go
  • pkg/components/components_suite_test.go
  • pkg/components/components_test.go
  • tests/func-tests/cli_download_test.go
✅ Files skipped from review due to trivial changes (3)
  • pkg/components/components_suite_test.go
  • controllers/handlers/cliDownload_test.go
  • controllers/handlers/cliDownload.go

Comment thread deploy/operator.yaml
@tiraboschi tiraboschi force-pushed the poc_virtiowin_download branch from 326c5c2 to c202ec8 Compare July 1, 2026 12:34
@tiraboschi

Copy link
Copy Markdown
Member Author

@coderabbitai could you please review it again? I reworked it to rely on image volume (GA in k8s 1.36)

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd -a components.go pkg/components | xargs -I{} echo {}
echo "---components.go---"
cat -n pkg/components/components.go | sed -n '1,50p'
echo "---search virtio---"
rg -n -i 'virtio' pkg/components/components.go
echo "---full relevant function---"
ast-grep run --pattern 'func GetDeploymentSpecCliDownloads($$$) $$$' --lang go pkg/components/components.go

Length of output: 7601


🤖 web_search executed:

When did the Kubernetes "image volume" (OCI VolumeSource, ImageVolumeSource) feature go GA? What Kubernetes version and feature gate name?

Length of output: 12007


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---CSV files search for virtio-win-data---"
rg -n "virtio-win-data\|virtio-win-init\|ImageVolumeSource\|emptyDir" -i deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml | head -50
echo "---operator.yaml---"
rg -n -i "virtio-win" deploy/operator.yaml
echo "---components_test.go---"
cat -n pkg/components/components_test.go
echo "---cliDownload.go---"
cat -n controllers/handlers/cliDownload.go | sed -n '1,80p'
echo "---check minimum kube version supported---"
rg -n -i "kubeVersion" deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/*.yaml | head -5

Length of output: 1043


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---CSV files search---"
rg -n -i 'virtio-win-data|virtio-win-init|ImageVolumeSource|emptyDir' deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml || true
echo "---operator.yaml---"
rg -n -i "virtio-win" deploy/operator.yaml || true
echo "---components_test.go---"
cat -n pkg/components/components_test.go || true
echo "---cliDownload.go---"
cat -n controllers/handlers/cliDownload.go | sed -n '1,80p'
echo "---kubeVersion in CSV---"
rg -n -i "kubeVersion|minKubeVersion" deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/*.yaml || true
echo "---check pullPolicy field default in ImageVolumeSource---"
rg -n "ImageVolumeSource" -A5 $(go env GOPATH 2>/dev/null)/pkg/mod/k8s.io/api*/core/v1/types.go 2>/dev/null || true
echo "---go.mod k8s version---"
rg -n "k8s.io/api " go.mod

Length of output: 7224


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---context around virtio-win-data in generated CSV (index-image)---"
sed -n '4300,4400p' deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
echo "---context around emptyDir at 4637---"
sed -n '4600,4650p' deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
echo "---olm-catalog csv search---"
rg -n -i 'virtio-win-data|virtio-win-init|image:|emptyDir|reference:' deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml | rg -i 'virtio' -A2 -B2 || true
echo "---git diff stat for this PR (compare with main)---"
git log --oneline -5

Length of output: 8930


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---search for supported OCP/kubernetes version docs---"
rg -n -i 'minimum.*(kubernetes|openshift|ocp)|supported.*(kubernetes|openshift|ocp)' README.md docs/*.md 2>/dev/null | head -30
fd -e md -i readme
echo "---search for maxKubeVersion / edge cases---"
rg -n -i 'ImageVolumeSource|image volume' -g '!*.yaml' . 2>/dev/null | grep -v vendor | head -20
echo "---check vendor for corev1.ImageVolumeSource definition to see PullPolicy default---"
find / -path /proc -prune -o -type d -name 'k8s.io' -print 2>/dev/null | head

Length of output: 2613


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -i 'olm.skipRange|com.redhat.openshift.versions|kubeVersion' deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/*.yaml deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/metadata/*.yaml 2>/dev/null || true
fd annotations.yaml deploy/olm-catalog | head
cat deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/metadata/annotations.yaml 2>/dev/null || true

Length of output: 1839


Hi @tiraboschi, thanks for reworking this — the new approach in pkg/components/components.go (Lines 297-320) is much cleaner than the initContainer/emptyDir plumbing from before. Dropping the ephemeral-storage sizing and the copy step is a nice simplification, and the new unit tests in pkg/components/components_test.go cover the volume, mount, and resource expectations well. I also confirmed the generated CSV manifests for 1.19.0 were correctly regenerated to reflect this (no stale init-container/emptyDir leftovers).

Two things I'd like to flag before this is safe to merge:

  1. Backward compatibility / minimum supported Kubernetes version. I checked upstream docs: the image volume source (corev1.ImageVolumeSource) went alpha in Kubernetes 1.31 (feature-gated, disabled by default), beta and enabled-by-default in 1.35, and GA only in 1.36 (you called this out correctly). HCO/CNV typically needs to support OpenShift releases that bundle older Kubernetes versions. I didn't find any kubeVersion/com.redhat.openshift.versions constraint in the bundle metadata (deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/metadata/annotations.yaml) that would prevent installation on a cluster where this feature is unavailable or disabled. On such clusters, the cli-download pod would fail to mount the volume (and possibly fail to schedule), silently breaking virtctl/ISO downloads. Could you confirm the minimum OCP/Kubernetes version this HCO release targets, and whether it's guaranteed to have ImageVolume at least in beta+default-on (1.35+)? If not, this needs either a version gate, a fallback path, or an explicit note in release/upgrade docs.
  2. Explicit pullPolicy on the image volume. In pkg/components/components.go Line 311-319, the ImageVolumeSource doesn't set PullPolicy. Given the virtio-win image is ~609MB, relying on the implicit default could cause unnecessary re-pulls on pod restarts. Consider setting it explicitly (e.g., IfNotPresent, consistent with params.ImagePullPolicy used for the server container) for predictable behavior.

Everything else — the test coverage, the e2e HEAD-request check, and the ConsoleCLIDownload link addition — looks solid. Nice cleanup overall, just want to make sure the Kubernetes-version dependency is a conscious, documented decision before this ships.

✅ 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.

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

🧹 Nitpick comments (1)
deploy/operator.yaml (1)

298-301: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider explicit pullPolicy on the virtio-win image volume.

The virtio-win-data volume's ImageVolumeSource only sets reference, with no pullPolicy. Since the image is referenced by digest, the kubelet default pull policy is effectively IfNotPresent already, but explicitly setting it avoids relying on that implicit behavior and matches the concern already raised in this PR's review thread for this large image.

♻️ Proposed fix
       volumes:
       - image:
           reference: quay.io/kubevirt/virtio-container-disk@sha256:6b823946eb7493347a93d6daa16b4101a68e16a0ee1766e01ac3adf82e4b5838
+          pullPolicy: IfNotPresent
         name: virtio-win-data
🤖 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.yaml` around lines 298 - 301, The virtio-win image volume
currently sets only the image reference in the `virtio-win-data`
`ImageVolumeSource`, so add an explicit `pullPolicy` there to make the intent
clear and match the existing review concerns. Update the `volumes` entry for
`virtio-win-data` in `operator.yaml` by setting the pull policy alongside the
digest-based `reference`, using the same image volume configuration block to
keep the behavior explicit and consistent.
🤖 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.

Nitpick comments:
In `@deploy/operator.yaml`:
- Around line 298-301: The virtio-win image volume currently sets only the image
reference in the `virtio-win-data` `ImageVolumeSource`, so add an explicit
`pullPolicy` there to make the intent clear and match the existing review
concerns. Update the `volumes` entry for `virtio-win-data` in `operator.yaml` by
setting the pull policy alongside the digest-based `reference`, using the same
image volume configuration block to keep the behavior explicit and consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d472c3ee-5153-452c-93df-3ba5fa29f503

📥 Commits

Reviewing files that changed from the base of the PR and between 326c5c2 and c202ec8.

📒 Files selected for processing (9)
  • controllers/handlers/cliDownload.go
  • controllers/handlers/cliDownload_test.go
  • deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/operator.yaml
  • pkg/components/components.go
  • pkg/components/components_suite_test.go
  • pkg/components/components_test.go
  • tests/func-tests/cli_download_test.go
✅ Files skipped from review due to trivial changes (2)
  • controllers/handlers/cliDownload.go
  • controllers/handlers/cliDownload_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/components/components_suite_test.go
  • pkg/components/components_test.go
  • pkg/components/components.go

@tiraboschi tiraboschi force-pushed the poc_virtiowin_download branch from c202ec8 to a9cabc2 Compare July 1, 2026 14:26

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

🧹 Nitpick comments (1)
tools/csv-merger/csv-merger.go (1)

257-258: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider naming the hardcoded version.

"1.36.0" is embedded directly as a literal. Extracting it to a named constant (e.g., minKubeVersionForImageVolumes) would make the reason for the bump self-documenting and easier to update if the requirement changes again.

As per path instructions, go.md recommends "Use shared constants for feature gate names, annotation keys, and label values; avoid duplicated string literals when introducing new ones in this PR's code paths."

♻️ Proposed refactor
+// minKubeVersionForImageVolumes is the minimum Kubernetes version required
+// for the ImageVolumeSource used to mount the virtio-win ISO (GA in k8s v1.36).
+const minKubeVersionForImageVolumes = "1.36.0"
+
 	if *testImagesNVRs != "" {
 		csvBase.Annotations["test-images-nvrs"] = *testImagesNVRs
 	}

-	csvBase.Spec.MinKubeVersion = "1.36.0"
+	csvBase.Spec.MinKubeVersion = minKubeVersionForImageVolumes
🤖 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 `@tools/csv-merger/csv-merger.go` around lines 257 - 258, The hardcoded minimum
Kubernetes version in csv-merger.go should be named instead of embedded as a
literal. Extract "1.36.0" into a shared constant near the csv merging logic and
assign csvBase.Spec.MinKubeVersion from that constant, so the version bump is
self-documenting and easy to update later. Use a descriptive symbol name such as
minKubeVersionForImageVolumes and keep the change localized to the
csvBase.Spec.MinKubeVersion assignment path.

Source: Path instructions

🤖 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.

Nitpick comments:
In `@tools/csv-merger/csv-merger.go`:
- Around line 257-258: The hardcoded minimum Kubernetes version in csv-merger.go
should be named instead of embedded as a literal. Extract "1.36.0" into a shared
constant near the csv merging logic and assign csvBase.Spec.MinKubeVersion from
that constant, so the version bump is self-documenting and easy to update later.
Use a descriptive symbol name such as minKubeVersionForImageVolumes and keep the
change localized to the csvBase.Spec.MinKubeVersion assignment path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dc13fd3e-6498-44af-ad52-af25410fc0fd

📥 Commits

Reviewing files that changed from the base of the PR and between c202ec8 and a9cabc2.

📒 Files selected for processing (10)
  • controllers/handlers/cliDownload.go
  • controllers/handlers/cliDownload_test.go
  • deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • deploy/operator.yaml
  • pkg/components/components.go
  • pkg/components/components_suite_test.go
  • pkg/components/components_test.go
  • tests/func-tests/cli_download_test.go
  • tools/csv-merger/csv-merger.go
✅ Files skipped from review due to trivial changes (2)
  • controllers/handlers/cliDownload_test.go
  • controllers/handlers/cliDownload.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • deploy/operator.yaml
  • pkg/components/components_test.go
  • deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml
  • pkg/components/components_suite_test.go
  • pkg/components/components.go

The virtio-win image is already part of the CNV payload but only
referenced as a string in a ConfigMap. This change makes the ISO
directly downloadable by mounting it into the virt-artifacts-server
pod using a Kubernetes image volume (stable in k8s 1.36 / OCP 4.23).

The image volume approach mounts the OCI image directly as a read-only
volume via the container runtime — no init container, no copy, no
ephemeral storage overhead. A subPath mount exposes only the ISO file
(/disk/virtio-win.iso) at the server's document root.

The virt-artifacts-server is the natural home for this artifact: despite
the deployment being named "cli-download", the underlying server image
is "virt-artifacts-server" — a general-purpose artifact server, not a
CLI-specific one. The virtio-win ISO is a downloadable binary artifact
that users need, just like virtctl. Spinning up a dedicated deployment
(with its own Service, Route, TLS, ServiceAccount) for a single static
file would add operational overhead without architectural benefit.

Changes:
- Add image volume referencing the virtio-win container image
- Mount virtio-win.iso via subPath into the server container
- Add virtio-win ISO download link to ConsoleCLIDownload
- Set minKubeVersion to 1.36.0 in CSV spec (required for image volumes)
- Add unit tests for the deployment spec changes
- Add e2e test to verify the ISO is downloadable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simone Tiraboschi <stirabos@redhat.com>
@tiraboschi tiraboschi force-pushed the poc_virtiowin_download branch from a9cabc2 to 48d9b56 Compare July 1, 2026 14:37
@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

@tiraboschi

Copy link
Copy Markdown
Member Author

@coderabbitai could you please review it again?

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---components.go ImageVolumeSource block---"
rg -n -B5 -A15 'ImageVolumeSource' pkg/components/components.go
echo "---csv-merger.go minKubeVersion---"
rg -n -B3 -A3 'minKubeVersion|MinKubeVersion' tools/csv-merger/csv-merger.go
echo "---CSV files minKubeVersion---"
rg -n 'minKubeVersion' deploy/index-image/community-kubevirt-hyperconverged/1.19.0/manifests/*.yaml deploy/olm-catalog/community-kubevirt-hyperconverged/1.19.0/manifests/*.yaml deploy/operator.yaml || true

Length of output: 10731


Confirmed — both concerns from my previous review have been addressed.

@tiraboschi, looks great — both items from my previous pass are now resolved:

  1. Minimum Kubernetes version gate: tools/csv-merger/csv-merger.go now defines minKubeVersion = "1.36.0" (Line 65) and applies it via csvBase.Spec.MinKubeVersion = minKubeVersion (Line 258). Both generated CSVs (deploy/olm-catalog/.../kubevirt-hyperconverged-operator.v1.19.0.clusterserviceversion.yaml and the index-image counterpart) correctly reflect minKubeVersion: 1.36.0 at Line 6119. This ensures OLM will block installation on clusters that predate GA support for ImageVolumeSource, closing the backward-compatibility gap I raised.
  2. Explicit pullPolicy: pkg/components/components.go Lines 315-318 now set PullPolicy: corev1.PullPolicy(params.ImagePullPolicy) on the ImageVolumeSource, consistent with the pull policy used elsewhere for this deployment. This avoids unpredictable/unnecessary re-pulls of the virtio-win image.

Nothing else stands out — the volume/mount wiring, tests, and generated manifests are all consistent. Nicely done cleaning this up.

✅ 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.

@tiraboschi

Copy link
Copy Markdown
Member Author

/retest

@openshift-ci

openshift-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown

@tiraboschi: The following tests 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/hco-e2e-upgrade-prev-operator-sdk-sno-aws 48d9b56 link false /test hco-e2e-upgrade-prev-operator-sdk-sno-aws
ci/prow/hco-e2e-operator-sdk-sno-aws 48d9b56 link false /test hco-e2e-operator-sdk-sno-aws
ci/prow/hco-e2e-operator-sdk-sno-azure 48d9b56 link false /test hco-e2e-operator-sdk-sno-azure
ci/prow/hco-e2e-operator-sdk-aws 48d9b56 link true /test hco-e2e-operator-sdk-aws
ci/prow/hco-e2e-upgrade-operator-sdk-sno-aws 48d9b56 link false /test hco-e2e-upgrade-operator-sdk-sno-aws
ci/prow/hco-e2e-kv-smoke-azure 48d9b56 link true /test hco-e2e-kv-smoke-azure
ci/prow/hco-e2e-consecutive-operator-sdk-upgrades-aws 48d9b56 link true /test hco-e2e-consecutive-operator-sdk-upgrades-aws
ci/prow/hco-e2e-upgrade-prev-operator-sdk-sno-azure 48d9b56 link false /test hco-e2e-upgrade-prev-operator-sdk-sno-azure
ci/prow/hco-e2e-upgrade-prev-operator-sdk-aws 48d9b56 link true /test hco-e2e-upgrade-prev-operator-sdk-aws
ci/prow/hco-e2e-operator-sdk-gcp 48d9b56 link true /test hco-e2e-operator-sdk-gcp
ci/prow/hco-e2e-kv-smoke-gcp 48d9b56 link true /test hco-e2e-kv-smoke-gcp
ci/prow/hco-e2e-upgrade-operator-sdk-aws 48d9b56 link true /test hco-e2e-upgrade-operator-sdk-aws
ci/prow/hco-e2e-upgrade-prev-operator-sdk-azure 48d9b56 link true /test hco-e2e-upgrade-prev-operator-sdk-azure
ci/prow/hco-e2e-upgrade-operator-sdk-azure 48d9b56 link true /test hco-e2e-upgrade-operator-sdk-azure
ci/prow/hco-e2e-operator-sdk-azure 48d9b56 link true /test hco-e2e-operator-sdk-azure
ci/prow/hco-e2e-upgrade-operator-sdk-sno-azure 48d9b56 link false /test hco-e2e-upgrade-operator-sdk-sno-azure
ci/prow/hco-e2e-consecutive-operator-sdk-upgrades-azure 48d9b56 link true /test hco-e2e-consecutive-operator-sdk-upgrades-azure

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

dco-signoff: yes Indicates the PR's author has DCO signed all their commits. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants