Skip to content

STOR-2997: Minimal implementation of GCP PD CSI driver operator#576

Open
mpatlasov wants to merge 4 commits into
openshift:mainfrom
mpatlasov:STOR-2997-Implement-GCP-PD-CSI-driver-operator-inside-csi-operator-framework
Open

STOR-2997: Minimal implementation of GCP PD CSI driver operator#576
mpatlasov wants to merge 4 commits into
openshift:mainfrom
mpatlasov:STOR-2997-Implement-GCP-PD-CSI-driver-operator-inside-csi-operator-framework

Conversation

@mpatlasov

@mpatlasov mpatlasov commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

This PR implements the minimal set of go-files and yaml-assets to enable the command

./bin/gcp-pd-csi-driver-operator start --kubeconfig $KUBECONFIG --namespace openshift-cluster-csi-drivers

to install and run GCP PD CSI driver:

gcp-pd-csi-driver-controller-c949b748-xkljz   10/10   Running   0          3m2s
gcp-pd-csi-driver-controller-c949b748-xvgl9   10/10   Running   0          3m2s
gcp-pd-csi-driver-node-5kcw5                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-frl74                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-gf9k7                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-p95sv                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-q4r98                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-xvmgq                  3/3     Running   0          3m2s

/cc @openshift/storage

@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 8, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 8, 2026

Copy link
Copy Markdown

@mpatlasov: This pull request references STOR-2997 which is a valid jira issue.

Details

In response to this:

This PR implements the minimal set of go-files and yaml-assets to enable the command

./bin/gcp-pd-csi-driver-smb-operator start --kubeconfig $KUBECONFIG --namespace openshift-cluster-csi-drivers

to install and run GCP PD CSI driver:

gcp-pd-csi-driver-controller-c949b748-xkljz   10/10   Running   0          3m2s
gcp-pd-csi-driver-controller-c949b748-xvgl9   10/10   Running   0          3m2s
gcp-pd-csi-driver-node-5kcw5                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-frl74                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-gf9k7                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-p95sv                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-q4r98                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-xvmgq                  3/3     Running   0          3m2s

/cc @openshift/storage

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

@openshift-ci

openshift-ci Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov: GitHub didn't allow me to request PR reviews from the following users: openshift/storage.

Note that only openshift members and repo collaborators can review this PR, and authors cannot review their own PRs.

Details

In response to this:

This PR implements the minimal set of go-files and yaml-assets to enable the command

./bin/gcp-pd-csi-driver-smb-operator start --kubeconfig $KUBECONFIG --namespace openshift-cluster-csi-drivers

to install and run GCP PD CSI driver:

gcp-pd-csi-driver-controller-c949b748-xkljz   10/10   Running   0          3m2s
gcp-pd-csi-driver-controller-c949b748-xvgl9   10/10   Running   0          3m2s
gcp-pd-csi-driver-node-5kcw5                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-frl74                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-gf9k7                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-p95sv                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-q4r98                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-xvmgq                  3/3     Running   0          3m2s

/cc @openshift/storage

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.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a GCP PD CSI Driver Operator CLI entrypoint with Cobra-based root and start commands. Defines operator and controller configuration, including standalone cluster validation, privileged binding removal, Infrastructure CR polling, and region-specific StorageClass selection. Adds selector support for generated StorageClass assets, updates the Dockerfile to build from the repository workspace, and adds the required RBAC binding manifest.


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Ote Binary Stdout Contract ❌ Error main() root Run calls cmd.Help() with no stdout redirection, so the no-subcommand path emits help text on stdout. Send Cobra output to stderr (SetOut/SetErr), or remove the root help path and keep process startup silent.
Container-Privileges ❌ Error Branch adds new GCP PD manifests with hostNetwork: true and privileged: true in controller.yaml/node.yaml, plus RBAC for privileged SCC. Remove these securityContext/hostNetwork privileges or document and minimize them; avoid privileged SCC usage unless strictly required.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: a minimal implementation of the GCP PD CSI driver operator.
Description check ✅ Passed The description directly matches the changeset and explains the operator command and assets being added.
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 The new tests use static t.Run names only; no Ginkgo titles or dynamic values like pod names, UUIDs, dates, or namespaces appear.
Test Structure And Quality ✅ Passed The new tests are focused table-driven unit tests, use context timeouts, create no cluster resources, and include useful failure messages consistent with repo patterns.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the only new test file uses standard Go testing and no MicroShift-unsupported APIs.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the new tests are plain Go unit tests using testing.T, with no multi-node assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed No unsafe topology assumptions were introduced: controller anti-affinity is preferred with maxUnavailable 1, replicas are handled by the shared topology-aware hook, and HyperShift is explicitly rej...
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the only new test is a unit test, and it has no IPv4-specific or external-network assumptions.
No-Weak-Crypto ✅ Passed No MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret comparisons appear in the changed files.
No-Sensitive-Data-In-Logs ✅ Passed Scanned all touched files; logs only mention controller names, regions, asset paths, and generic errors—no passwords, tokens, PII, or secrets exposed.
✨ 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 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mpatlasov

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

The pull request process is described here

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

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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 8, 2026

@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 (2)
pkg/driver/gcp-pd/gcp_pd.go (1)

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

Fix malformed log call and redundant/non-idiomatic error message.

klog.Error(nil, "...") treats nil as a fmt.Print-style argument (klog's Error args are "handled in the manner of fmt.Print"), so this prints something like <nil>Flavour HyperShift is not supported! instead of a clean message. Additionally, this error is already logged again by the caller (RunOperator logs "error building operator config: %v" on any non-nil error from this builder), so the local klog.Error call is redundant. The fmt.Errorf message is also capitalized and ends with !, which violates Go's error-string convention (lower-case, no trailing punctuation).

🔧 Proposed fix
 	if flavour != generator.FlavourStandalone {
-		klog.Error(nil, "Flavour HyperShift is not supported!")
-		return nil, fmt.Errorf("Flavour HyperShift is not supported!")
+		return nil, fmt.Errorf("flavour %q is not supported", flavour)
 	}
🤖 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/driver/gcp-pd/gcp_pd.go` around lines 36 - 39, The gcp_pd builder’s
unsupported-flavour branch is logging incorrectly and returning a non-idiomatic
error. In the config builder path in `gcp_pd.go`, remove the local
`klog.Error(nil, ...)` call because `RunOperator` already logs builder failures,
and change the returned `fmt.Errorf` message to a lowercase, punctuation-free
error string. Keep the check on `flavour != generator.FlavourStandalone` and
ensure the branch only returns the clean error.
cmd/gcp-pd-csi-driver-operator/main.go (1)

27-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Ignored error return from cmd.Help().

cmd.Help() returns an error that's discarded here.

🔧 Proposed fix
 		Run: func(cmd *cobra.Command, args []string) {
-			cmd.Help()
+			if err := cmd.Help(); err != nil {
+				klog.Errorf("failed to print help: %v", err)
+			}
 			os.Exit(1)
 		},

As per path instructions, "Never ignore error returns" for **/*.go.

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

In `@cmd/gcp-pd-csi-driver-operator/main.go` around lines 27 - 30, The cobra
command’s Run handler is discarding the error from cmd.Help(), which violates
the “never ignore error returns” rule. Update the Run function in main.go to
check and handle the return value from cmd.Help() explicitly, using the
cmd.Help() call itself as the unique locator, and ensure the process still exits
with a non-zero status if Help fails.

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 `@cmd/gcp-pd-csi-driver-operator/main.go`:
- Around line 27-30: The cobra command’s Run handler is discarding the error
from cmd.Help(), which violates the “never ignore error returns” rule. Update
the Run function in main.go to check and handle the return value from cmd.Help()
explicitly, using the cmd.Help() call itself as the unique locator, and ensure
the process still exits with a non-zero status if Help fails.

In `@pkg/driver/gcp-pd/gcp_pd.go`:
- Around line 36-39: The gcp_pd builder’s unsupported-flavour branch is logging
incorrectly and returning a non-idiomatic error. In the config builder path in
`gcp_pd.go`, remove the local `klog.Error(nil, ...)` call because `RunOperator`
already logs builder failures, and change the returned `fmt.Errorf` message to a
lowercase, punctuation-free error string. Keep the check on `flavour !=
generator.FlavourStandalone` and ensure the branch only returns the clean error.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: 51202570-b405-4a12-9cee-b72111c8a207

📥 Commits

Reviewing files that changed from the base of the PR and between 1c2b08b and 5ed0670.

⛔ Files ignored due to path filters (30)
  • assets/overlays/gcp-pd/generated/standalone/cabundle_cm.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_pdb.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/csidriver.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_attacher_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_snapshotter_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/manifests.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_privileged_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/privileged_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/service.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/servicemonitor.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_ssd.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshot_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass_images.yaml is excluded by !**/generated/**
📒 Files selected for processing (2)
  • cmd/gcp-pd-csi-driver-operator/main.go
  • pkg/driver/gcp-pd/gcp_pd.go

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest-required

2 similar comments
@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest-required

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest-required

@rhrmo

rhrmo commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

/test hypershift-e2e-aks

@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

🧹 Nitpick comments (2)
Dockerfile.gcp-pd (2)

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

Avoid copying entire build context.

COPY . . copies the full repository into the builder stage instead of specific files/directories needed for the build. As per path instructions, "COPY specific files, not entire context."

🤖 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 `@Dockerfile.gcp-pd` at line 3, Replace the broad COPY instruction in the
Docker build stage with explicit COPY directives for only the files and
directories required by the build, excluding the rest of the repository context.

Source: Path instructions


6-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Missing HEALTHCHECK instruction.

No HEALTHCHECK is defined for the final image. As per path instructions, "HEALTHCHECK defined."

🤖 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 `@Dockerfile.gcp-pd` around lines 6 - 10, Add a HEALTHCHECK instruction to the
final image definition in Dockerfile.gcp-pd, alongside the existing ENTRYPOINT
and LABEL directives. Configure it to invoke an appropriate health probe for
gcp-pd-csi-driver-operator and preserve the current startup command.

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.

Inline comments:
In `@Dockerfile.gcp-pd`:
- Around line 6-10: Update the final image stage in the Dockerfile around the
gcp-pd-csi-driver-operator ENTRYPOINT to add a non-root USER directive, ensuring
the operator runs as non-root while preserving the existing image metadata and
startup command.

---

Nitpick comments:
In `@Dockerfile.gcp-pd`:
- Line 3: Replace the broad COPY instruction in the Docker build stage with
explicit COPY directives for only the files and directories required by the
build, excluding the rest of the repository context.
- Around line 6-10: Add a HEALTHCHECK instruction to the final image definition
in Dockerfile.gcp-pd, alongside the existing ENTRYPOINT and LABEL directives.
Configure it to invoke an appropriate health probe for
gcp-pd-csi-driver-operator and preserve the current startup command.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: 19e8acdf-4877-4e40-93b2-802e0864bd31

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed0670 and fa76b6a.

📒 Files selected for processing (1)
  • Dockerfile.gcp-pd

Comment thread Dockerfile.gcp-pd
Comment on lines 6 to 10
FROM registry.ci.openshift.org/ocp/5.0:base-rhel9
COPY --from=builder /go/src/github.com/openshift/gcp-pd-csi-driver-operator/gcp-pd-csi-driver-operator /usr/bin/
COPY --from=builder /go/src/github.com/openshift/csi-operator/bin/gcp-pd-csi-driver-operator /usr/bin/
ENTRYPOINT ["/usr/bin/gcp-pd-csi-driver-operator"]
LABEL io.k8s.display-name="OpenShift GCP PD CSI Driver Operator" \
io.k8s.description="The GCP PD CSI Driver Operator installs and maintains the GCP PD CSI Driver on a cluster."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Missing non-root USER directive in final image.

The final stage runs the operator without setting a non-root USER, so the container defaults to root. As per path instructions, "USER non-root; never run as root."

🔒 Proposed fix
 FROM registry.ci.openshift.org/ocp/5.0:base-rhel9
 COPY --from=builder /go/src/github.com/openshift/csi-operator/bin/gcp-pd-csi-driver-operator /usr/bin/
+USER 65532:65532
 ENTRYPOINT ["/usr/bin/gcp-pd-csi-driver-operator"]
📝 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
FROM registry.ci.openshift.org/ocp/5.0:base-rhel9
COPY --from=builder /go/src/github.com/openshift/gcp-pd-csi-driver-operator/gcp-pd-csi-driver-operator /usr/bin/
COPY --from=builder /go/src/github.com/openshift/csi-operator/bin/gcp-pd-csi-driver-operator /usr/bin/
ENTRYPOINT ["/usr/bin/gcp-pd-csi-driver-operator"]
LABEL io.k8s.display-name="OpenShift GCP PD CSI Driver Operator" \
io.k8s.description="The GCP PD CSI Driver Operator installs and maintains the GCP PD CSI Driver on a cluster."
FROM registry.ci.openshift.org/ocp/5.0:base-rhel9
COPY --from=builder /go/src/github.com/openshift/csi-operator/bin/gcp-pd-csi-driver-operator /usr/bin/
USER 65532:65532
ENTRYPOINT ["/usr/bin/gcp-pd-csi-driver-operator"]
LABEL io.k8s.display-name="OpenShift GCP PD CSI Driver Operator" \
io.k8s.description="The GCP PD CSI Driver Operator installs and maintains the GCP PD CSI Driver on a cluster."
🤖 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 `@Dockerfile.gcp-pd` around lines 6 - 10, Update the final image stage in the
Dockerfile around the gcp-pd-csi-driver-operator ENTRYPOINT to add a non-root
USER directive, ensuring the operator runs as non-root while preserving the
existing image metadata and startup command.

Source: Path instructions

@mpatlasov mpatlasov force-pushed the STOR-2997-Implement-GCP-PD-CSI-driver-operator-inside-csi-operator-framework branch from fa76b6a to d85ac06 Compare July 14, 2026 00:29

@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 `@cmd/gcp-pd-csi-driver-operator/main.go`:
- Line 28: Update the Cobra command handler around cmd.Help() to handle its
returned error instead of discarding it. Use the error-returning command flow,
such as RunE, and return cmd.Help() so help-output failures propagate; ensure no
Go error return remains ignored.

In `@Dockerfile.gcp-pd`:
- Line 3: Replace the broad COPY . . instruction in the Dockerfile build stage
with explicit COPY directives for only the manifests and source directories
required by this build target. Exclude secrets, credentials, build artifacts,
and unrelated repository files from the builder context.

In `@pkg/driver/gcp-pd/gcp_pd.go`:
- Line 38: Update the error string returned by the HyperShift handling in the
relevant function to remove the trailing exclamation mark, preserving the exact
message text as “Flavour HyperShift is not supported”.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: b1bd05f7-b7fc-430b-877a-41c866600a9b

📥 Commits

Reviewing files that changed from the base of the PR and between fa76b6a and d85ac06.

⛔ Files ignored due to path filters (32)
  • assets/overlays/gcp-pd/generated/standalone/cabundle_cm.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_hostnetwork_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_pdb.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/csidriver.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/hostnetwork_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_attacher_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_snapshotter_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/manifests.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_privileged_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/privileged_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/service.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/servicemonitor.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_ssd.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshot_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass_images.yaml is excluded by !**/generated/**
📒 Files selected for processing (3)
  • Dockerfile.gcp-pd
  • cmd/gcp-pd-csi-driver-operator/main.go
  • pkg/driver/gcp-pd/gcp_pd.go

Use: "gcp-pd-csi-driver-operator",
Short: "OpenShift GCP PD CSI Driver Operator",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Handle the cmd.Help() error.

Line 28 discards Cobra’s returned error, so help-output failures are silently lost. Check and propagate/handle it, for example by using RunE and returning cmd.Help().

As per path instructions: Go code must never ignore error returns.

🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 28-28: Error return value of cmd.Help is not checked

(errcheck)

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

In `@cmd/gcp-pd-csi-driver-operator/main.go` at line 28, Update the Cobra command
handler around cmd.Help() to handle its returned error instead of discarding it.
Use the error-returning command flow, such as RunE, and return cmd.Help() so
help-output failures propagate; ensure no Go error return remains ignored.

Sources: Path instructions, Linters/SAST tools

Comment thread Dockerfile.gcp-pd
COPY legacy/gcp-pd-csi-driver-operator .
RUN make
WORKDIR /go/src/github.com/openshift/csi-operator
COPY . .

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not copy the entire build context.

COPY . . places every repository file into the builder stage, potentially including secrets, credentials, and unrelated artifacts. Copy only the manifests and source directories required by this build target.

As per path instructions, “COPY specific files, not entire context.”

🤖 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 `@Dockerfile.gcp-pd` at line 3, Replace the broad COPY . . instruction in the
Dockerfile build stage with explicit COPY directives for only the manifests and
source directories required by this build target. Exclude secrets, credentials,
build artifacts, and unrelated repository files from the builder context.

Source: Path instructions

Comment thread pkg/driver/gcp-pd/gcp_pd.go Outdated
@mpatlasov mpatlasov force-pushed the STOR-2997-Implement-GCP-PD-CSI-driver-operator-inside-csi-operator-framework branch from d85ac06 to 3c7108f Compare July 14, 2026 00:54

@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 `@pkg/driver/gcp-pd/gcp_pd.go`:
- Line 38: Update the unsupported-flavour error in the relevant driver function
to start with a lowercase letter, while retaining the flavour-specific context
by formatting the flavour value in the message.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: 926fa496-de4b-4f51-98ab-16491ea1ea52

📥 Commits

Reviewing files that changed from the base of the PR and between d85ac06 and 3c7108f.

⛔ Files ignored due to path filters (32)
  • assets/overlays/gcp-pd/generated/standalone/cabundle_cm.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_hostnetwork_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_pdb.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/csidriver.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/hostnetwork_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_attacher_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_snapshotter_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/manifests.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_privileged_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/privileged_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/service.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/servicemonitor.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_ssd.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshot_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass_images.yaml is excluded by !**/generated/**
📒 Files selected for processing (3)
  • Dockerfile.gcp-pd
  • cmd/gcp-pd-csi-driver-operator/main.go
  • pkg/driver/gcp-pd/gcp_pd.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • cmd/gcp-pd-csi-driver-operator/main.go
  • Dockerfile.gcp-pd

func GetGCPPDOperatorControllerConfig(ctx context.Context, flavour generator.ClusterFlavour, c *clients.Clients) (*config.OperatorControllerConfig, error) {
if flavour != generator.FlavourStandalone {
klog.Error(nil, "Flavour HyperShift is not supported")
return nil, fmt.Errorf("Flavour HyperShift is not supported")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Lowercase the returned error string.

ST1005 still flags this line because Go error strings must not start with an uppercase letter. Use a lowercase, flavour-specific message such as fmt.Errorf("flavour %v is not supported", flavour).

Static analysis reports ST1005: error strings should not be capitalized.

🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 38-38: ST1005: error strings should not be capitalized

(staticcheck)

🤖 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/driver/gcp-pd/gcp_pd.go` at line 38, Update the unsupported-flavour error
in the relevant driver function to start with a lowercase letter, while
retaining the flavour-specific context by formatting the flavour value in the
message.

Source: Linters/SAST tools

@rhrmo

rhrmo commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

/retest-required

const (
generatedAssetBase = "overlays/gcp-pd/generated"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see we have the generated assets but there is no generator.CSIDriverGeneratorConfig function, these should be generated from this function, right? Or am I missing something?

@RomanBednar

Copy link
Copy Markdown
Contributor

PR seems somewhat incomplete - when I delete assets/overlays/gcp-pd/generated directory and try to re-generate the assets it fails:

make update-generated-assets
hack/update-generated-assets.sh
assets/assets.go:7:28: pattern overlays/*: cannot embed directory overlays/gcp-pd: contains no embeddable files
make: *** [update-generated-assets] Error 1

This is because collectConfigs() is not wired to load CSIDriverGeneratorConfig (which is missing) - this is what @rhrmo pointed out.

Also, there's a typo in the binary in PR description: ./bin/gcp-pd-csi-driver-smb-operator -> smb

I was thinking that this PR could be an intermediate step where you just intend to demonstrate a working binary - however the switch from legacy directory in Containerfile would indicate that the migration to generated files is finished.

When I worked on AWS migration I implemented this in a single PR, not saying it's the only right way but I think that first we need to get the generators working and see CI tests are passing with those assets. Then cross-check the assets with the legacy ones - it's easy to misss something.

@mpatlasov

Copy link
Copy Markdown
Contributor Author

@RomanBednar , @rhrmo , thank you for review, I fixed a typo in PR description -- nice catch!

You are right, the PR is intermediate. It provides the operator binary that works in manual tests and passes CI, but based on pre-defined assets. The next step is to auto-generate assets with generator machinery. SMB operator went through the same process: compare #205 vs. #217.

however the switch from legacy directory in Containerfile would indicate that the migration to generated files is finished

I'd prefer to make this switch as early as possible to see CI failures (and any other complains) earlier and have time to fix them before the end of the cycle. Let me know if you prefer other approach -- keep the PR open until everything is done and polished before the merge.

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/test e2e-azure

1 similar comment
@mpatlasov

Copy link
Copy Markdown
Contributor Author

/test e2e-azure

This PR implements the minimal set of go-files and yaml-assets to enable the command
```
./bin/gcp-pd-csi-driver-smb-operator start --kubeconfig $KUBECONFIG --namespace openshift-cluster-csi-drivers
```
to install and run GCP PD CSI driver:
```
gcp-pd-csi-driver-controller-c949b748-xkljz   10/10   Running   0          3m2s
gcp-pd-csi-driver-controller-c949b748-xvgl9   10/10   Running   0          3m2s
gcp-pd-csi-driver-node-5kcw5                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-frl74                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-gf9k7                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-p95sv                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-q4r98                  3/3     Running   0          3m2s
gcp-pd-csi-driver-node-xvmgq                  3/3     Running   0          3m2s
```
Use gcp-pd go files from cmd/ and pkg/ dirs rather than legacy/
Previous versions of the operator create one single priv ClusterRole (`gcp-pd-privileged-role`) and two ClusterRoleBindings for that (`gcp-pd-controller-privileged-binding` and `gcp-pd-node-privileged-binding`).
With this PR merged, the operator creates another ClusterRole specifically for the controller (`gcp-pd-hostnetwork-role`) and another ClusterRoleBindings for that (`gcp-pd-controller-hostnetwork-binding`).
This makes older binding for the controller redundant, this commit deletes it unconditionally.
GCP Dedicated only supports hyperdisk-balanced disk type.
Add a new StorageClass asset that will be used instead of standard-csi
and ssd-csi when the operator detects GCP Dedicated.

At operator startup, fetch the Infrastructure CR (with retry for up to
1 minute during early cluster bootstrap) and check if the GCP region
starts with "u-". If so, the cluster runs on GCP Dedicated where only
hyperdisk-balanced disks are supported — create only the
hyperdisk-balanced StorageClass as default.

On regular GCP, the existing standard-csi and ssd-csi StorageClasses
are used as before.

See corresponding commits for legacy/: 7a3e209 and 7f08260.
@mpatlasov mpatlasov force-pushed the STOR-2997-Implement-GCP-PD-CSI-driver-operator-inside-csi-operator-framework branch from 3c7108f to ddb0a38 Compare July 15, 2026 03:16

@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

♻️ Duplicate comments (1)
pkg/driver/gcp-pd/gcp_pd.go (1)

51-55: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Error string still capitalized (ST1005), plus klog.Error(nil, ...) misuse.

Two issues here:

  1. fmt.Errorf("Flavour HyperShift is not supported") still starts with an uppercase letter — the earlier ST1005 capitalization review comment on this line was not addressed (only the trailing punctuation was fixed).
  2. klog.Error(nil, "...") is not the structured ErrorS(err error, msg string, ...) call — klog.Error is a Print-style variadic function, so passing nil as the first positional argument produces a garbled log line (e.g. <nil>Flavour HyperShift is not supported) instead of a clean message. This log call is also redundant: the caller in pkg/operator/starter.go (RunOperator) already logs klog.Errorf("error building operator config: %v", err) on the returned error.
🐛 Proposed fix
 	if flavour != generator.FlavourStandalone {
-		klog.Error(nil, "Flavour HyperShift is not supported")
-		return nil, fmt.Errorf("Flavour HyperShift is not supported")
+		return nil, fmt.Errorf("flavour %v is not supported", flavour)
 	}
🤖 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/driver/gcp-pd/gcp_pd.go` around lines 51 - 55, Update
GetGCPPDOperatorControllerConfig to use a lowercase error message and remove the
redundant klog.Error call; return the error directly so RunOperator remains the
single logging point.
🧹 Nitpick comments (3)
pkg/driver/gcp-pd/gcp_pd.go (1)

74-85: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the selector closure.

cfg.StorageClassSelector can be a direct return instead of an if/return pair.

♻️ Proposed simplification
 	cfg.StorageClassSelector = func(name string) bool {
-		if storageClassSet.Has(name) {
-			return true
-		}
-		return false
+		return storageClassSet.Has(name)
 	}
🤖 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/driver/gcp-pd/gcp_pd.go` around lines 74 - 85, In the
cfg.StorageClassSelector closure, replace the redundant if/return branching with
a direct return of storageClassSet.Has(name), preserving the existing selector
behavior.
pkg/driver/gcp-pd/storageclass_test.go (2)

119-129: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Test takes ~10 seconds due to the context timeout.

Since PollUntilContextTimeout runs immediately (immediate=true) and the poll interval is 5s, a much shorter context (e.g. 1-2s) would still exercise the not-found error path without waiting out most of the 10s window.

⚡ Proposed fix
 	configClient := fakeconfig.NewSimpleClientset()
 	// Use a short timeout so the retry loop finishes quickly in tests.
-	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
 	defer cancel()
🤖 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/driver/gcp-pd/storageclass_test.go` around lines 119 - 129, Shorten the
timeout context in TestGetStorageClassFilesNoInfrastructure to approximately 1–2
seconds, keeping the existing immediate polling and expected-error assertion
unchanged so the not-found path is exercised without the test taking nearly 10
seconds.

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

Deprecated fakeconfig.NewSimpleClientset.

Static analysis flags this as deprecated (SA1019) in favor of NewClientset, which may fail lint gating in CI.

🧰 Tools golangci-lint (2.12.2): `SA1019: fakeconfig.NewSimpleClientset is deprecated: NewClientset replaces this...`

Also applies to: 120-120

🤖 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/driver/gcp-pd/storageclass_test.go` at line 98, Replace deprecated
fakeconfig.NewSimpleClientset calls in the storage class tests with
fakeconfig.NewClientset, including both occurrences, while preserving the
existing test infrastructure arguments and behavior.

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 `@pkg/driver/gcp-pd/gcp_pd.go`:
- Around line 92-133: Update the error handling after
wait.PollUntilContextTimeout in getStorageClassFiles so it wraps lastErr only
when it is non-nil; otherwise use the poll’s err as the underlying error.
Preserve the existing failure message while ensuring the returned error never
wraps a nil value.

---

Duplicate comments:
In `@pkg/driver/gcp-pd/gcp_pd.go`:
- Around line 51-55: Update GetGCPPDOperatorControllerConfig to use a lowercase
error message and remove the redundant klog.Error call; return the error
directly so RunOperator remains the single logging point.

---

Nitpick comments:
In `@pkg/driver/gcp-pd/gcp_pd.go`:
- Around line 74-85: In the cfg.StorageClassSelector closure, replace the
redundant if/return branching with a direct return of storageClassSet.Has(name),
preserving the existing selector behavior.

In `@pkg/driver/gcp-pd/storageclass_test.go`:
- Around line 119-129: Shorten the timeout context in
TestGetStorageClassFilesNoInfrastructure to approximately 1–2 seconds, keeping
the existing immediate polling and expected-error assertion unchanged so the
not-found path is exercised without the test taking nearly 10 seconds.
- Line 98: Replace deprecated fakeconfig.NewSimpleClientset calls in the storage
class tests with fakeconfig.NewClientset, including both occurrences, while
preserving the existing test infrastructure arguments and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: 18167f75-4491-460d-9f98-79d63f46f342

📥 Commits

Reviewing files that changed from the base of the PR and between 3c7108f and ddb0a38.

⛔ Files ignored due to path filters (33)
  • assets/overlays/gcp-pd/generated/standalone/cabundle_cm.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_hostnetwork_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_pdb.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/controller_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/csidriver.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/hostnetwork_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/kube_rbac_proxy_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/lease_leader_election_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_attacher_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/main_snapshotter_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/manifests.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_privileged_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/node_sa.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/privileged_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_role.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/prometheus_rolebinding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/service.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/servicemonitor.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_hyperdisk_balanced.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/storageclass_ssd.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumeattributesclass_reader_resizer_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshot_reader_provisioner_binding.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass.yaml is excluded by !**/generated/**
  • assets/overlays/gcp-pd/generated/standalone/volumesnapshotclass_images.yaml is excluded by !**/generated/**
📒 Files selected for processing (8)
  • Dockerfile.gcp-pd
  • assets/overlays/gcp-pd/custom/old_controller_privileged_binding.yaml
  • cmd/gcp-pd-csi-driver-operator/main.go
  • pkg/driver/gcp-pd/gcp_pd.go
  • pkg/driver/gcp-pd/storageclass_test.go
  • pkg/generated-assets/generated_assets.go
  • pkg/operator/config/config.go
  • pkg/operator/starter.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • Dockerfile.gcp-pd
  • cmd/gcp-pd-csi-driver-operator/main.go

Comment on lines +92 to +133
// getStorageClassFiles returns the list of StorageClass asset files to use,
// based on whether the cluster runs on GCP Dedicated.
// It retries for up to 1 minute to fetch the Infrastructure CR, because during
// early cluster installation the CR may not exist yet.
// On GCP Dedicated, only hyperdisk-balanced is supported.
// On regular GCP, standard-csi and ssd-csi are used.
func getStorageClassFiles(ctx context.Context, configClient configclient.Interface) ([]string, error) {
regularFiles := []string{
"storageclass.yaml",
"storageclass_ssd.yaml",
}
gcpDedicatedFiles := []string{
"storageclass_hyperdisk_balanced.yaml",
}

var region string
var lastErr error
err := wait.PollUntilContextTimeout(ctx, 5*time.Second, 1*time.Minute, true, func(ctx context.Context) (bool, error) {
infra, err := configClient.ConfigV1().Infrastructures().Get(ctx, globalInfrastructureName, metav1.GetOptions{})
if err != nil {
lastErr = err
klog.V(4).Infof("Failed to get Infrastructure CR, will retry: %v", err)
return false, nil
}
if infra.Status.PlatformStatus == nil || infra.Status.PlatformStatus.GCP == nil {
klog.V(4).Infof("Infrastructure CR has no GCP PlatformStatus, assuming regular GCP")
return true, nil
}
region = infra.Status.PlatformStatus.GCP.Region
return true, nil
})
if err != nil {
return nil, fmt.Errorf("failed to get Infrastructure CR: %w", lastErr)
}

if strings.HasPrefix(region, gcpDedicatedRegionPrefix) {
klog.Infof("GCP Dedicated detected (region %q), using hyperdisk-balanced StorageClass", region)
return gcpDedicatedFiles, nil
}
klog.Infof("Regular GCP detected (region %q), using standard StorageClasses", region)
return regularFiles, 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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file and the polling helper usage context.
git ls-files pkg/driver/gcp-pd/gcp_pd.go
wc -l pkg/driver/gcp-pd/gcp_pd.go
cat -n pkg/driver/gcp-pd/gcp_pd.go | sed -n '1,220p'

# Find the imported wait package and any similar error-handling patterns.
rg -n "PollUntilContextTimeout|lastErr|fmt.Errorf\\(\"failed to get Infrastructure CR" -S pkg/driver/gcp-pd/gcp_pd.go pkg -g '!**/vendor/**'

Repository: openshift/csi-operator

Length of output: 6768


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Use a small read-only probe to learn PollUntilContextTimeout behavior from the
# vendored/module source if available, and from the public Go package docs if not.
python3 - <<'PY'
import os, glob
candidates = glob.glob('**/*wait*.go', recursive=True)
for p in candidates[:20]:
    print(p)
PY

# Search for the helper implementation in downloaded modules if present.
rg -n "func PollUntilContextTimeout|PollUntilContextTimeout\\(" "$(go env GOPATH 2>/dev/null)/pkg/mod" -g '*.go' 2>/dev/null | head -n 40 || true

Repository: openshift/csi-operator

Length of output: 10789


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the implementation of PollUntilContextTimeout in the vendored wait package.
sed -n '1,260p' vendor/k8s.io/apimachinery/pkg/util/wait/wait.go | cat -n

# Also inspect any helper paths around the specific function if needed.
rg -n "func PollUntilContextTimeout|ErrWaitTimeout|context deadline exceeded|context canceled|lastErr" vendor/k8s.io/apimachinery/pkg/util/wait/wait.go -n -A4 -B4

Repository: openshift/csi-operator

Length of output: 10080


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the exact PollUntilContextTimeout implementation with line numbers only.
awk '
  /func PollUntilContextTimeout/ {flag=1}
  flag {print NR ":" $0}
  flag && /^\}/ && c++>=1 {exit}
' vendor/k8s.io/apimachinery/pkg/util/wait/wait.go

# Probe how fmt.Errorf behaves with %w and a nil error in a minimal Go snippet.
cat <<'EOF' >/tmp/probe_nil_wrap.go
package main
import (
  "fmt"
)
func main() {
  var err error
  fmt.Printf("%q\n", fmt.Errorf("failed: %w", err).Error())
}
EOF
go run /tmp/probe_nil_wrap.go

Repository: openshift/csi-operator

Length of output: 181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for any local callers that rely on this exact error message shape.
rg -n "failed to get Infrastructure CR" -S .

Repository: openshift/csi-operator

Length of output: 404


Avoid wrapping lastErr unconditionally. If the poll exits before the callback sets lastErr, %w will render a malformed %!w(<nil>) message. Fall back to err when lastErr is nil.

🤖 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/driver/gcp-pd/gcp_pd.go` around lines 92 - 133, Update the error handling
after wait.PollUntilContextTimeout in getStorageClassFiles so it wraps lastErr
only when it is non-nil; otherwise use the poll’s err as the underlying error.
Preserve the existing failure message while ensuring the returned error never
wraps a nil value.

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest-required

Comment on lines +96 to +116
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
configClient := fakeconfig.NewSimpleClientset(test.infra)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

files, err := getStorageClassFiles(ctx, configClient)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

if len(files) != len(test.expectedFiles) {
t.Fatalf("expected %d files, got %d: %v", len(test.expectedFiles), len(files), files)
}
for i, f := range files {
if f != test.expectedFiles[i] {
t.Errorf("file[%d]: expected %q, got %q", i, test.expectedFiles[i], f)
}
}
})
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just a suggestion, could we possibly include assert library and use it for unit tests? I think we lack use of this library in our repos and for unit tests this is a great tool.

Then the code could look for example something like this (this is just an example, it can definitely be done better):

for _, test := range tests {
                t.Run(test.name, func(t *testing.T) {
                        configClient := fakeconfig.NewSimpleClientset(test.infra)
                        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
                        defer cancel()

                        files, err := getStorageClassFiles(ctx, configClient)

                        //using assert
                        assert.NoErrorf(t, err, "unexpected error: %v", err)
                        assert.Len(t,test.expectedFiles, len(files), "wrong number of files")
                        assert.Equal(t, test.expectedFiles, files, "files don't match expected")
                })
        }

@rhrmo

rhrmo commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

/retest-required

@rhrmo

rhrmo commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov I don't mind if we don't have the code to generate assets right now, I was just unsure why it was not there yet, we can merge this PR without the generation code. I left a unit test suggestion, but we do not need to switch to the library right now as getting this PR merged is a priority. I don't think the e2e tests are failing because of changes from this pr and required ones seem to be passing.
/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 15, 2026
@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov: 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/e2e-azure-file-csi-hypershift ddb0a38 link false /test e2e-azure-file-csi-hypershift
ci/prow/e2e-azure-csi-hypershift ddb0a38 link false /test e2e-azure-csi-hypershift
ci/prow/aws-efs-operator-e2e-extended ddb0a38 link false /test aws-efs-operator-e2e-extended
ci/prow/aws-efs-single-zone-operator-e2e-extended ddb0a38 link false /test aws-efs-single-zone-operator-e2e-extended
ci/prow/e2e-azure-file-nfs-csi-hypershift ddb0a38 link false /test e2e-azure-file-nfs-csi-hypershift
ci/prow/smb-win2022-operator-e2e ddb0a38 link false /test smb-win2022-operator-e2e
ci/prow/e2e-aws-csi-extended ddb0a38 link false /test e2e-aws-csi-extended
ci/prow/e2e-aws-ovn-upgrade ddb0a38 link true /test e2e-aws-ovn-upgrade
ci/prow/e2e-azure-file-csi-extended ddb0a38 link false /test e2e-azure-file-csi-extended
ci/prow/aws-efs-sts-cross-account-operator-e2e ddb0a38 link false /test aws-efs-sts-cross-account-operator-e2e
ci/prow/e2e-azurestack-csi ddb0a38 link false /test e2e-azurestack-csi
ci/prow/smb-win2019-operator-e2e ddb0a38 link false /test smb-win2019-operator-e2e
ci/prow/e2e-azure-csi-extended ddb0a38 link false /test e2e-azure-csi-extended

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.

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest-required

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn-csi

@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn-csi

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/e2809ef0-805d-11f1-8e7a-27de9981ab15-0

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn

@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov: trigger 0 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn-serial

@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn-serial

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/bebacb70-805e-11f1-87c5-2a251edf5348-0

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn-serial

@mpatlasov

Copy link
Copy Markdown
Contributor Author

/retest all

@openshift-ci

openshift-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@mpatlasov: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.0-e2e-gcp-ovn-serial

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/56f94b20-8085-11f1-9e6f-d576eba2878f-0

@mpatlasov

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

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants