Repository navigation
GCP-231: feat(api): add GCP Workload Identity Federation types and validation - #7285
Conversation
WalkthroughAdds GCP Workload Identity Federation and resource label types; extends GCPPlatformSpec with WorkloadIdentity and ResourceLabels; tightens GCP naming regexes; adds immutability and cross-field CRD validations; introduces two GCP condition types; updates deepcopy, client apply configs, CLI flags/tests, CRD manifests, docs, fixtures, and pins k8s.io/utils. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4676-4689: Revise reserved-word guard to forbid only "google"—not "goog".GCP project IDs forbid "google" but not "goog". The latter is a Cloud Storage bucket restriction. Update the CEL rule accordingly.
project: ... pattern: ^[a-z]([a-z0-9-]{4,28}[a-z0-9])$ type: string x-kubernetes-validations: + - message: Project ID must not contain reserved substring "google" + rule: !self.contains('google') - message: Project is immutable rule: self == oldSelfapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4784-4798: Refine the regex pattern to block only "google", not "goog".GCP project ID restrictions disallow the substring "google" but do not restrict "goog" at the project ID level (it's only restricted for specific resources like GCS buckets). Update the pattern to block only the reserved word:
project: @@ - pattern: ^(?!.*google)(?!.*goog)[a-z]([a-z0-9-]{4,28}[a-z0-9])$ + pattern: ^(?!.*google)[a-z]([a-z0-9-]{4,28}[a-z0-9])$
🧹 Nitpick comments (16)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (4)
4634-4649: Scope immutability to the field, not the whole object (future-proofing).Object-level immutability on network may block adding future optional fields. Prefer making only name immutable.
properties: name: ... type: string + x-kubernetes-validations: + - message: Network name is immutable + rule: self == oldSelf required: - name type: object - x-kubernetes-validations: - - message: Network is immutable - rule: self == oldSelf
4655-4670: Same here: make only subnet name immutable.Avoid freezing the entire privateServiceConnectSubnet object.
properties: name: ... type: string + x-kubernetes-validations: + - message: Private Service Connect subnet name is immutable + rule: self == oldSelf required: - name type: object - x-kubernetes-validations: - - message: Private Service Connect subnet is immutable - rule: self == oldSelf
4708-4757: Consider lowering maxItems to leave headroom for system labels.You note HyperShift reserves ~4 labels; with maxItems 64 users can hit per-resource limits. Consider maxItems 60 to avoid runtime failures.
- maxItems: 64 + maxItems: 60
4759-4854: Deduplicate per-field immutability; add cross-field validation for project consistency.Verification confirms all three points:
"gcp-" prefix reservation: Verified correct. Google reserves this prefix for Workload Identity Pool and Provider IDs.
Per-field immutability redundancy: The code contains individual immutability rules for
poolID,providerID,projectNumber, andnodePoolEmail(shown in snippet). These are redundant with the object-levelrule: self == oldSelfat theworkloadIdentitylevel. Remove the per-field duplicates.Feature gating is proper:
workloadIdentityappears only in featuregated CRDs (*TechPreviewNoUpgrade.crd.yaml,*CustomNoUpgrade.crd.yaml) and is required there. It is completely absent from base*Default.crd.yamlCRDs, which correctly prevents breaking upgrades on non-featuregated installations.Cross-field validation feasibility: CEL supports the
.split("@")syntax for email domain extraction. Add the proposed validation rule atspec.platform.gcplevel to ensurenodePoolEmailproject matchesspec.platform.gcp.project.api/hypershift/v1beta1/gcp_validation_test.go (2)
7-59: Consider adding negative test cases to validate rejection of invalid inputs.The test only verifies that valid structs can be constructed, but doesn't test that invalid inputs would be rejected. According to the PR objectives, GCPResourceLabel has strict RFC1035-compliant validation rules including:
- Keys starting with 'goog' prefix should be rejected
- Keys/values with underscores should be rejected (RFC1035)
- Keys/values ending with hyphens should be rejected
- Keys/values exceeding 63 characters should be rejected
- Keys starting with uppercase letters should be rejected
While CEL validation in the CRD will ultimately enforce these rules, consider adding table entries that document expected failures to serve as regression tests when the validation logic changes.
Example negative cases to add:
+ { + name: "When label key starts with reserved 'goog' prefix, it should fail validation", + label: GCPResourceLabel{Key: "goog-test", Value: "value"}, + expectError: true, + }, + { + name: "When label key contains underscore, it should fail validation", + label: GCPResourceLabel{Key: "test_key", Value: "value"}, + expectError: true, + },
61-101: Consider adding negative test cases for invalid region formats.Similar to the
TestGCPResourceLabelfunction, this test only verifies that valid region strings can be assigned but doesn't validate that invalid formats would be rejected. Consider adding negative test cases such as:
- Regions with uppercase letters
- Regions with invalid characters
- Empty regions
- Regions with trailing/leading hyphens
This would document expected validation behavior and serve as regression tests.
docs/content/reference/api.md (3)
5954-5959: Make region format machine‑checkable.Consider adding an explicit regex (e.g., ^[a-z]+(-[a-z0-9]+)*[0-9]$) and a note that zones (e.g., “-a”) must not be appended to regions. This reduces ambiguity for users and validators.
6001-6030: WIF prerequisites: add concrete attribute mapping example.Include a brief mapping snippet (google.subject -> assertion.sub; attribute.aud -> assertion.aud) to make setup reproducible and reduce misconfiguration.
6001-6007: List reserved/auto‑applied labels.You mention “reserves approximately 4 labels.” Naming them (keys) helps users avoid conflicts.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5894-5989: WIF block looks solid; minor nits only.
- poolID/providerID/projectNumber validations and immutability are sensible.
- Service account email regex is precise for GSA format.
Optional: object-level immutability plus per-field immutability is redundant; you can keep only the object-level rule to reduce noise.
api/hypershift/v1beta1/gcp.go (1)
131-139: Consider loweringResourceLabelsMaxItems to account for reserved system labelsYou note that GCP allows up to 64 labels per resource and that HyperShift reserves ~4 labels for system use, but
ResourceLabelscurrently allows up to 64 user-specified entries. This can lead to hard-to-debug failures at reconciliation time when combined with system labels.Consider setting
MaxItemsto something like 60 (or another explicit budget) so user configs cannot exceed the provider’s effective limit once system labels are included.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (2)
5554-5604: Prevent duplicate label keys and leave headroom for system labels
- Today duplicates are possible since this is a plain array. Make it a map keyed by "key" to enforce uniqueness.
- maxItems is 64, but controllers add ~4 system labels. Users could hit the per-resource 64 limit at runtime. Either reduce to 60 here or validate in controllers.
Proposed diff (unique keys + headroom to 60):
- maxItems: 64 - type: array + maxItems: 60 + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map
5605-5700: Relax object-level immutability on workloadIdentityYou already mark each field immutable. Keeping
x-kubernetes-validations: self == oldSelfat the object level blocks any safe, additive day-2 changes (e.g., future optional fields) and forces cluster recreation for rotations. Recommend removing the object-level rule and relying on per-field immutability.Proposed diff (remove object-level immutability):
- x-kubernetes-validations: - - message: WorkloadIdentity is immutable - rule: self == oldSelfPlease confirm you don’t need to rotate service account emails or extend this struct day‑2; if rotation is required, the current object-level immutability will prevent it.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4816-4865: Enforce unique label keys and prefer map semantics.Duplicate keys can slip through and cause confusion when applied. Model this list as a map keyed by
key.Apply:
resourceLabels: @@ - items: + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - key + items: properties: key: pattern: ^[a-z]([0-9a-z-]{0,61}[0-9a-z])?$ value: pattern: ^$|^[0-9a-z]([0-9a-z-]{0,61}[0-9a-z])?$cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (2)
5432-5441: Tighten region regex to avoid digits in non-terminal segments.Current pattern allows cases like “us-2west1” which aren’t valid. Recommend constraining digits to the trailing segment only.
Apply this diff:
- pattern: ^[a-z]+(-[a-z0-9]+)+[0-9]+$ + pattern: ^[a-z]+(?:-[a-z]+)+[0-9]+$Examples still valid: us-central1, europe-west12, northamerica-northeast1. Invalid as intended: us1, us-central, us-central1-a.
5597-5598: Requiring workloadIdentity at platform.gcp may be a breaking change.Making spec.platform.gcp.workloadIdentity required forces WIF on all new GCP clusters and blocks updates where it is unset.
- Confirm this is feature-gated for TechPreview only and won’t affect existing non-WIF flows.
- Consider making it optional (omit from required) and fail validation only when endpointAccess/networkConfig imply WIF.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (17)
api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
api/hypershift/v1beta1/gcp_validation_test.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.goclient/applyconfiguration/utils.goclient/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.goclient/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.goapi/hypershift/v1beta1/hostedcluster_conditions.goapi/hypershift/v1beta1/hostedcluster_types.goclient/applyconfiguration/hypershift/v1beta1/gcpplatformspec.godocs/content/reference/api.mdapi/hypershift/v1beta1/zz_generated.deepcopy.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/gcp.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (6)
api/hypershift/v1beta1/gcp_validation_test.go (2)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-54)test/e2e/util/external_oidc.go (1)
Key(289-292)
client/applyconfiguration/utils.go (4)
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabelApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReferenceApplyConfiguration(22-24)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
GCPServiceAccountsRefApplyConfiguration(22-24)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfigApplyConfiguration(22-27)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
GCPServiceAccountsRefApplyConfiguration(22-24)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
api/hypershift/v1beta1/hosted_controlplane.go (1)
ConditionType(294-294)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(223-236)GCPWorkloadIdentityConfig(162-219)
api/hypershift/v1beta1/gcp.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
🔇 Additional comments (42)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4694-4706: Region regex and guidance look good.api/hypershift/v1beta1/hostedcluster_types.go (1)
129-131: LGTM!The constant follows the established pattern for CAPI provider image overrides and is properly documented.
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: LGTM!The new condition types follow the established pattern for platform-specific validation conditions and are properly documented.
client/applyconfiguration/utils.go (1)
160-167: LGTM!The new case statements follow the established pattern and are correctly ordered. As generated code, this is expected to be correct.
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
1-38: LGTM!This is properly generated apply configuration code following the standard pattern.
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
1-47: LGTM!This is properly generated apply configuration code following the standard pattern.
docs/content/reference/api.md (1)
5038-5048: Condition type naming: confirm alignment across API, CRDs, and docs.Docs add “ValidGCPCredentials” and “ValidGCPWorkloadIdentity”, while the PR summary mentions “ValidWorkloadIdentityConfiguration”. Please confirm the canonical names and keep them consistent everywhere (constants, CRDs, status conditions, and docs).
client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (1)
26-92: LGTM!The auto-generated apply configuration correctly adds the new
ResourceLabelsandWorkloadIdentityfields with proper builder methods following standard patterns.client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
22-65: LGTM!The auto-generated apply configuration for
GCPWorkloadIdentityConfigcorrectly implements all builder methods with proper chaining support.api/hypershift/v1beta1/zz_generated.deepcopy.go (3)
1485-1494: LGTM!The auto-generated
DeepCopyIntoforGCPPlatformSpeccorrectly handles the newResourceLabelsslice with proper allocation and copy, and assignsWorkloadIdentitydirectly since it contains only value types.
1612-1671: LGTM!The auto-generated deepcopy functions for
GCPResourceLabel,GCPServiceAccountsRef, andGCPWorkloadIdentityConfigare correct. These types contain only value-type fields (strings and nested value types), so the simple*out = *incopy semantics are appropriate.
3431-3435: LGTM!The
PlatformSpec.DeepCopyIntonow correctly callsDeepCopyIntoon theGCPPlatformSpecpointer to ensure theResourceLabelsslice is properly deep-copied rather than shallow-copied.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (5)
5769-5785: GCP network name validation looks correct.Pattern and immutability rule align with GCP naming (lowercase, hyphen, <=63). No issues.
5790-5805: GCP subnet name validation looks correct.Pattern and immutability rule align with GCP subnet naming. No issues.
5814-5824: Project ID regex is appropriately strict.Matches GCP rules (6–30, starts letter, lowercase/digits/hyphen, no trailing hyphen). Good guard.
5829-5841: Region regex correctly excludes zones and enforces trailing digits.Examples provided match; pattern allows multi-segment regions (e.g., northamerica-northeast1). Looks good.
5966-5977: Service account email pattern: consider future-proofing.If you anticipate longer IDs in the future, keep current limits but add a brief comment noting they mirror current GCP 6–30 constraints. No change required now.
api/hypershift/v1beta1/gcp.go (3)
7-18: Label and resource name validation look consistent with GCP rulesThe updated
GCPResourceReferencename regex and the newGCPResourceLabelkey/value patterns (including thegoogreserved-prefix CEL check) line up with the documented RFC1035-style constraints and GCP docs you reference, and should give users clear, predictable validation behavior.Also applies to: 20-54
70-83: Immutability enforcement for network fields is appropriateMarking
NetworkandPrivateServiceConnectSubnetas immutable both via+immutableandself == oldSelfXValidations matches how these fields are typically treated in cloud platform specs and avoids drift or disruptive mutations after cluster creation.
85-117: Project and region validation are tightened correctlyThe
Projectpattern and length constraints capture the documented GCP project ID rules, and the newRegionregex (plus immutability) correctly enforces “at least one hyphen” and “must end in digits” while rejecting zone-style values likeus-central1-a.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (7)
5480-5489: GCP network name pattern looks goodMatches RFC1035-style GCP resource naming and length constraints. No issues.
5493-5496: Immutability on network objectself == oldSelf is appropriate here since the object only carries name; safe.
5501-5510: GCP PSC subnet name pattern looks goodConsistent with GCP resource naming; no issues.
5514-5516: Immutability on PSC subnetReasonable to prevent renames post-create.
5531-5531: Project ID regex aligns with GCP rulesStart-letter, 6–30 chars, lowercase/digits/hyphen, no trailing hyphen. OK.
5540-5549: Region pattern is strict and correctForces at least one hyphen and trailing digits (regions, not zones). Examples provided match. OK.
5702-5706: Requiring workloadIdentity in TechPreview CRD: verify upgrade/create pathsMaking
workloadIdentityrequired is a breaking schema change. In TechPreviewNoUpgrade this might be fine, but please confirm:
- No existing HostedClusters on GCP rely on the TechPreview CRD without this field.
- All applyconfigs/builders default or enforce population.
- E2E/create flows provide values; otherwise object creation will fail.
If needed, consider making it optional initially and gating enforcement in admission/controllers.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (3)
4742-4751: GCP network name validation looks good.Pattern, bounds, and immutability align with Compute Engine naming rules.
Also applies to: 4755-4758
4763-4771: PSC subnet name validation looks good.Matches GCP resource name constraints; immutability applied correctly.
Also applies to: 4776-4778
4802-4811: Region regex is reasonable and future-friendly.Catches common formats and excludes zones; immutability is fine.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (4)
5661-5670: GCP network name regex/immutability — LGTMPattern and immutability look correct and match Compute naming rules.
Also applies to: 5674-5676
5682-5691: GCP subnet name regex/immutability — LGTMConsistent with Compute naming rules and day-2 immutability.
Also applies to: 5695-5697
5703-5716: Project ID validation — LGTMRegex + length bounds align with GCP constraints (6–30 chars; start letter; no trailing hyphen).
5718-5733: Region validation — LGTMRegex excludes zone suffixes and enforces trailing digits; matches region formats (e.g., us-central1).
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (8)
5372-5381: GCP network name pattern looks good.Lowercase, hyphen, end with alnum, ≤63 — matches Compute Engine naming. No changes requested.
5385-5387: Immutability guard for network is correct.Object-level self == oldSelf is fine here.
Ensure server-side defaulting doesn’t mutate this object on updates (would trip immutability).
5393-5402: PSC subnet name pattern is correct.Aligns with GCP RFC1035-style constraints. No changes requested.
5406-5408: Immutability for PSC subnet is correct.Same caveat as network: avoid defaulting-on-update.
5423-5423: Project ID regex matches GCP rules.6–30 chars, starts with letter, no trailing hyphen. Looks right.
5511-5529: Pool/Provider ID validation looks sound.Length, charset, reserved ‘gcp-’ prefix, and immutability are appropriate.
Confirm Google’s API does not allow trailing hyphens for these IDs (your regex forbids them).
Also applies to: 5544-5561
5591-5592: Immutability for workloadIdentity object is good.Object-level immutability matches the security intent.
5569-5577: I need to verify the claims about Google Service Account email formats and CAPG requirements.I need more context about HyperShift/CAPG requirements for NodePool service accounts.
Let me search for explicit CAPG documentation on service account requirements for GCP NodePool.
The review comment is based on incorrect assumptions about CAPG requirements.
Cluster API Provider GCP documentation explicitly states to "create a new service account with Editor permissions," not use default service accounts. User-managed service accounts follow the format: service-account-name@project-id.iam.gserviceaccount.com—which the current regex correctly validates.
While the default Compute Engine service account does use the format PROJECT_NUMBER-compute@developer.gserviceaccount.com and the App Engine default uses PROJECT_ID@appspot.gserviceaccount.com, CAPG does not support these. The regex restriction to
.iam.gserviceaccount.comis intentional—it enforces security best practices by requiring explicitly created, minimally-privileged service accounts rather than broad default accounts.The review incorrectly assumes CAPG "can run" with default SAs. No evidence supports this claim, and documentation contradicts it. The current regex pattern is correct for its intended scope.
Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (5)
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5842-5893: Enforce unique label keys via list-map semanticsAdd list-map to prevent duplicate keys and get SSA-merge correctness on updates.
Apply at the array level:
resourceLabels: ... maxItems: 60 type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - keyOptionally, add a brief doc note clarifying that keys starting with “goog” are intentionally disallowed (broader than GCP’s “goog-”), to avoid confusion.
5996-6000: Confirm “workloadIdentity” required only in gated CRDsYou noted this is intentional under the feature gate. Please verify the non-gated CRDs don’t require it.
#!/bin/bash # Show where workloadIdentity is required across generated CRDs set -euo pipefail rg -nC3 '^\s*-\s+workloadIdentity\s*$' cmd/install/assets/hypershift-operator/zz_generated.crd-manifests \ | sed -n '1,200p' echo echo "If only CustomNoUpgrade (or other gated) manifests show it under a 'required:' block, we're good."cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5785: Enforce unique label keys; keep 60-item headroomDuplicate label keys are still possible. Add a CEL rule at the array level to guarantee uniqueness without changing list semantics.
Apply:
resourceLabels: description: | ... items: ... maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))If desired later, mirror this with a kubebuilder XValidation comment on the Go field so it persists into generated CRDs.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4972-4972: Requiring workloadIdentity under feature gate is acceptable.Per prior thread, this CRD is feature‑gated; keeping it required here is fine. No change requested.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5446-5496: Enforce unique resourceLabels keys (without list-map semantics).You kept array semantics (order preserved) and capped to 60. However, duplicate keys are still possible and can lead to last-wins/ambiguous behavior. Add a CEL array-level validation to guarantee uniqueness by key.
Apply this diff under spec.platform.gcp.resourceLabels (same level as items/maxItems):
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster. ... maxItems: 60 type: array
🧹 Nitpick comments (8)
api/hypershift/v1beta1/gcp_validation_test.go (1)
50-58: Tests provide limited validation coverage.These tests only verify non-empty struct creation. The actual pattern validation occurs via CEL in the CRD, so these tests serve mainly as documentation of expected valid inputs.
Consider adding regex-based validation in tests to catch pattern regressions without requiring a full CRD/admission test:
import "regexp" var gcpLabelKeyPattern = regexp.MustCompile(`^[a-z]([0-9a-z-]{0,61}[0-9a-z])?$`) func TestGCPResourceLabel(t *testing.T) { // ... existing valid cases ... // Add validation for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if !gcpLabelKeyPattern.MatchString(tt.label.Key) { t.Errorf("Key %q does not match pattern", tt.label.Key) } }) } // Add invalid cases invalidCases := []struct { name string key string }{ {"key starts with digit", "1invalid"}, {"key ends with hyphen", "invalid-"}, {"key contains uppercase", "Invalid"}, } // ... }Also applies to: 92-100
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5894-5994: WIF fields/readability: solid constraints; minor nits optional
- Strong immutability + tight regexes for poolID/providerID/projectNumber/nodePoolEmail look good.
- Minor optional: top-level WorkloadIdentity immutability plus per-field immutability is redundant; keeping only the top-level rule reduces noise without changing behavior.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5540-5545: Tighten region regex (optional) to avoid false acceptsCurrent regex allows digits in middle segments (e.g., "us-1central1"). Consider a stricter, future-tolerant pattern that matches known region formats where digits only trail the final segment:
- pattern: ^[a-z]+(-[a-z0-9]+)+[0-9]+$ + pattern: ^[a-z]+(?:-[a-z]+)+[1-9][0-9]*$Keeps examples like "us-central1", "europe-west12", "northamerica-northeast1" valid, while rejecting unlikely names.
Also applies to: 5548-5548
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5661-5677: Make immutability target the specific field, not the whole objectUsing self == oldSelf at the object level for network and privateServiceConnectSubnet freezes the entire object, which can impede safe future extensions. Prefer field-level immutability on .name instead.
Apply:
properties: network: properties: name: description: ... maxLength: 63 minLength: 1 pattern: ^[a-z]([-a-z0-9]*[a-z0-9])?$ type: string + x-kubernetes-validations: + - message: Network name is immutable + rule: self == oldSelf required: - name type: object - x-kubernetes-validations: - - message: Network is immutable - rule: self == oldSelf privateServiceConnectSubnet: properties: name: description: ... maxLength: 63 minLength: 1 pattern: ^[a-z]([-a-z0-9]*[a-z0-9])?$ type: string + x-kubernetes-validations: + - message: Private Service Connect subnet name is immutable + rule: self == oldSelf required: - name type: object - x-kubernetes-validations: - - message: Private Service Connect subnet is immutable - rule: self == oldSelfAlso applies to: 5682-5697
5816-5821: Avoid redundant immutability — keep only the top-level guardworkloadIdentity has a top-level self == oldSelf and per-field immutability on poolID/providerID/projectNumber/serviceAccountsRef.nodePoolEmail. The nested rules are redundant and bloat the schema. Keep the top-level guard and drop the duplicates.
Apply:
poolID: ... - x-kubernetes-validations: - - message: Pool ID is immutable - rule: self == oldSelf projectNumber: ... - x-kubernetes-validations: - - message: Project number is immutable - rule: self == oldSelf providerID: ... - x-kubernetes-validations: - - message: Provider ID is immutable - rule: self == oldSelf serviceAccountsRef: properties: nodePoolEmail: ... - x-kubernetes-validations: - - message: NodePool email is immutable - rule: self == oldSelf ... x-kubernetes-validations: - message: WorkloadIdentity is immutable rule: self == oldSelfAlso applies to: 5847-5852, 5885-5886
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4816-4865: Make resourceLabels a map by key to prevent duplicates.Currently an array; duplicate keys can slip in and last-write-wins is unclear. Use list‑map semantics so keys are unique and merges are predictable.
resourceLabels: @@ maxItems: 60 type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map
4968-4973: Add CEL to ensure nodePoolEmail domain matches .project.Early validation avoids subtle misconfigs (project typo vs GSA domain).
gcp: description: gcp specifies configuration for clusters running on Google Cloud Platform. properties: @@ - required: + required: - networkConfig - project - region - workloadIdentity type: object + x-kubernetes-validations: + - message: serviceAccountsRef.nodePoolEmail must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || + !has(self.workloadIdentity.serviceAccountsRef) || + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1] + == (self.project + ".iam.gserviceaccount.com")api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4708-4757: Enforce unique label keys with list‑map; current array allows duplicatesGCP labels are key/value; allowing duplicate keys in the array can lead to last‑write‑wins and confusion. Make the list a map keyed by “key” to enforce uniqueness.
Apply this diff on the resourceLabels array:
- type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - key + type: array
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (18)
api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)
✅ Files skipped from review due to trivial changes (1)
- docs/content/reference/api.md
🚧 Files skipped from review as they are similar to previous changes (4)
- client/applyconfiguration/utils.go
- client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go
- api/hypershift/v1beta1/hostedcluster_types.go
- client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
api/hypershift/v1beta1/hostedcluster_conditions.goclient/applyconfiguration/hypershift/v1beta1/gcpplatformspec.gocmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlclient/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.goapi/hypershift/v1beta1/gcp.goapi/hypershift/v1beta1/zz_generated.deepcopy.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlapi/hypershift/v1beta1/gcp_validation_test.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml
🧬 Code graph analysis (3)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
api/hypershift/v1beta1/hosted_controlplane.go (1)
ConditionType(294-294)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
GCPServiceAccountsRefApplyConfiguration(22-24)
api/hypershift/v1beta1/zz_generated.deepcopy.go (2)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(225-241)GCPWorkloadIdentityConfig(162-221)client/applyconfiguration/hypershift/v1beta1/workloadidentity.go (1)
WorkloadIdentity(32-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Red Hat Konflux / hypershift-operator-main-on-pull-request
- GitHub Check: Red Hat Konflux / hypershift-cli-mce-211-on-pull-request
- GitHub Check: Red Hat Konflux / hypershift-release-mce-211-on-pull-request
🔇 Additional comments (32)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
1485-1494: LGTM - Auto-generated deep copy functions are correct.The generated
DeepCopyIntoimplementations properly handle the new GCP types:
GCPResourceLabelandGCPServiceAccountsRefuse value copy (appropriate for structs with only string fields)GCPWorkloadIdentityConfigcorrectly copies the nestedServiceAccountsRefGCPPlatformSpecproperly allocates and copies theResourceLabelsslicePlatformSpecnow delegates toDeepCopyIntofor proper deep copy of GCP fieldsAlso applies to: 1612-1671, 3431-3435
api/hypershift/v1beta1/gcp.go (4)
7-54: Well-structured GCP resource naming types with comprehensive validation.The
GCPResourceReferenceandGCPResourceLabeltypes have solid RFC1035-compliant validation:
- Key pattern correctly enforces lowercase start, alphanumeric end, and no consecutive hyphens
- Value pattern allows empty strings as GCP permits
- The
googreserved prefix check via XValidation is appropriate
70-83: Network configuration immutability properly enforced.The
+immutablemarkers with corresponding XValidation rules onNetworkandPrivateServiceConnectSubnetfields ensure these critical networking configurations cannot be changed after cluster creation.
86-139: GCPPlatformSpec validation patterns are correct.The project and region patterns correctly enforce GCP naming rules:
- Project: 6-30 chars, lowercase start, alphanumeric end
- Region: properly handles multi-segment regions like
northamerica-northeast1and multi-digit suffixes likeeurope-west12- ResourceLabels with MaxItems=60 reserves headroom for HyperShift's ~4 system labels within GCP's 64-label limit
159-241: GCPWorkloadIdentityConfig and GCPServiceAccountsRef validation is thorough.The WIF configuration types have proper constraints:
ProjectNumber: numeric-only pattern with reasonable max lengthPoolID/ProviderID: 4-32 char pattern matching GCP's requirements withgcp-prefix reservationNodePoolEmail: pattern correctly validates service account email format with project ID constraints matching line 98All fields are appropriately marked immutable to prevent breaking the authentication chain post-creation.
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
47-52: Test fixture correctly reflects the new workloadIdentity structure.The fixture properly includes the new required
workloadIdentityblock with its nested fields, maintaining alignment with the API schema changes.api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: New GCP condition types follow established patterns.The
ValidGCPCredentialsandValidGCPWorkloadIdentityconditions are well-documented and consistent with other platform-specific validation conditions (e.g.,ValidAWSIdentityProvider,ValidAzureKMSConfig).Consider adding corresponding reason constants (e.g.,
InvalidGCPCredentialsReason,InvalidGCPWorkloadIdentityReason) in the Reasons const block for consistency with patterns likeInvalidAzureCredentialsReason. This can be done when the controller implementation is added.client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (3)
27-33: LGTM! Generated apply configuration fields follow standard patterns.The new fields for ResourceLabels and WorkloadIdentity are correctly structured for declarative configuration with server-side apply.
73-84: LGTM! Append-style builder correctly handles nil values.The WithResourceLabels method follows the standard pattern for slice builders in Kubernetes apply configurations, including the appropriate panic for nil values to prevent runtime errors.
Minor note: Line 74 has a typo ("build" should be "built"), but since this is generated code, the fix should be applied to the generator template rather than this file.
86-92: LGTM! Standard setter-style builder for optional field.The WithWorkloadIdentity method correctly implements the builder pattern for an optional pointer field.
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (2)
1-27: LGTM! Generated apply configuration structure is correct.The GCPWorkloadIdentityConfigApplyConfiguration type is properly structured with appropriate optional fields for declarative configuration.
31-65: LGTM! All builder methods follow standard patterns.The constructor and four With* methods correctly implement the fluent builder pattern for Kubernetes apply configurations, enabling method chaining for declarative configuration construction.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (4)
5769-5785: GCP VPC network name pattern + immutability LGTMRegex and immutability rule look correct for GCP resource naming.
5790-5805: GCP PSC subnet name pattern + immutability LGTMConstraints align with GCP standards; immutability rule is appropriate.
5812-5824: Project ID validation looks correctAnchored regex enforces 6–30 chars, starts with letter, no trailing hyphen. Good.
5829-5841: Region regex blocks zones and enforces trailing digits — LGTMPattern matches regions like us-central1, europe-west12; excludes zone suffixes (e.g., us-central1-a).
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (2)
5480-5489: GCP resource name rules: LGTM + immutabilityPatterns and immutability for network and PSC subnet names match GCP Compute constraints and look solid.
Also applies to: 5502-5510, 5493-5496, 5514-5516
5531-5531: Project ID regex: LGTMThe pattern and length bounds align with GCP project ID rules.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5712-5716: Good tightenings on project and region validationProject ID and region patterns/lengths match GCP rules and improve error clarity. Immutability on both is appropriate.
Also applies to: 5721-5733
5800-5852: poolID/providerID regex now require a leading letter — correctLeading-letter constraint aligns with GCP rules for WIF pool/provider IDs. Thanks for fixing.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4881-4934: WIF IDs and reserved prefix checks look correct.Regex + ‘gcp-’ reservation aligned with IAM rules; immutability is right. No changes requested.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (5)
5372-5387: Network name validation + immutability look good.Pattern matches GCP resource naming, and object immutability rule is correct.
5393-5408: Subnet name validation + immutability look good.Consistent with GCP naming rules and prevents day‑2 drift.
5415-5427: Project ID regex is appropriate and immutable.6–30 chars, lowercase/digits/hyphens, no trailing hyphen; matches GCP guidance.
5432-5444: Region format and immutability are correct.Regex blocks zone suffixes and enforces trailing digits (e.g., us-central1).
5497-5597: All validation patterns confirmed correct; no changes needed.The verification confirms both specifications:
- The 'gcp-' prefix is reserved and may not be used in Workload Identity pool or provider IDs, so the validation rule
!self.startsWith('gcp-')is correct.- Service account IDs must be 6–30 characters with lowercase letters, digits, and hyphens (starting with a letter, ending with a letter or digit), and project IDs must also be 6–30 characters following the same character rules. The nodePoolEmail regex correctly enforces these constraints on both the local and project ID parts.
The poolID and providerID patterns also align properly with Workload Identity specifications.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (6)
4634-4649: LGTM: network name validation + immutabilityThe GCP VPC network name regex and the immutability rule look correct and aligned with Compute Engine naming.
4655-4670: LGTM: PSC subnet name validation + immutabilitySame as network name; constraints and immutability are appropriate.
4861-4865: Double-check: making workloadIdentity required is intentionalMarking workloadIdentity as required under gcp is a behavioral change. If intentional behind the feature gate, document it in the PR and release notes. Otherwise, consider making it optional and validating presence only when WIF is enabled.
4759-4860: Workload Identity: solid immutability/format checks; verify requiredness vs feature gateValidation for poolID/providerID/projectNumber and GSA email looks consistent and intentionally strict. Since this is the feature‑gated CRD, please confirm that the standard CRD (non‑featuregated) does NOT mark gcp.workloadIdentity as required, to avoid breaking existing clusters when the gate is off.
4691-4706: Region regex admits invalid forms like “us-central-1”; tighten to two segmentsThe pattern ^[a-z]+(-[a-z0-9]+)+[0-9]+$ accepts “us-central-1” (three segments). GCP regions are exactly two segments with digits at the end (e.g., “us-central1”, “europe-west12”, “northamerica-northeast1”). Recommend tightening the regex and adding a CEL guard for exactly one hyphen.
Apply this diff:
- pattern: ^[a-z]+(-[a-z0-9]+)+[0-9]+$ + pattern: ^[a-z]+-[a-z0-9]+[0-9]$And append a validation alongside immutability:
x-kubernetes-validations: + - message: Region must have exactly two segments separated by a single hyphen (e.g., us-central1) + rule: self.split('-').size() == 2 - message: Region is immutable rule: self == oldSelfLikely an incorrect or invalid review comment.
4676-4689: Regex is correct; no CEL guard needed for reserved prefixes in project IDsGCP project IDs are not documented as prohibiting "google" or "goog". Project ID rules restrict length and characters (lowercase letters, numbers, hyphens, start with a letter, etc.) only. Restrictions on "google"/"goog" apply to other resource types like Cloud Storage buckets and Integration Connectors, not project IDs. The regex in the YAML correctly enforces official GCP project ID requirements and requires no additional CEL validation for reserved prefixes.
Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (7)
docs/content/reference/api.md (1)
6263-6267: Fix invalid regex; remove HTML anchor and provide copy/paste‑able pattern.The Pattern line renders an anchor, not a regex. Replace with a literal regex and ensure it’s generated from the Go doc comment.
Apply in source (api/hypershift/v1beta1/gcp.go) then regenerate docs:
- Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. + Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Wrap the regex in backticks in the Go comment to avoid Markdown/link expansion in the generated docs, then run
make api-docs.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4979-4980: workloadIdentity marked required under GCP platformAcknowledged as feature‑gated per prior discussion; keeping it required here is fine. No action.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5785: Enforce unique label keys; keep headroom at 60.Array allows duplicate keys; add a CEL uniqueness check to avoid last-write-wins ambiguity. MaxItems=60 headroom is good; keep it.
Apply under spec.platform.gcp.resourceLabels:
resourceLabels: ... maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key)) items: properties: key: ...cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
6003-6007: Double‑check gating: workloadIdentity required only in gated CRDs.Since this file is CustomNoUpgrade (gated), requiring workloadIdentity is fine. Please verify non‑gated CRDs don’t require it to avoid accidental breakage outside the feature gate.
#!/bin/bash # Verify only gated CRDs require platform.gcp.workloadIdentity rg -n -C2 'platform:\s*\n\s*gcp:.*\n.*required:([\s\S]*?)workloadIdentity' cmd/install/assets \ | rg -n -C1 'featuregated|CustomNoUpgrade|DevPreviewNoUpgrade|TechPreviewNoUpgrade|standard|HostedCluster'
5856-5873: Clarify reserved‑prefix wording for label keys (policy is broader than GCP).The rule intentionally blocks any key starting with “goog…”, but the message says “reserved 'goog' prefix” which can be read as the single token “goog-”. Consider clarifying to “reserved ‘goog*’ prefixes” (or narrow the rule/message to “goog-” if you decide to match GCP docs exactly). This is a follow‑up to earlier feedback.
- - message: Label keys starting with the reserved 'goog' prefix are not allowed + - message: Label keys starting with reserved 'goog*' prefixes are not allowed rule: '!self.startsWith(''goog'')'cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5554-5604: Enforce unique label keys for resourceLabelsPrevent duplicate label keys and get idempotent merges by making the list a keyed map. Add list-map hints (and an optional CEL fallback) to the array:
resourceLabels: items: properties: key: # …existing key schema… value: # …existing value schema… required: - key - value type: object maxItems: 60 type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + x-kubernetes-validations: + - rule: self.map(l, l.key).allUnique() + message: Duplicate label keys are not allowedcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5446-5495: Enforce unique label keys at array level.Without de-dup, duplicate keys can yield ambiguous reconciliation and last-write-wins surprises. Add a CEL array-level validation to ensure keys are unique. Max 60 headroom is good.
Apply this diff under resourceLabels:
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self.all(l, self.exists_one(x, x.key == l.key)) items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster.
🧹 Nitpick comments (9)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (2)
4708-4757: Enforce label key uniqueness at the schema level.As written, duplicate keys can be submitted; last-wins is ambiguous for users and propagation. Use a list-map keyed by “key” to force uniqueness.
Apply near items list:
resourceLabels: ... items: ... maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map
4836-4854: Add a cross-field check to align nodePoolEmail’s project with spec.gcp.project.Prevents subtle misconfig (email domain’s project != .gcp.project). Suggested CEL at the gcp object level:
For example under spec.platform.gcp.x-kubernetes-validations:
- message: nodePoolEmail project must match spec.platform.gcp.project rule: "!has(self.workloadIdentity) || !has(self.workloadIdentity.serviceAccountsRef) || ( self.workloadIdentity.serviceAccountsRef.nodePoolEmail.matches('^[a-z][a-z0-9-]{4,28}[a-z0-9]@[a-z][a-z0-9-]{4,28}[a-z0-9]\\.iam\\.gserviceaccount\\.com$') && self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split('@')[1].split('.')[0] == self.project )"docs/content/reference/api.md (3)
6297-6307: Add Service Account User role to the required IAM set.To attach a VM service account when creating instances, the controller needs roles/iam.serviceAccountUser on that service account (or project). Add it explicitly to avoid permission errors.
- This GSA requires the following IAM roles: - - roles/compute.instanceAdmin.v1 (Compute Instance Admin v1) - - roles/compute.networkAdmin (Compute Network Admin) + This GSA requires the following IAM roles: + - roles/compute.instanceAdmin.v1 (Compute Instance Admin v1) + - roles/compute.networkAdmin (Compute Network Admin) + - roles/iam.serviceAccountUser (on the VM service account used by created instances)Please verify this against CAPG docs for your supported version or align with cmd/infra/gcp/iam-bindings.json.
6021-6029: Clarify WIF provider mappings with a concrete example.Add a brief example for attribute/subject mapping and the principal used in the iam.workloadIdentityUser binding to reduce setup ambiguity.
Example snippet to append:
Example: - Provider attribute mapping includes: google.subject -> assertion.sub - Subject pattern used by controllers: system:serviceaccount:kube-system:capi-gcp-controller-manager - IAM binding: role: roles/iam.workloadIdentityUser member: principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/attribute.subject/system:serviceaccount:kube-system:capi-gcp-controller-manager
6003-6007: Quantify or qualify reserved label count.“Reserves approximately 4 labels” is vague. Either state the exact number or say “at least 4 labels may be reserved” to set clearer expectations.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4816-4865: Ensure label key uniqueness with list-as-mapTo prevent duplicate label keys, make resourceLabels a map keyed by “key”. This also improves apply semantics.
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. @@ items: @@ required: - key - value type: object maxItems: 60 type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - key
4784-4798: Add CEL to ensure nodePoolEmail domain matches configured projectPrevents subtle typos where the GSA belongs to a different project than .platform.gcp.project.
gcp: type: object + x-kubernetes-validations: + - message: serviceAccountsRef.nodePoolEmail must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || + !has(self.workloadIdentity.serviceAccountsRef) || + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1] + == (self.project + ".iam.gserviceaccount.com")Also applies to: 4938-4963
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5862-5884: GSA email pattern is precise; confirm cross‑project intent.Regex accepts only PROJECT_ID.iam.gserviceaccount.com and a conservative local-part; immutability OK. If cross‑project GSAs are not intended, consider a CEL to ensure the domain’s project matches spec.platform.gcp.project; otherwise ignore.
Option (only if same‑project is required):
x-kubernetes-validations: - message: nodePoolEmail project must match spec.platform.gcp.project rule: self.split("@")[1].split(".iam.gserviceaccount.com")[0] == oldSelf.split("@")[1].split(".iam.gserviceaccount.com")[0] || self.split("@")[1].split(".iam.gserviceaccount.com")[0] == root.spec.platform.gcp.projectcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5842-5893: Enforce unique label keys via list‑map semantics.Without list‑map, duplicate keys can slip in and merge poorly. Treat resourceLabels as a map keyed by “key” for validation and server‑side apply behavior.
Apply:
resourceLabels: description: |- @@ items: @@ type: object - maxItems: 60 - type: array + maxItems: 60 + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (18)
api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- api/hypershift/v1beta1/hostedcluster_types.go
- client/applyconfiguration/utils.go
- api/hypershift/v1beta1/gcp_validation_test.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.goapi/hypershift/v1beta1/hostedcluster_conditions.goclient/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlclient/applyconfiguration/hypershift/v1beta1/gcpplatformspec.goapi/hypershift/v1beta1/zz_generated.deepcopy.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamldocs/content/reference/api.mdcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/gcp.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (4)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
GCPServiceAccountsRefApplyConfiguration(22-24)
client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (4)
client/applyconfiguration/hypershift/v1beta1/gcpnetworkconfig.go (1)
GCPNetworkConfigApplyConfiguration(22-25)api/hypershift/v1beta1/gcp.go (1)
GCPEndpointAccessType(58-58)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabelApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfigApplyConfiguration(22-27)
api/hypershift/v1beta1/zz_generated.deepcopy.go (2)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(228-248)GCPWorkloadIdentityConfig(162-224)client/applyconfiguration/hypershift/v1beta1/workloadidentity.go (1)
WorkloadIdentity(32-34)
api/hypershift/v1beta1/gcp.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
🔇 Additional comments (44)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (8)
4634-4643: GCP network name regex looks correct; keep.Matches GCP naming and 63-char max. Good addition.
4647-4649: Immutability for network object is appropriate.Prevents day-2 drift; aligns with infra invariants.
4655-4664: PSC subnet name regex looks correct; keep.Conforms to GCP resource naming.
4668-4670: Immutability for PSC subnet is appropriate.Prevents reconciliation churn.
4685-4685: Project ID regex is tight and matches GCP rules.6–30 chars, starts with letter, no trailing hyphen. Good.
4759-4866: WIF block (patterns + immutability) looks solid.poolID/providerID/projectNumber constraints and reserved-prefix checks are clear; object immutability is appropriate.
4871-4871: Confirm gating for new required field.workloadIdentity is marked required. Please confirm this only ships in the feature‑gated CRD and cannot impact existing GCP HCPs that aren’t using WIF yet (upgrade safety).
4694-4703: Region regex pattern is correct and verified.The verification confirms the regex pattern
^[a-z]+(-[a-z0-9]+)+[0-9]+$correctly validates GCP region names:
- All 10 known valid regions match
- All invalid cases (non-hyphenated, non-digit-ending, zones, malformed) are properly rejected
- Requirements are satisfied: at least one hyphen, lowercase letters/digits only, must end with digits
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
47-52: LGTM! Fixture correctly demonstrates the new workloadIdentity API structure.The test fixture appropriately shows the new GCP Workload Identity Federation fields with empty values, which is suitable for a "minimal flags necessary to render" test case. This helps document the API surface for developers.
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: LGTM! Well-documented condition types for GCP validation.The new
ValidGCPCredentialsandValidGCPWorkloadIdentitycondition types are clearly documented and follow the established patterns in the codebase. The comments appropriately explain their purpose and expected failure scenarios.client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
1-38: Generated code - skipping detailed review.This is auto-generated code (as indicated by the comment on line 16). The structure follows standard Kubernetes apply configuration patterns. No critical issues identified.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (4)
4742-4758: GCP network and subnet name validation/immutability — LGTMPatterns and immutability guards match Compute Engine naming rules and prevent day‑2 drift. No changes requested.
Also applies to: 4763-4778
4784-4798: Project ID regex — LGTMThe 6–30 chars, start-with-letter, hyphen/digit constraints are correct for GCP project IDs, and immutability is appropriate.
4802-4814: Region regex tightened — looks right; please sanity‑check a few newer regionsPattern enforces at least one hyphen and trailing digits (e.g., us-central1, europe-west12, northamerica-northeast2). Suggest adding/confirming unit cases for those examples.
Also applies to: 4811-4811
4867-4974: WIF config validations — solid coverageReserved “gcp-” prefix blocks, length/patterns, and immutability on pool/provider/projectNumber and SA email look good. No changes requested beyond the cross‑field check suggested separately.
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
22-47: LGTM - Generated apply configuration follows standard patterns.The generated apply configuration for GCPResourceLabel correctly implements the builder pattern with appropriate field types and chaining methods. The structure aligns with Kubernetes apply configuration conventions.
client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (3)
27-32: LGTM - New fields properly integrated.The ResourceLabels and WorkloadIdentity fields are correctly added to support GCP Workload Identity Federation configuration with appropriate types.
73-84: LGTM - Defensive nil check prevents misuse.The WithResourceLabels method correctly implements the variadic append pattern with a nil panic to catch programming errors early. This is appropriate defensive programming for generated builder code.
86-92: LGTM - Standard setter pattern.The WithWorkloadIdentity method follows the correct builder pattern for setting pointer fields.
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
22-65: LGTM - Generated apply configuration correctly implements WIF structure.The GCPWorkloadIdentityConfigApplyConfiguration properly defines all required fields (ProjectNumber, PoolID, ProviderID, ServiceAccountsRef) with appropriate builder methods following Kubernetes apply configuration conventions. The nested ServiceAccountsRef reference is correctly typed.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (8)
5661-5670: GCP network name regex + doc look solid.Pattern and description match GCP Compute naming; no issues.
5674-5677: Network immutability rule is appropriate.Object-level immutability via self == oldSelf aligns with rest of CRD.
5682-5691: PSC subnet name validation is correct.Regex and limits conform to GCP resource naming.
5695-5697: PSC subnet immutability is correct.
5712-5713: Project ID regex matches stated rules.Starts with letter; 6–30 chars; hyphen rules OK.
5721-5730: Region pattern blocks zones and enforces trailing digits.Good balance vs. enumerating regions.
5792-5855: WIF poolID/providerID regex tightened to start with letter + reserved-prefix guard.This fixes the earlier leading-digit issue and blocks gcp- prefix; immutability is correct.
5821-5834: projectNumber numeric validation and immutability look good.api/hypershift/v1beta1/zz_generated.deepcopy.go (3)
1485-1494: GCPPlatformSpec deepcopy for ResourceLabels/WorkloadIdentity looks correctCloning the
ResourceLabelsslice withmake+copyavoids aliasing between copies, and value-copyingWorkloadIdentityis sufficient given it only contains value fields. This matches controller-gen’s typical patterns and should behave correctly when PlatformSpec is deep-copied.
1612-1625: DeepCopy implementations for GCP WIF support types are sufficient
GCPResourceLabel,GCPServiceAccountsRef, andGCPWorkloadIdentityConfigcontain only value fields (strings and a value-typed embedded struct), so the autogenerated shallow copies (*out = *inplus direct assignment ofServiceAccountsRef) are correct and won’t introduce shared mutable state.Also applies to: 1642-1671
3431-3435: Using DeepCopyInto for PlatformSpec.GCP is the right fixSwitching the GCP branch to allocate a new
GCPPlatformSpecand invokeDeepCopyIntoensures the newResourceLabelsslice (and other future composite fields) are properly deep-copied instead of aliasing the original.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5769-5778: LGTM on GCP name/project/region validations and immutability.Patterns for network/subnet names, project ID, and region plus immutability rules look correct and defensively scoped.
Also applies to: 5782-5784, 5791-5798, 5803-5805, 5812-5821, 5836-5838
5907-5963: Verification confirms the "gcp-" prefix restriction is correct and documented.The Google Cloud IAM docs confirm that the prefix "gcp-" is reserved and cannot be used in workload identity pool or provider IDs. The code's validation checks and descriptions accurately reflect this requirement. No changes are needed.
api/hypershift/v1beta1/gcp.go (5)
3-18: LGTM! Improved GCP resource naming validation.The updated pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$correctly enforces GCP's RFC1035-style naming requirements and is more readable than the previous regex. The expanded documentation clearly explains the validation rules.
20-54: LGTM! Solid RFC1035-compliant label validation.The validation patterns correctly enforce Compute Engine label requirements: no underscores, proper start/end character constraints, and reserved prefix blocking. The distinction between Key (must be non-empty) and Value (can be empty) aligns with GCP behavior.
70-83: LGTM! Appropriate immutability constraints.Network and subnet immutability is correct for GCP clusters, as these resources cannot be changed after cluster creation without breaking connectivity.
159-224: LGTM! Comprehensive WIF configuration with proper safeguards.The validation patterns correctly enforce GCP's WIF naming requirements, including the 4-32 character length constraint and reserved prefix blocking. The immutability constraints appropriately prevent breaking the authentication chain, and the detailed comments provide valuable context for users setting up WIF.
85-157: LGTM! Well-structured GCP platform configuration.The validation patterns for Project and Region are correct, and the 60-item limit on ResourceLabels appropriately reserves capacity for system labels. The required, immutable WorkloadIdentity field is appropriate for preventing authentication chain breakage (and backward compatibility is addressed via feature-gating per past review discussion).
Verification confirms: All 42 current GCP region IDs follow the pattern with letter groups separated by hyphens and ending with numeric suffixes, so the region regex pattern
^[a-z]+(-[a-z0-9]+)+[0-9]+$is correct and comprehensive.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (6)
5372-5388: GCP network name regex + immutability LGTM.Pattern matches GCP VPC naming and
self == oldSelfis appropriate.
5393-5408: PSC subnet name regex + immutability LGTM.Matches GCP subnet naming and prevents day-2 drift.
5414-5427: Project ID validation is correct.Pattern enforces 6–30, lowercase/digits/hyphen, starts with letter, no trailing hyphen; aligns with GCP rules.
5432-5444: Region validation looks good.Structural check excludes zones (must end with digits) and allows multi-segment regions.
5497-5604: Workload Identity Federation schema + immutability LGTM.Field regexes, reserved-prefix bans, and object immutability look solid.
5573-5593: GSA email regex LGTM; immutable fits intent.Covers typical 6–30 char SA IDs and project IDs with required domain suffix.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (7)
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5842-5892: Enforce unique label keys and clarify reserved prefix wording.
- Add list‑map semantics so duplicate keys are rejected at admission and merge works predictably.
- Wording: since you intentionally reserve any key starting with “goog” (broader than GCP’s “goog-”), say “reserved by HyperShift” to avoid implying this is a GCP rule.
Apply on resourceLabels (array):
resourceLabels: @@ - maxItems: 60 - type: array + maxItems: 60 + type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - keyAnd on the key description:
- GCP reserves the 'goog' prefix for system labels. + HyperShift intentionally reserves any key starting with 'goog' to avoid collisions with Google-reserved labels.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4867-4974: Add a cross-field guard tying nodePoolEmail domain to the configured project.Prevents mismatched project IDs in GSA emails (common typo). Add at platform.gcp scope:
gcp: description: gcp specifies configuration for clusters running on Google Cloud Platform. properties: @@ type: object + x-kubernetes-validations: + - message: serviceAccountsRef.nodePoolEmail must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || + !has(self.workloadIdentity.serviceAccountsRef) || + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1] + == (self.project + ".iam.gserviceaccount.com")
4979-4980: Keeping workloadIdentity required is fine under the GCPPlatform feature gate.Given this CRD is feature-gated, requiring it won’t break existing non-GCP users. No change requested.
docs/content/reference/api.md (1)
6263-6268: Fix broken regex in “Pattern” (HTML anchor rendered inside regex).Replace the invalid anchor with a copy/paste‑able regex and wrap it in code to prevent linkification. Also ensure the source Go comment is updated and docs regenerated via make api-docs.
Apply this doc change:
-Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. +Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.And keep the surrounding text: “Must start with a lowercase letter and end with a letter or digit.”
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5554-5603: Enforce unique resource label keys at the schema levelArray allows duplicate keys today; this creates last‑write‑wins ambiguity and SSA merge drift. Make the list a map keyed by “key” to enforce uniqueness and improve apply semantics.
Apply this minimal change:
resourceLabels: items: @@ maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5785: Enforce unique GCP label keys (CEL) to avoid ambiguous duplicatesDuplicate keys are currently allowed in spec.platform.gcp.resourceLabels. This can lead to last-write-wins ambiguity across controllers. Add a list-level CEL to guarantee uniqueness by key without changing list semantics.
Apply:
maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key)) items:cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5445-5495: Enforce unique label keys; keep 60-item cap.You cap at 60 (good headroom), but duplicate keys are still allowed and can be ambiguous downstream. Add an array-level CEL rule to ensure keys are unique while keeping list semantics/order.
Apply this diff near resourceLabels:
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. ... + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster. ... maxItems: 60 type: array
🧹 Nitpick comments (8)
api/hypershift/v1beta1/gcp.go (1)
103-117: Region validation pattern is correct, but MinLength could be more precise.The region pattern
^[a-z]+(-[a-z0-9]+)+[0-9]+$correctly enforces GCP region format (e.g., "us-central1", "europe-west2") and will reject invalid formats. However,MinLength=1is inconsistent with the pattern's actual minimum of approximately 4-6 characters. While the pattern provides the real enforcement (making this a cosmetic issue), consider updatingMinLengthto better reflect the actual constraint.Consider updating to better align schema metadata with the pattern:
// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MinLength=6api/hypershift/v1beta1/gcp_validation_test.go (1)
7-101: Tests are effectively no-ops and don’t exercise the actual validation behavior.Both
TestGCPResourceLabelandTestGCPRegionPatternonly assert thatKey/regionare non-empty, and every table entry is already non-empty. As written, these tests can’t fail in any realistic scenario and don’t validate the RFC1035 patterns, reservedgoogprefix rules, or region regexes you’ve added at the API/CRD level. They mainly add maintenance cost and a misleading impression of coverage.Consider either:
- Adding assertions that actually exercise the validation logic (e.g., via helper functions mirroring the regexes, or by inspecting the generated CRD/OpenAPI schema and including negative cases), or
- Removing these tests entirely if meaningful validation can only be done at a higher level (e.g., envtest-based CRD validation).
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4816-4865: Ensure label keys are unique and get proper merge semantics.Today duplicates can slip through; prefer Kubernetes list-as-map to enforce uniqueness and avoid last-wins merges.
Apply under resourceLabels:
resourceLabels: description: |- @@ items: @@ type: object maxItems: 60 type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - keycmd/cluster/gcp/create_test.go (1)
74-93: Consider refactoring test cases to reduce verbosity.The test cases manually construct
RawCreateOptionswith all fields, making them verbose and harder to maintain. Consider starting fromvalidOptsand selectively clearing the field being tested.Example refactor:
tests := map[string]struct { - opts RawCreateOptions + setupOpts func() RawCreateOptions expectErr bool expectSubstr string }{ "missing project": { - opts: RawCreateOptions{Region: validOpts.Region, Network: validOpts.Network, PrivateServiceConnectSubnet: validOpts.PrivateServiceConnectSubnet, WorkloadIdentityProjectNumber: validOpts.WorkloadIdentityProjectNumber, WorkloadIdentityPoolID: validOpts.WorkloadIdentityPoolID, WorkloadIdentityProviderID: validOpts.WorkloadIdentityProviderID, NodePoolServiceAccountEmail: validOpts.NodePoolServiceAccountEmail}, + setupOpts: func() RawCreateOptions { + opts := validOpts + opts.Project = "" + return opts + }, expectErr: true, expectSubstr: "required flag(s) \"project\" not set", }, "missing region": { - opts: RawCreateOptions{Project: validOpts.Project, Network: validOpts.Network, PrivateServiceConnectSubnet: validOpts.PrivateServiceConnectSubnet, WorkloadIdentityProjectNumber: validOpts.WorkloadIdentityProjectNumber, WorkloadIdentityPoolID: validOpts.WorkloadIdentityPoolID, WorkloadIdentityProviderID: validOpts.WorkloadIdentityProviderID, NodePoolServiceAccountEmail: validOpts.NodePoolServiceAccountEmail}, + setupOpts: func() RawCreateOptions { + opts := validOpts + opts.Region = "" + return opts + }, expectErr: true expectSubstr: "required flag(s) \"region\" not set", }, "missing network": { - opts: RawCreateOptions{Project: validOpts.Project, Region: validOpts.Region, PrivateServiceConnectSubnet: validOpts.PrivateServiceConnectSubnet, WorkloadIdentityProjectNumber: validOpts.WorkloadIdentityProjectNumber, WorkloadIdentityPoolID: validOpts.WorkloadIdentityPoolID, WorkloadIdentityProviderID: validOpts.WorkloadIdentityProviderID, NodePoolServiceAccountEmail: validOpts.NodePoolServiceAccountEmail}, + setupOpts: func() RawCreateOptions { + opts := validOpts + opts.Network = "" + return opts + }, expectErr: true, expectSubstr: "required flag(s) \"network\" not set", }, "all required fields provided": { - opts: validOpts, + setupOpts: func() RawCreateOptions { return validOpts }, expectErr: false, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { - _, err := tc.opts.Validate(context.Background(), &core.CreateOptions{}) + _, err := tc.setupOpts().Validate(context.Background(), &core.CreateOptions{}) if tc.expectErr {docs/content/reference/api.md (1)
5991-6030: New GCP fields read well; one suggestion on WIF prerequisites.WIF prerequisites are helpful. Consider explicitly stating immutability for workloadIdentity subfields (poolID/providerID/projectNumber) in the prose to align with the “immutable after cluster creation” note and avoid day‑2 drift attempts.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5497-5604: Add cross-field check: nodePoolEmail’s project must match spec.gcp.project.Regexes/immutability look solid. To prevent misconfig (wrong project in the GSA email), add a CEL validation at the gcp level that ties nodePoolEmail’s domain to spec.gcp.project.
Example diff under spec.platform.gcp (same level as properties: …, required: …):
gcp: description: gcp specifies configuration for clusters running on Google Cloud Platform. properties: endpointAccess: ... + x-kubernetes-validations: + - message: workloadIdentity.serviceAccountsRef.nodePoolEmail must belong to the same project as spec.platform.gcp.project + rule: 'has(self.project) && has(self.workloadIdentity) && has(self.workloadIdentity.serviceAccountsRef) ? + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.endsWith(sprintf("@%s.iam.gserviceaccount.com", self.project)) : true'api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (2)
4708-4757: Enforce uniqueness of label keys to prevent duplicate entries.As modeled, resourceLabels is an array and can accept duplicate keys. Make it a map-list keyed by "key" so duplicates are rejected and merges behave predictably.
resourceLabels: @@ - items: + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - key + items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster.
4799-4807: Tighten projectNumber lower bound (verify exact spec).Today’s regex allows any 1+ digits; consider a safer floor (e.g., 6) to catch obvious mistakes while still future‑proof. Please verify the officially documented length range before changing.
- minLength: 1 + minLength: 6If docs indicate a different minimum/maximum, adjust accordingly.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (20)
api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go
- client/applyconfiguration/utils.go
- client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go
- cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
api/hypershift/v1beta1/hostedcluster_conditions.goapi/hypershift/v1beta1/hostedcluster_types.goapi/hypershift/v1beta1/gcp_validation_test.goclient/applyconfiguration/hypershift/v1beta1/gcpplatformspec.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/cluster/gcp/create.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.deepcopy.goapi/hypershift/v1beta1/gcp.godocs/content/reference/api.mdcmd/cluster/gcp/create_test.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml
🧬 Code graph analysis (7)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
api/hypershift/v1beta1/hosted_controlplane.go (1)
ConditionType(294-294)
api/hypershift/v1beta1/gcp_validation_test.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-54)
client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (4)
client/applyconfiguration/hypershift/v1beta1/gcpnetworkconfig.go (1)
GCPNetworkConfigApplyConfiguration(22-25)api/hypershift/v1beta1/gcp.go (1)
GCPEndpointAccessType(58-58)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabelApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfigApplyConfiguration(22-27)
cmd/cluster/gcp/create.go (2)
cmd/util/util.go (1)
ValidateRequiredOption(11-16)support/globalconfig/network.go (1)
NetworkConfig(23-29)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(228-248)GCPWorkloadIdentityConfig(162-224)
api/hypershift/v1beta1/gcp.go (2)
test/e2e/util/external_oidc.go (1)
Key(289-292)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
cmd/cluster/gcp/create_test.go (2)
support/globalconfig/network.go (1)
NetworkConfig(23-29)cmd/cluster/gcp/create.go (2)
RawCreateOptions(30-54)CreateOptions(119-122)
🔇 Additional comments (42)
api/hypershift/v1beta1/hostedcluster_types.go (1)
129-131: LGTM! Consistent addition for GCP CAPI provider image override.The new constant follows the established pattern for CAPI provider image overrides and is properly placed alongside other provider-specific constants.
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: LGTM! Well-documented GCP validation conditions.The new condition types follow the established pattern for platform-specific validation conditions and are appropriately placed alongside other cloud provider validation conditions.
api/hypershift/v1beta1/gcp.go (1)
226-248: LGTM! GSA email validation is correct and addresses previous review feedback.The pattern correctly enforces Google Service Account email format, and the
MinLength=37accurately reflects the minimum possible length (6-char service account name + '@' + 6-char project + 24-char domain suffix). This properly addresses the feedback from the previous review.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (6)
5769-5778: LGTM: GCP network name validation and immutability are correct.Also applies to: 5782-5785
5791-5798: LGTM: Subnet name validation and immutability look good.Also applies to: 5803-5805
5811-5821: LGTM: Project ID pattern matches GCP constraints and prevents trailing hyphen.
5826-5838: LGTM: Region validation is precise (regions only) and immutable.Also applies to: 5840-5841
5894-6001: ****Google reserves the "gcp-" prefix for both workload identity pool IDs and provider IDs, as documented in the official Google Cloud IAM guidance. The validation rules in this CRD correctly enforce this documented requirement. The code comments accurately reflect this constraint, and the regex pattern and immutability validations are appropriate.
Likely an incorrect or invalid review comment.
6003-6007: Gating verified: workloadIdentity is correctly required only in gated CRDs.Verification confirms proper implementation:
- Default variant: workloadIdentity NOT present (standard, non-gated)
- CustomNoUpgrade variant: workloadIdentity required at line 6006 (gated)
- TechPreviewNoUpgrade variant: workloadIdentity required at line 5717 (gated)
The code correctly restricts the workloadIdentity requirement to feature-gated CRD variants, with the standard Default variant remaining unaffected.
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
20-37: Generated applyconfig forGCPServiceAccountsReflooks correct and consistent.Struct shape, JSON tag, constructor, and
WithNodePoolEmailsetter all match existing applyconfiguration patterns; no issues found.client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (1)
27-32: NewResourceLabelsandWorkloadIdentityapply fields/methods look consistent with existing patterns.Field additions and
WithResourceLabels/WithWorkloadIdentitymatch the established applyconfiguration style (including nil-guard + panic on variadic inputs); no functional or maintainability issues spotted.Also applies to: 73-92
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (4)
4742-4757: GCP network name validation and immutability look good.Pattern and immutability rule align with GCP resource naming (start letter, [-a-z0-9], <=63). No issues.
4763-4778: PSC subnet name validation and immutability look good.Same constraints as network name; consistent with GCP requirements.
4793-4797: Project ID regex is correct.Enforces 6–30 chars, starts with letter, no trailing hyphen. Immutable guard is appropriate.
4802-4811: Region format validation is reasonable.Requires at least one hyphen and trailing digits; blocks zone suffixes. Immutable guard is appropriate.
cmd/cluster/gcp/create_test.go (1)
22-58: LGTM! Comprehensive test coverage.The test properly verifies that all new GCP WIF-related fields are correctly mapped from CLI options to the HostedCluster spec, ensuring the integration works end-to-end.
cmd/cluster/gcp/create.go (3)
18-66: LGTM! Clear field declarations and helpful flag descriptions.The flag bindings properly reference
hypershift infra create gcpoutput, which guides users to obtain the required WIF configuration values.
88-105: Verify that making all WIF fields required is intentional.All Workload Identity Federation fields (
--workload-identity-project-number,--workload-identity-pool-id,--workload-identity-provider-id,--node-pool-service-account-email) are now mandatory. This means WIF is required for all GCP clusters.If WIF is the only supported authentication method for HyperShift on GCP, this is correct. However, if there are scenarios where users might not want WIF (e.g., using alternative authentication), making these fields unconditionally required could be overly restrictive.
Based on learnings, ensure this aligns with the GCP platform requirements. If WIF is optional, consider adding conditional validation or making these fields optional with appropriate defaults.
168-193: LGTM! Clean mapping of CLI options to API types.The implementation correctly populates the GCP-specific configuration with network and WIF settings, maintaining a clear structure that aligns with the API design.
api/hypershift/v1beta1/zz_generated.deepcopy.go (3)
1612-1671: LGTM! Properly generated DeepCopy methods.The auto-generated DeepCopy methods for
GCPResourceLabel,GCPServiceAccountsRef, andGCPWorkloadIdentityConfigfollow the standard pattern with appropriate nil checks.
1485-1494: LGTM! Correct deep copy logic for GCP fields.The DeepCopyInto method properly handles:
ResourceLabels: Allocates a new slice and copies elementsWorkloadIdentity: Direct assignment is correct since the type contains only value types
3431-3435: LGTM! Important fix for proper deep copying.Line 3434 now correctly calls
DeepCopyIntoinstead of shallow assignment. This ensures nested fields likeResourceLabelsare properly deep copied, preventing shared references between copies.docs/content/reference/api.md (4)
5954-5959: Region validation text looks correct.Examples and invalid cases are precise; guidance to avoid zone suffixes is clear.
6181-6236: Label constraints are accurately captured.RFC1035-style rules and ‘goog’ reserved prefix guidance match GCE requirements. LGTM.
6289-6310: Verify IAM roles for nodePoolEmail GSA (least‑privilege).Current list includes roles/compute.instanceAdmin.v1 and roles/compute.networkAdmin. Many CAPG setups also need roles/iam.serviceAccountUser to attach a VM service account; please confirm against your “cmd/infra/gcp/iam-bindings.json” and CAPG version, and update the list or add a note to rely on that file as the source of truth.
5038-5049: Condition names added — ensure cross‑repo consistency.Validate that “ValidGCPCredentials” and “ValidGCPWorkloadIdentity” exactly match the condition constants used in CRDs/controllers and any status reporting, to avoid doc/code drift.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (5)
5480-5496: LGTM: Network name validation + immutabilityRegex and object‑level immutability look correct for GCP VPC network names.
5501-5516: LGTM: Private Service Connect subnet name + immutabilityConsistent RFC1035‑style pattern and immutability.
5531-5535: LGTM: GCP project ID regexPattern matches documented constraints (start with letter, hyphens allowed, 6–30, no trailing hyphen) and is immutable.
5541-5552: LGTM: Region format regexForbids zones and enforces trailing digits; immutable.
5605-5712: LGTM: Workload Identity Federation schemaRequired + immutable, reserved prefix checks, and hardened patterns look solid.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5799-5855: WIF IDs: leading-letter + reserved-prefix guard — looks goodpoolID/providerID now require a leading letter and block the reserved 'gcp-' prefix. This aligns with GCP rules and prevents invalid configs from passing CRD validation.
5863-5881: Service account email regex (modern domain only) — acknowledgedStrictly allowing PROJECT_ID.iam.gserviceaccount.com and excluding legacy developer.gserviceaccount.com is intentional here. Pattern bounds and immutability look correct.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (4)
5372-5387: LGTM on GCP network/subnet name rules and immutability.Patterns match GCP resource-name requirements and immutability is applied at the object level.
Also applies to: 5393-5408
5423-5427: LGTM on GCP project ID regex and immutability.The tightened pattern enforces 6–30, lowercase, hyphen, no trailing hyphen, and is immutable.
5432-5444: Region regex looks right.Pattern excludes zones (e.g., “-a”), requires at least one hyphen and trailing digits; immutability included.
5609-5610: LGTM on making workloadIdentity required for GCP.Consistent with introducing WIF as the supported auth path for this TechPreview CRD.
Please confirm this won’t block existing non-WIF clusters from applying TechPreview HCPs accidentally.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (5)
4634-4649: GCP network name validation + immutability look correct.Regex and immutability match Compute Engine naming rules; no issues spotted.
4655-4670: PSC subnet name validation + immutability look correct.Consistent with network name rules; good guardrails.
4685-4689: Project ID regex is appropriately strict.Length, charset, start/end constraints align with GCP guidance; immutability is appropriate.
4694-4706: Region pattern excludes zones and enforces trailing digits — LGTM.Examples given match the pattern; immutability is appropriate.
4759-4866: WIF fields and immutability are well‑designed. One question on required-ness.Schema and reserved‑prefix checks look solid. Confirm that making workloadIdentity required under gcp is intentional for all gated clusters; otherwise consider making it optional initially with validation/conditions guiding users.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (6)
docs/content/reference/api.md (1)
6263-6267: Fix invalid regex (HTML anchor leaked into “Pattern”) and regenerate docs.The rendered “Pattern” is not a regex; it includes an HTML anchor. Replace with a literal, copy/paste‑able regex and keep the 63‑char note. Update the source Go comment (for hypershift/v1beta1.GCPResourceReference.name), wrap the regex in backticks, then re-run make api-docs.
Apply in docs after regeneration:
-Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. +Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Also keep the prose “Must start with a lowercase letter and end with a letter or digit.”
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4867-4974: WIF: add a cross-field guard for project consistency and tighten projectNumber length.
- Add a CEL rule ensuring serviceAccountsRef.nodePoolEmail domain matches .project (early typo catch).
- projectNumber allows any length; suggest 6–20 to avoid obvious input errors while staying flexible.
Proposed diffs:
- Cross-field validation under the gcp object:
gcp: type: object + x-kubernetes-validations: + - message: serviceAccountsRef.nodePoolEmail must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || + !has(self.workloadIdentity.serviceAccountsRef) || + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1] + == (self.project + ".iam.gserviceaccount.com")
- projectNumber length tweak:
projectNumber: ... - maxLength: 25 - minLength: 1 + maxLength: 20 + minLength: 6api/hypershift/v1beta1/gcp.go (1)
241-247: MinLength is off by one character.Based on the pattern, the minimum valid email length is 37 characters:
- Service account name: 6 chars (min from
[a-z][a-z0-9-]{4,28}[a-z0-9])@: 1 char- Project ID: 6 chars (same pattern)
.iam.gserviceaccount.com: 24 chars- Total: 37 chars
MinLength=38would incorrectly reject the shortest valid emails.// +kubebuilder:validation:Pattern=`^[a-z][a-z0-9-]{4,28}[a-z0-9]@[a-z][a-z0-9-]{4,28}[a-z0-9]\.iam\.gserviceaccount\.com$` -// +kubebuilder:validation:MinLength=38 +// +kubebuilder:validation:MinLength=37 // +kubebuilder:validation:MaxLength=100cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5785: Enforce unique label keys at the array level (no list‑map semantics).Duplicate label keys are currently allowed; last-write-wins is ambiguous. Add a CEL x-kubernetes-validations rule on the array to guarantee uniqueness by key.
Apply under spec.platform.gcp.resourceLabels:
resourceLabels: ... - maxItems: 60 - type: array + maxItems: 60 + type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key)) items: properties: key: ...cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5554-5604: Enforce unique label keys for resourceLabelsAllowing duplicates introduces last-write-wins ambiguity and complicates SSA merges. Make the list a keyed map by "key" to enforce uniqueness at the API level.
Apply this minimal change to the list metadata:
resourceLabels: items: properties: key: # …existing key schema… value: # …existing value schema… required: - key - value type: object maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5446-5495: Enforce unique label keys for resourceLabels (array-level CEL).Duplicate keys can cause ambiguous downstream behavior. Keep list semantics and add a CEL uniqueness rule at the array level.
Apply this diff near resourceLabels (array scope):
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. ... + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster. ... maxItems: 60 type: arrayNote: This preserves order and avoids list-map semantics while preventing duplicates.
🧹 Nitpick comments (8)
api/hypershift/v1beta1/gcp_validation_test.go (1)
7-101: Tests are lightweight smoke checks; consider strengthening if you want real validation coverageRight now both tests only assert non‑empty fields (label key, region), so they’ll pass even if the underlying CEL regexes or reserved‑prefix rules are accidentally weakened, as long as these sample values remain non‑empty. That’s fine as a compile‑time/smoke check, but if you want these tests to guard the new GCP constraints more strongly, consider (in a follow‑up):
- Adding explicit negative cases (e.g. keys starting with
goog, bad region formats) and- Either reusing a shared validation helper or at least mirroring the regexes in Go so failures surface here and not only via CRD/apiserver tests.
Not critical, but would increase the tests’ signal if you decide it’s worth the extra maintenance.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4802-4811: Tighten region regex to avoid accepting invalid multi-hyphen regions.Current pattern allows extra “-segment”s (e.g., “us-central1-1”). Recommend exactly one hyphen and trailing digits.
Apply this diff:
- pattern: ^[a-z]+(-[a-z0-9]+)+[0-9]+$ + pattern: ^[a-z]+-[a-z]+[a-z0-9]*[0-9]$
4815-4865: Enforce unique label keys and keep constraints — switch list to map semantics.Constraints on key/value and ‘goog’ prefix are solid. To prevent duplicate keys, use map-style list with key as the map key.
Apply this diff:
resourceLabels: ... - items: + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + items: properties: key: ... value: ... - maxItems: 60 + maxItems: 60 type: arraycmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5605-5712: Consider consolidating immutability to object-level for WorkloadIdentityYou already have
x-kubernetes-validations: self == oldSelfon workloadIdentity. Keeping per-field immutability rules duplicates checks and increases churn on future schema changes. Prefer object-level immutability only; retain per-field constraints (length/pattern) for shape validation.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5842-5892: Prevent duplicate GCP label keys (uniqueness).As written, duplicate keys can be submitted in resourceLabels. Recommend list-map semantics for SSA + validation, or add a CEL guard.
Option A (preferred): treat list as a map keyed by “key”.
resourceLabels: maxItems: 60 type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - key items: type: objectOption B (CEL guard) if you prefer to keep list-type: atomic.
resourceLabels: maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self.all(x, self.exists_one(y, x.key == y.key))
5894-6001: Guard against mismatched project in service account email.Add a cross-field validation ensuring workloadIdentity.serviceAccountsRef.nodePoolEmail belongs to the same project as platform.gcp.project to avoid silent misconfig.
gcp: properties: ... required: - networkConfig - project - region - workloadIdentity type: object + x-kubernetes-validations: + - message: serviceAccountsRef.nodePoolEmail project must match platform.gcp.project + rule: > + !has(self.workloadIdentity) || + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@", 2)[1].endsWith(".iam.gserviceaccount.com") && + self.workloadIdentity.serviceAccountsRef.nodePoolEmail + .split("@", 2)[1] + .split(".iam.gserviceaccount.com", 2)[0] == self.projectAlso applies to: 6003-6008
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (2)
4708-4757: Enforce label key uniqueness via list=map for resourceLabels.Today duplicates can slip in; GCP treats labels as a map. Make the list a map keyed by "key" to guarantee uniqueness and better patch semantics.
Apply this minimal diff in the resourceLabels array block:
resourceLabels: items: properties: key: ... required: - key - value type: object maxItems: 60 - type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map + type: array
4759-4866: WIF types/immutability look good; add cross-field check for GSA email project.Great coverage on pool/provider IDs, reserved prefixes, and hardened SA email regex. Add a CEL guard to ensure nodePoolEmail’s project matches spec.platform.gcp.project to avoid subtle misconfigurations.
Apply at the gcp object level (same scope as project/region):
gcp: properties: project: ... workloadIdentity: ... + x-kubernetes-validations: + - message: serviceAccountsRef.nodePoolEmail must belong to the same project as spec.platform.gcp.project + rule: '!has(self.workloadIdentity) || self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@").size() == 2 && self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1] == (self.project + ".iam.gserviceaccount.com")'Note: placing this at the gcp object allows referencing both fields in one rule.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (20)
api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- cmd/cluster/gcp/create.go
- client/applyconfiguration/utils.go
- client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go
- client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
api/hypershift/v1beta1/hostedcluster_conditions.goapi/hypershift/v1beta1/hostedcluster_types.goclient/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.gocmd/cluster/gcp/create_test.gocmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamldocs/content/reference/api.mdapi/hypershift/v1beta1/gcp.goapi/hypershift/v1beta1/zz_generated.deepcopy.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/gcp_validation_test.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (5)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
api/hypershift/v1beta1/hosted_controlplane.go (1)
ConditionType(294-294)
cmd/cluster/gcp/create_test.go (1)
cmd/cluster/gcp/create.go (2)
RawCreateOptions(30-54)CreateOptions(119-122)
api/hypershift/v1beta1/gcp.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(228-248)GCPWorkloadIdentityConfig(162-224)
api/hypershift/v1beta1/gcp_validation_test.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-54)
🔇 Additional comments (35)
api/hypershift/v1beta1/hostedcluster_types.go (1)
129-131: GCP CAPI provider image annotation matches existing patternThe new
ClusterAPIGCPProviderImageconstant is consistent with other CAPI provider image override annotations and introduces no behavioral risk. LGTM.api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: New GCP conditions are consistent with existing condition taxonomy
ValidGCPCredentialsandValidGCPWorkloadIdentityfollow the established condition naming and documentation style (AWS/Azure counterparts) and give controllers clear hooks to surface GCP failures. No issues from an API/compatibility standpoint.api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
1485-1494: GCP deep‑copy semantics look correct and avoid aliasing
GCPPlatformSpec.DeepCopyIntonow:
- Deep‑copies
ResourceLabelsby allocating a new slice and copying value elements.- Copies
WorkloadIdentityby value, which is appropriate given it andGCPServiceAccountsRefare value‑only structs.- New DeepCopy helpers for
GCPResourceLabel,GCPServiceAccountsRef, andGCPWorkloadIdentityConfigare straightforward and correct for their field shapes.PlatformSpec.DeepCopyIntonow deep‑copies theGCPpointer viaDeepCopyInto, preventing shared mutable state across copies.Overall this generated code matches the new GCP API types and should behave correctly.
Also applies to: 1612-1625, 1642-1655, 1657-1671, 3394-3435
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
42-52: Fixture updates align with new GCP validation requirementsThe updated fixture now includes non‑empty network/subnet names and a
workloadIdentityblock whose values match the documented GCP regex constraints (project number, pool/provider IDs, and service account email). This should keep the “minimal flags” test meaningful as the API tightens validation.docs/content/reference/api.md (2)
5038-5049: Align condition type naming for GCP WIF validation.Docs list “ValidGCPWorkloadIdentity”, while the PR summary mentions “ValidWorkloadIdentityConfiguration”. Use a single, canonical ConditionType across code, CRDs, and docs to avoid confusion, then regenerate docs.
6297-6307: Current documentation is accurate per authoritative iam-bindings.json source.The documentation at lines 6297-6307 correctly reflects the roles defined in
cmd/infra/gcp/iam-bindings.jsonfor thenodepool-mgmtservice account:
- roles/compute.instanceAdmin.v1
- roles/compute.networkAdmin
The suggested
roles/iam.serviceAccountUserrole is not present in the authoritative IAM bindings file referenced in the documentation itself. No changes needed.Likely an incorrect or invalid review comment.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (4)
4742-4757: GCP network name regex and immutability look correct.Pattern matches GCP naming rules and immutability guard is appropriate.
4763-4778: Subnet name validation and immutability look good.Matches GCP constraints; object-level immutability is fine here.
4785-4797: Project ID validation looks right.Regex enforces 6–30 chars, start with letter, no trailing hyphen — aligns with GCP rules. Immutability guard is correct.
4976-4980: Requiring workloadIdentity is OK under the GCPPlatform feature gate.Given this CRD is feature-gated, making workloadIdentity required here won’t impact existing non-GCP clusters.
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
1-47: LGTM - Generated apply configuration code.This is auto-generated code following standard controller-runtime patterns for server-side apply. The fluent builder pattern is correctly implemented.
cmd/cluster/gcp/create_test.go (3)
63-97: Good use of baselinevalidOptsfor test maintainability.The pattern of defining a valid baseline and selectively omitting fields for negative test cases is clean. The test coverage for the new required fields (network, WIF configuration) is appropriate.
52-57: Assertions correctly verify the new API structure.The test properly validates that CLI options are correctly mapped to the nested
GCPPlatformSpecfields includingNetworkConfig,WorkloadIdentity, andServiceAccountsRef.
131-146: Integration test updated with all required flags.The minimal flags test case is appropriately updated to include the new required GCP flags, ensuring the CLI rendering works end-to-end.
api/hypershift/v1beta1/gcp.go (4)
6-18: Improved resource name pattern.The updated pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$correctly allows single-character names (just "a") while still enforcing GCP naming rules. The optional group properly handles the case where hyphens and digits can appear in the middle but names must end with a letter or digit.
20-54: Well-documented RFC1035 label validation.The patterns correctly enforce Compute Engine label requirements. Good documentation noting that other GCP services may have different rules. The CEL validation for the reserved 'goog' prefix is appropriate.
102-117: Region pattern correctly enforces GCP region format.The pattern
^[a-z]+(-[a-z0-9]+)+[0-9]+$correctly validates regions (e.g.,us-central1,europe-west12) while rejecting zones (e.g.,us-central1-a) and invalid formats (e.g.,us1,us-central). The comments clearly document valid and invalid examples.
159-224: Workload Identity configuration is well-structured.The validation constraints are internally consistent - PoolID/ProviderID patterns enforce 4-32 characters which matches the documented and annotated length constraints. The reserved
gcp-prefix is correctly blocked via CEL validation, and immutability is properly enforced.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5799-5856: WIF IDs: good fix to require a leading letter; please verify across generated CRDs.poolID/providerID now start with a letter and are immutable. Looks correct. Please confirm all CRDs (HostedClusters/HostedControlPlanes, Custom/TechPreview) and the Go types carry the same pattern.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (5)
5480-5496: GCP network name validation looks correctPattern matches GCP RFC1035-style names and immutability is enforced. LGTM.
5501-5516: GCP PSC subnet name validation looks correctPattern and immutability align with GCP rules. LGTM.
5531-5535: Project ID regex + immutability: good coverageRegex enforces GCP rules (6–30 chars, starts letter, no trailing dash). Immutability is appropriate. LGTM.
5537-5549: Region format validation is sensibleRejects zone suffixes and requires trailing digits; permissive enough for future regions. LGTM.
5717-5718: Verify consumer paths for required workloadIdentity field in GCP platform specThe workloadIdentity field is marked as required in both TechPreviewNoUpgrade and CustomNoUpgrade CRD variants. Infrastructure code exists to create Workload Identity Pool, OIDC Provider, and service accounts via a separate
create_iamCLI command, and API documentation includes prerequisites and configuration requirements for workloadIdentity.However, verification found no practical examples in
examples/directory and no e2e tests demonstrating complete GCP cluster creation with workloadIdentity populated. Thecreate_iamCLI operates independently, requiring users to manually wire its output into the cluster spec. Confirm that:
- CLI/operator flow documents this two-step process clearly
- Test coverage validates end-to-end GCP cluster creation with workloadIdentity
- User-facing examples show how to combine
create_iamoutput with cluster manifestcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (5)
5372-5387: GCP network name regex + immutability: LGTMPattern matches GCP VPC naming and is immutable as intended.
5393-5408: PSC subnet name regex + immutability: LGTMConsistent with GCP resource naming and locked post‑create.
5423-5427: Project ID validation: LGTMRegex, length bounds, and immutability align with GCP rules.
5432-5444: Region format validation: LGTMPattern excludes zones (e.g., “-a”) and enforces digit suffix; immutability added.
5497-5604: Confirm intent: workloadIdentity is required and fully immutable.Making workloadIdentity required (Line 5606) and immutable is a strong contract. Given this PR adds only the API layer (no controller), confirm this won’t block existing GCP users or day‑2 adjustments during TechPreview rollout.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5769-5785: GCP name/project/region validations look solid.Regexes and immutability rules align with GCP docs and RFC1035-style constraints. No issues from me here.
Also applies to: 5791-5805, 5820-5824, 5830-5838
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (5)
4634-4650: GCP network name regex + immutability look correct.Meets Compute Engine rules; object-level immutability is fine.
4655-4670: Private Service Connect subnet name validation is solid.Pattern and immutability align with GCP naming.
4676-4686: Project ID pattern tightened appropriately.Length and boundary rules match GCP constraints; no issues spotted.
4868-4872: Making workloadIdentity required: confirm gating and CLI UX.Since workloadIdentity is now required for GCP, confirm:
- The feature gate and CLI validations surface clear errors when omitted.
- Docs and examples are updated accordingly.
4694-4703: Region pattern validation confirmed.The regex pattern correctly validates GCP region format. Test results confirm all valid regions pass and common mistakes (missing hyphens, missing trailing digits, zone suffixes, uppercase letters, double hyphens) are properly rejected.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (8)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4938-4986: CEL guard: ensure GSAs belong to the configured GCP project.Add a cross-field validation so controlPlaneEmail/nodePoolEmail domains match .project to avoid hard-to-debug mismatches.
gcp: description: gcp specifies configuration for clusters running on Google Cloud Platform. properties: @@ type: object + x-kubernetes-validations: + - message: serviceAccountsRef.controlPlaneEmail must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || !has(self.workloadIdentity.serviceAccountsRef) || + self.workloadIdentity.serviceAccountsRef.controlPlaneEmail.split("@")[1] == + (self.project + ".iam.gserviceaccount.com") + - message: serviceAccountsRef.nodePoolEmail must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || !has(self.workloadIdentity.serviceAccountsRef) || + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1] == + (self.project + ".iam.gserviceaccount.com")Based on learnings, the requirement was previously discussed as optional given the feature gate; still a low-cost safety net.
docs/content/reference/api.md (1)
6263-6267: Fix invalid regex rendering (HTML anchor leaked into “Pattern”).The regex for GCPResourceReference.name is broken in the generated docs (contains an HTML anchor). Replace with a copy/paste‑able pattern and keep the 63‑char note. Update the source Go comment to wrap the regex in backticks and regenerate docs.
Apply this doc change:
-Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. +Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Tip: In api/hypershift/v1beta1/gcp.go, wrap the regex in backticks in the field doc and run
make api-docsso it renders as code, not a link.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5785: Enforce unique GCP label keys (keep maxItems=60 headroom).The resourceLabels array permits duplicate keys, causing ambiguous last-write-wins behavior at reconciliation time. Add a CEL uniqueness check at the array level to guarantee keys are unique without switching list semantics.
Apply under spec.platform.gcp.resourceLabels:
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. @@ maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))api/hypershift/v1beta1/gcp.go (1)
226-267: Service account email MinLength is off by one vs the regex and blocks valid addressesThe regex for
NodePoolEmail/ControlPlaneEmail:
^[a-z][a-z0-9-]{4,28}[a-z0-9]@[a-z][a-z0-9-]{4,28}[a-z0-9]\.iam\.gserviceaccount\.com$implies a minimum length of:
- local part: 1 + 4 + 1 = 6
@: 1- project ID: 1 + 4 + 1 = 6
- suffix
.iam.gserviceaccount.com: 24Total minimum: 6 + 1 + 6 + 24 = 37 characters.
With
+kubebuilder:validation:MinLength=38, a perfectly valid minimal address likeaaaaab@aaaaab.iam.gserviceaccount.com(37 chars) would match the pattern but still be rejected by the schema. That’s a user‑visible correctness issue.Consider aligning
MinLengthwith the regex for both fields:- // +kubebuilder:validation:MinLength=38 + // +kubebuilder:validation:MinLength=37 @@ - // +kubebuilder:validation:MinLength=38 + // +kubebuilder:validation:MinLength=37This keeps the schema constraints self‑consistent and avoids unnecessarily rejecting valid GSAs.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5554-5604: Enforce unique label keys for resourceLabelsresourceLabels as a plain array allows duplicate keys and last-write-wins ambiguity. Make it a list-map keyed by “key” to ensure uniqueness and clean merge/apply semantics.
Apply this minimal change at the array level:
resourceLabels: items: properties: key: ... value: ... required: - key - value type: object maxItems: 60 type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5445-5495: Enforce unique label keys to avoid ambiguous updatesDuplicates in resourceLabels can cause last-write-wins ambiguity across resources/operators. Add a CEL array-level rule to ensure keys are unique. Also, you set maxItems: 60 (headroom) — confirm this is intentional and mirrored in other CRDs.
Apply this diff near resourceLabels (array level):
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. ... + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster. ... - maxItems: 60 + maxItems: 60 type: arraycmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5842-5892: Enforce unique label keys via list‑map semantics (optional).To prevent duplicate label keys and get stable SSA merge behavior, mark resourceLabels as a map keyed by “key”. Non‑breaking and improves UX.
resourceLabels: @@ - maxItems: 60 - type: array + maxItems: 60 + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map
5869-5873: Reserved prefix message: keep as-is if intentionally stricter than GCP.You’re blocking any “goog*”. If this broader reservation is intentional (to avoid collisions), consider a short doc note in the field description to make it explicit to users.
🧹 Nitpick comments (8)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4815-4865: Enforce unique label keys and SSA-friendly merges for resourceLabels.Make resourceLabels a map keyed by "key" to prevent duplicates and improve server-side apply behavior.
resourceLabels: description: |- @@ items: @@ type: object maxItems: 60 type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (2)
4885-4887: Overly strict immutability blocks safe GSA rotation.Making workloadIdentity entirely immutable prevents rotating GSAs (serviceAccountsRef) during incident response or routine rotation. Keep poolID/projectNumber/providerID immutable, but allow serviceAccountsRef updates (still format-validated).
Adjust validations:
- x-kubernetes-validations: - - message: WorkloadIdentity is immutable - rule: self == oldSelf + x-kubernetes-validations: + - message: WorkloadIdentity identifiers (poolID, projectNumber, providerID) are immutable; serviceAccountsRef may be rotated. + rule: self.poolID == oldSelf.poolID && self.projectNumber == oldSelf.projectNumber && self.providerID == oldSelf.providerIDAnd drop per-field immutability on emails:
- x-kubernetes-validations: - - message: ControlPlane email is immutable - rule: self == oldSelf- x-kubernetes-validations: - - message: NodePool email is immutable - rule: self == oldSelfAlso applies to: 4853-4855, 4873-4875
4735-4738: Narrow reserved-prefix check to 'goog-' to avoid false positives.Current rule blocks any key starting with "goog" (e.g., "goody-..."). GCP reserves the "goog-" prefix; narrow the match accordingly.
- - message: Label keys starting with the reserved 'goog' - prefix are not allowed - rule: '!self.startsWith(''goog'')' + - message: Label keys starting with the reserved 'goog-' prefix are not allowed + rule: '!self.startsWith(''goog-'')'cmd/cluster/gcp/create.go (2)
18-27: New GCP flags and validation: confirm intentional requirement of full WIF configurationThe new flags and RawCreateOptions fields are wired cleanly and Validate enforces that all of them (network, PSC subnet, WIF project number, pool/provider IDs, and both service account emails) are non-empty before proceeding. This makes
hypershift cluster create gcprequire a full Workload Identity configuration plus network details for every new cluster.If the intent is that WIF is always mandatory for GCP-created clusters, this is fine, but it is a behavioral change for the CLI and may break existing scripts that relied on fewer required flags. If WIF is meant to be optional, you’ll likely want to relax some of these
ValidateRequiredOptionchecks and/or gate them behind a feature flag.Also applies to: 30-58, 60-71, 84-113
175-198: ApplyPlatformSpecifics wiring for NetworkConfig and WorkloadIdentity looks correctThe mapping from validated options into
GCPPlatformSpec(NetworkConfigwithNetworkandPrivateServiceConnectSubnet, andWorkloadIdentityincludingServiceAccountsRef) is straightforward and matches the API types described inapi/hypershift/v1beta1/gcp.go. This should round-trip cleanly into the rendered HostedCluster and the YAML fixture.If Workload Identity may evolve (e.g., additional optional fields or different service account roles), consider keeping all WIF-related wiring localized here so future changes don’t leak into other parts of the CLI.
cmd/cluster/gcp/create_test.go (1)
65-75: Extend validation tests to cover all newly required GCP flags
TestValidateGCPOptionsnow covers missingproject,region, andnetwork, plus the all-fields-valid case, butValidatealso requiresPrivateServiceConnectSubnet,WorkloadIdentityProjectNumber,WorkloadIdentityPoolID,WorkloadIdentityProviderID, and both service account emails.Consider adding individual table entries for each of these missing fields so future changes to validation behavior are caught by tests.
Also applies to: 77-101, 105-115
api/hypershift/v1beta1/gcp.go (1)
159-224: Redundant immutability markers could be simplified laterWithin
GCPWorkloadIdentityConfig, each field has both+immutableand an explicitXValidation:rule="self == oldSelf"(andServiceAccountsRefis also immutable at the parent level). Functionally this is fine, but it results in redundant immutability constraints in the generated CRD and slightly more verbose schema.In a follow‑up, you could rely on either the
+immutablemarker or the explicitXValidation(but not both) on these fields to reduce schema noise while preserving behavior.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5497-5625: Add cross-field check: SA emails’ project must match spec.gcp.projectPrevent misconfig by ensuring controlPlaneEmail/nodePoolEmail belong to the same project as spec.platform.gcp.project.
Apply this diff under the spec.platform.gcp object (sibling to “type: object”):
required: - networkConfig - project - region - workloadIdentity type: object + x-kubernetes-validations: + - message: service account emails must use the same project as spec.platform.gcp.project + rule: | + !has(self.workloadIdentity) || !has(self.project) || + ( + self.workloadIdentity.serviceAccountsRef.controlPlaneEmail.split("@")[1].split(".")[0] == self.project && + self.workloadIdentity.serviceAccountsRef.nodePoolEmail.split("@")[1].split(".")[0] == self.project + )If you prefer scoping the rule, we can place an equivalent validation at a higher ancestor for broader context. I can mirror this to the non-TechPreview CRD in a follow-up.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (1)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (11)
api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
cmd/cluster/gcp/create_test.godocs/content/reference/api.mdcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlcmd/cluster/gcp/create.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlapi/hypershift/v1beta1/gcp.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml
🧬 Code graph analysis (3)
cmd/cluster/gcp/create_test.go (2)
support/globalconfig/network.go (1)
NetworkConfig(23-29)cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
cmd/cluster/gcp/create.go (3)
cmd/util/util.go (1)
ValidateRequiredOption(11-16)support/globalconfig/network.go (1)
NetworkConfig(23-29)api/hypershift/v1beta1/gcp.go (4)
GCPNetworkConfig(71-83)GCPResourceReference(6-18)GCPWorkloadIdentityConfig(162-224)GCPServiceAccountsRef(228-268)
api/hypershift/v1beta1/gcp.go (2)
test/e2e/util/external_oidc.go (1)
Key(289-292)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
🔇 Additional comments (26)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4902-4915: Reconsider minLength constraint—Google does not enforce fixed project number length.Google's public docs do not specify a fixed digit length for project numbers, treating them as opaque numeric IDs. While 12-digit numbers are typical in practice, setting
minLength: 6could reject valid project numbers. Keep the originalminLength: 1to avoid unnecessarily rejecting valid identifiers, and usemaxLength: 20-25as headroom. The pattern^[0-9]+$is appropriate.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4889-4893: Verify backward compatibility impact of requiredworkloadIdentityfield in GCP platform specs.The review concern is partially confirmed:
workloadIdentityis marked as required in the featuregated CRD manifest (lines 4889–4893), and the CLI enforces its presence when creating clusters viacmd/cluster/gcp/create.go(lines 99–106). However, the verification was inconclusive on backward compatibility:
- Standard (non-featuregated) CRD manifests do not appear to reference
workloadIdentityin available search results, suggesting this is a new requirement.- The featuregated deployment mechanism could not be located in the codebase, making it unclear whether:
- These manifests are deployed conditionally (only on supported clusters) or universally
- Existing clusters without
workloadIdentityconfig would be rejected or migrated- Controllers gracefully handle the absence of this field
Manually verify:
- How
zz_generated.featuregated-crd-manifests/CRDs are selected and deployed- Whether old HCP/HC instances without
workloadIdentitywould fail validation or create operations- Whether default values or optional handling exists in controllers as a fallback
docs/content/reference/api.md (1)
5038-5049: Condition naming consistency: “ValidGCPWorkloadIdentity” vs PR objective.Docs introduce ValidGCPWorkloadIdentity, while the PR summary mentions ValidWorkloadIdentityConfiguration. Please confirm the intended condition type name and align code, CRD, and docs.
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
42-53: Fixture values correctly aligned with new GCP flags and spec wiringThe updated fixture (
network,privateServiceConnectSubnet, andworkloadIdentityblock including service account emails) matches the new CLI flags and the ApplyPlatformSpecifics mapping, so comparison-based tests should remain stable.cmd/cluster/gcp/create_test.go (2)
25-39: ApplyPlatformSpecifics test thoroughly covers new GCP fieldsThe test now asserts all key fields (
NetworkConfignames,WorkloadIdentityproject number/pool/provider IDs, and both service account emails). This gives good confidence that the GCPPlatformSpec wiring stays correct when the API evolves.Also applies to: 47-59
135-145: CreateCluster CLI test and fixture stay consistent with new required flagsThe minimal CLI args include all new flags, and the rendered manifests are compared against the updated fixture. This is a good end-to-end guard that the flag wiring, ApplyPlatformSpecifics, and YAML structure remain in sync as the API evolves.
Also applies to: 171-176
api/hypershift/v1beta1/gcp.go (5)
7-17: GCPResourceReference name validation and docs look consistent with GCP naming rulesThe updated comments and pattern (
^[a-z]([-a-z0-9]*[a-z0-9])?$with MaxLength=63) correctly enforce “starts with a letter, ends with letter/digit, lowercase/digits/hyphens only” for resource names and align with Compute Engine naming expectations. No issues here.
20-54: GCPResourceLabel key/value validation is appropriately strict and reservesgoogsafelyThe RFC1035-style key/value regexes and the explicit
!self.startsWith('goog')XValidation match the stated constraints and avoid underscores while staying compatible with Compute Engine label rules. Allowing empty values viaMinLength=0+^$|...is also in line with GCP behavior. This struct looks well‑designed.
70-83: Immutability on network and Private Service Connect subnet is a good safety guardMarking both
NetworkandPrivateServiceConnectSubnetas immutable (with explicitself == oldSelfXValidation) is a sensible choice for network topology—changing these after cluster creation would be highly disruptive. The config here is clear and robust.
85-117: Project and region validation tighten inputs without blocking valid GCP valuesThe project ID regex now enforces 6–30 chars, starting with a letter and not ending in
-, which matches GCP requirements. The region pattern (^[a-z]+(-[a-z0-9]+)+[0-9]+$) correctly allows multi‑segment regions likeeurope-west12while rejecting zones (us-central1-a). Overall, this is a solid tightening of validation.
131-156: ResourceLabels cap and WorkloadIdentity immutability fit the API designCapping
resourceLabelsat 60 items to leave headroom under GCP’s 64‑label limit is a pragmatic choice. MakingworkloadIdentityrequired and immutable (plusself == oldSelfXValidation) matches the intent to treat WIF configuration as a “set once at creation” concern and avoids mid‑lifecycle auth breakage, which aligns with the feature’s semantics.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (4)
5480-5496: GCP VPC/subnet naming and immutability: LGTMRegex matches GCP rules and immutability is correctly enforced at the object level.
Also applies to: 5501-5516
5522-5552: Project ID and region validations: LGTM
- Project ID regex enforces 6–30, lowercase/digits/hyphens, start letter, no trailing hyphen.
- Region regex prevents zone suffixes and requires trailing digits (e.g., us-central1).
5711-5720: nodePoolEmail minLength tightened to 38: LGTMMatches the shortest valid service account email length.
5605-5733: No action needed — "gcp-" prefix ban is official and correct.The "gcp-" prefix is reserved by Google for both Workload Identity Pools and Workload Identity Pool Providers, as documented in the official GCP IAM REST API. The validation rules in the YAML correctly prevent users from specifying IDs with this prefix, aligning with actual GCP constraints.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (4)
5372-5388: GCP network/subnet name rules + immutability: LGTMPatterns match GCP naming and immutability is enforced correctly.
Also applies to: 5393-5408
5423-5423: Project/region validation: LGTMProject ID regex and region pattern (disallowing zone suffix) look correct and constrained appropriately; immutability is set.
Also applies to: 5432-5445
5497-5566: WIF poolID/providerID constraints + immutability: LGTMLength, charset, reserved prefix, and immutability rules are appropriate.
5568-5612: Service account email regex: LGTMPattern matches GSA email rules and bounds look reasonable.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (7)
5769-5778: GCP VPC name regex + immutability look correct.Pattern and object-level immutability align with GCE naming (lowercase, hyphen, <=63). LGTM.
Also applies to: 5782-5784
5790-5798: PSC subnet name validation is consistent and safe.Same constraints and immutability applied; looks good.
Also applies to: 5803-5805
5818-5821: Project ID regex matches GCP rules.Length 6–30, starts with letter, no trailing hyphen. Good.
5830-5838: Region pattern covers multi‑segment regions ending with digits.Blocks zones (e.g., “-a”) as intended. LGTM.
5971-6013: GSA email regexes look solid.Anchors to RFC‑style SA ID and project ID segments, domain fixed to .iam.gserviceaccount.com, min/max lengths sensible. LGTM.
5908-5927: Code correctly enforces actual Google Cloud constraint.Google reserves the prefix "gcp-" for use by Google and customer-defined pool/provider IDs must not start with "gcp-". The schema validation is correctly implemented and aligns with the documented WIF/IAM requirement.
6024-6028: Feature-gating correctly implemented—no action required.Verification confirms the gating is working as intended: workloadIdentity is completely absent from the non-gated
hostedclusters-Default.crd.yamlvariant and is marked as required only in the gated variants (hostedclusters-TechPreviewNoUpgrade.crd.yamlandhostedclusters-CustomNoUpgrade.crd.yaml). The lines flagged (6024-6028) inCustomNoUpgrade.crd.yamlcorrectly include workloadIdentity in the required array for that gated variant. No accidental enforcement occurs outside the feature flag.
|
/retest |
1 similar comment
|
/retest |
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (10)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4867-4996: Add CEL guard ensuring GSAs belong to the configured GCP project.Validate that
serviceAccountsRef.controlPlaneandserviceAccountsRef.nodePooldomains match.project + ".iam.gserviceaccount.com". Catches fat‑fingered project IDs early.Apply under
.platform.gcp(or inside.platform.gcp.workloadIdentity) as:+ x-kubernetes-validations: + - message: serviceAccountsRef emails must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || + !has(self.workloadIdentity.serviceAccountsRef) || + ( + let dom = (self.project + ".iam.gserviceaccount.com"); + self.workloadIdentity.serviceAccountsRef.controlPlane.split("@")[1] == dom && + self.workloadIdentity.serviceAccountsRef.nodePool.split("@")[1] == dom + )
5000-5000: RequiredworkloadIdentityunder the GCPPlatform feature gate is OK.Acknowledging prior thread: since this CRD slice is feature‑gated, requiring it won’t block existing clusters.
docs/content/reference/api.md (2)
6289-6330: Clarify IAM: WorkloadIdentityUser vs ServiceAccountUser.
Add a one‑liner to avoid confusion:
- If the CAPG controller impersonates the VM GSA via roles/iam.workloadIdentityUser, roles/iam.serviceAccountUser is not required.
- When using a distinct VM service account, grant roles/iam.serviceAccountUser on that VM SA to the controller GSA to attach it to instances.
Keep roles scoped narrowly and reference your authoritative iam-bindings.json.
6263-6268: Fix broken regex (update source comment, then regenerate).
The “Pattern” shows an HTML anchor, not a regex. Please change the source Go comment (api/hypershift/v1beta1/gcp.go for GCPResourceReference.Name) to wrap the regex in backticks and use the correct expression, then run “make api-docs”.Suggested source comment line:
// Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5842-5893: Enforce unique label keys and clarify reserved prefix wording
- Recommend list-map semantics to prevent duplicate label keys and ensure stable SSA merges.
- The message says GCP reserves 'goog' prefix; if the stricter-than-GCP ban on any 'goog*' is intentional, adjust the text to explicitly say it’s an intentional HyperShift restriction to avoid collisions.
Suggested schema additions:
resourceLabels: maxItems: 60 type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - keyOptionally, update the key doc string to: “We intentionally reserve any key starting with ‘goog’ to avoid collisions with Google-reserved labels.”
6027-6027: workloadIdentity required in gated CRD: acknowledgedRequired here is fine if this manifest is only served under the CustomNoUpgrade feature gate and non-gated CRDs don’t require it. No action if that remains true.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5554-5604: Enforce unique label keys for resourceLabelsDuplicate keys create last-write-wins ambiguity and drift when syncing to GCP. Make the list a keyed map by "key":
resourceLabels: items: properties: key: ... value: ... required: - key - value type: object maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5445-5495: Enforce unique label keys; narrow reserved prefix to 'goog-'.
- Keys aren’t enforced unique; duplicates can lead to last-write-wins ambiguity. Add a CEL array-level rule.
- Reserved-prefix check currently blocks any key starting with "goog", which is broader than the documented "goog-" reservation. Narrowing avoids false rejections.
Apply this diff:
resourceLabels: description: |- @@ - items: + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' + items: @@ key: @@ - x-kubernetes-validations: - - message: Label keys starting with the reserved 'goog' - prefix are not allowed - rule: '!self.startsWith(''goog'')' + x-kubernetes-validations: + - message: Label keys starting with the reserved 'goog-' prefix are not allowed + rule: '!self.startsWith(''goog-'')'api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4707-4757: Resource labels schema looks good.
- RFC1035-style keys/values for Compute Engine.
- Reserved 'goog' prefix blocked.
- Capacity capped at 60 to leave headroom.
No further action from my side given prior decision to keep a plain list.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5785: Prevent duplicate resource label keys (array-level uniqueness)Duplicate keys are still possible; add a CEL validation at the array level to enforce uniqueness without changing list semantics.
Apply:
resourceLabels: description: |- @@ items: ... maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))
🧹 Nitpick comments (4)
api/hypershift/v1beta1/gcp_validation_test.go (1)
9-107: Tests don’t exercise the actual validation logicBoth
TestGCPResourceLabelandTestGCPRegionPatternonly assert thatKey/regionare non-empty, so they will succeed even if the underlying regex/CEL rules onGCPResourceLabeland GCP region fields are misconfigured. This gives very weak signal compared to the e2e/API UX tests that already hit the real CRD validations.Consider either:
- Reworking these tests to actually drive objects through the same validation path the API server uses (or at least validate against the generated schema), or
- Removing this file and relying on the stronger coverage in
test/e2e/v2/tests/api_ux_validation_test.go.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5540-5549: Optional: tighten region regex to allow digits only in the last segmentCurrent pattern permits digits in earlier segments. If you want to model GCP regions more closely, prefer a pattern where only the final segment ends with digits, e.g.:
- ^[a-z]+(?:-[a-z]+)+[0-9]+$
Purely optional; the existing rule is acceptable.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5497-5626: Guard against reusing the same GSA for controlPlane and nodePool.Recommend a CEL check to prevent misconfiguration:
serviceAccountsRef: description: |- @@ type: object + x-kubernetes-validations: + - message: controlPlane and nodePool service accounts must be different + rule: self.controlPlane != self.nodePoolcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5916-5921: Cross-field guard: SA email domain should match project IDAdd a CEL to ensure controlPlane/nodePool GSAs belong to the same project as spec.platform.gcp.project; avoids subtle misconfig.
Apply near the gcp object (after required/type):
required: - networkConfig - project - region - workloadIdentity type: object + x-kubernetes-validations: + - message: serviceAccountsRef emails must match the GCP project ID + rule: has(self.workloadIdentity) && has(self.workloadIdentity.serviceAccountsRef) ? + (self.workloadIdentity.serviceAccountsRef.controlPlane.split('@', 2)[1] == + (self.project + ".iam.gserviceaccount.com") && + self.workloadIdentity.serviceAccountsRef.nodePool.split('@', 2)[1] == + (self.project + ".iam.gserviceaccount.com")) : true
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (22)
api/go.mod(1 hunks)api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)test/e2e/v2/tests/api_ux_validation_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- api/hypershift/v1beta1/hostedcluster_types.go
- client/applyconfiguration/utils.go
- api/hypershift/v1beta1/hostedcluster_conditions.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.goclient/applyconfiguration/hypershift/v1beta1/gcpplatformspec.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.gotest/e2e/v2/tests/api_ux_validation_test.goapi/hypershift/v1beta1/gcp_validation_test.goapi/go.modclient/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.gocmd/cluster/gcp/create.goapi/hypershift/v1beta1/zz_generated.deepcopy.gocmd/cluster/gcp/create_test.gocmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlapi/hypershift/v1beta1/gcp.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamldocs/content/reference/api.mdapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (8)
client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (4)
client/applyconfiguration/hypershift/v1beta1/gcpnetworkconfig.go (1)
GCPNetworkConfigApplyConfiguration(22-25)api/hypershift/v1beta1/gcp.go (1)
GCPEndpointAccessType(58-58)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabelApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfigApplyConfiguration(22-27)
test/e2e/v2/tests/api_ux_validation_test.go (2)
test/e2e/util/crd.go (1)
HasFieldInCRDSchema(15-38)hypershift-operator/controllers/hostedcluster/internal/platform/gcp/gcp.go (1)
GCP(34-34)
api/hypershift/v1beta1/gcp_validation_test.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-54)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
GCPServiceAccountsRefApplyConfiguration(22-25)
cmd/cluster/gcp/create.go (2)
cmd/util/util.go (1)
ValidateRequiredOption(11-16)support/globalconfig/network.go (1)
NetworkConfig(23-29)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(228-268)GCPWorkloadIdentityConfig(162-224)
cmd/cluster/gcp/create_test.go (1)
cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
api/hypershift/v1beta1/gcp.go (2)
test/e2e/util/external_oidc.go (1)
Key(289-292)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
🔇 Additional comments (47)
api/go.mod (1)
10-10: LGTM: Dependency promotion aligns with new validation code.Promoting k8s.io/utils to a direct dependency is appropriate given the PR introduces comprehensive validation rules that likely leverage utilities from this package.
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
1-47: LGTM: Standard auto-generated apply configuration.The generated apply configuration follows Kubernetes patterns correctly with appropriate fluent builders for the GCPResourceLabel type.
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
1-47: LGTM: Standard auto-generated apply configuration.The generated apply configuration follows Kubernetes patterns correctly with appropriate fluent builders for the GCPServiceAccountsRef type.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (4)
4742-4757: Network name regex + immutability look correct.Pattern matches GCP constraints and the field is immutable. LGTM.
4763-4778: PSC subnet name regex + immutability look correct.Matches GCP naming and locks day‑2 changes. LGTM.
4793-4793: Project ID pattern is appropriate.6–30 chars, starts with letter, hyphens allowed (not trailing). LGTM.
4803-4811: Region pattern is reasonable and excludes zones.Requires hyphenated segments and trailing digits (e.g., us-central1). LGTM.
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
42-53: GCP fixture values align with new WIF and network validationsThe network/PSC subnet names, projectNumber, pool/provider IDs, and service account emails all look consistent with the new GCP validation rules and are reasonable choices for the minimal render fixture.
test/e2e/v2/tests/api_ux_validation_test.go (1)
343-672: Comprehensive WIF + GCP label e2e coverage looks goodThe new GCP WIF context cleanly follows existing API UX patterns and exercises the important success and failure paths (projectNumber, reserved pool/provider prefixes, SA email formats, label semantics, and max-count). The struct setup is a bit repetitive but consistent with the rest of the file and acceptable for these scenario tests.
docs/content/reference/api.md (4)
5038-5048: LGTM: new GCP condition types read clearly and match intent.
5954-5959: LGTM: region format guidance is accurate and blocks zones.
Examples and constraints align with GCP regions.
5991-6030: WIF prerequisites are good; keep the “immutable after creation” note.
No changes requested.
6181-6236: LGTM: label rules reflect Compute Engine (RFC1035) constraints and ‘goog’ reserve.
Clear and actionable.cmd/cluster/gcp/create.go (4)
18-28: LGTM - Flag constants follow conventions.The new flag constants are well-named and consistent with the existing codebase patterns.
37-58: LGTM - New fields are well-documented.The new RawCreateOptions fields have clear documentation and appropriate types.
93-113: LGTM - Required validation is appropriate for WIF setup.All new fields are validated as required, which is appropriate since Workload Identity Federation needs complete configuration. Since GCP support is feature-gated, this won't impact existing clusters.
181-198: LGTM - Platform specifics correctly populated.The CLI options are properly mapped to the GCPPlatformSpec fields, including NetworkConfig and WorkloadIdentity configuration.
client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go (1)
27-32: LGTM - Generated apply configuration code is correct.The builder methods for ResourceLabels and WorkloadIdentity follow the standard apply configuration pattern with appropriate nil handling and method chaining.
Also applies to: 73-92
cmd/cluster/gcp/create_test.go (1)
29-59: LGTM - Comprehensive test coverage for new fields.The tests thoroughly validate the new WIF and networking fields, including positive cases, validation of missing required fields, and end-to-end CLI flag rendering.
Also applies to: 65-96, 136-146
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
1-65: LGTM - Generated apply configuration follows standard patterns.The GCPWorkloadIdentityConfig apply configuration correctly implements the builder pattern for all fields with proper method chaining.
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
1488-1495: LGTM - Generated deepcopy code correctly handles new types.The deepcopy implementations properly handle the ResourceLabels slice with per-element copying, and correctly manage the pointer field in GCPResourceLabel.Value.
Also applies to: 1614-1678
api/hypershift/v1beta1/gcp.go (5)
7-17: LGTM - Updated resource name pattern is more precise.The updated pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$correctly enforces GCP resource naming requirements: must start with lowercase letter and end with lowercase letter or digit.
74-82: LGTM - Immutability correctly enforced on network configuration.The Network and PrivateServiceConnectSubnet fields are properly marked as immutable with XValidation rules, preventing changes after cluster creation.
86-157: LGTM - GCPPlatformSpec additions are well-designed.The updated validation patterns for Project and Region are more precise and match GCP requirements. The new ResourceLabels field with MaxItems=60 appropriately reserves space for system labels. The WorkloadIdentity field is correctly marked as required and immutable, which is appropriate for feature-gated WIF support.
159-224: LGTM - GCPWorkloadIdentityConfig validation is comprehensive.The validation rules are thorough:
- ProjectNumber enforces numeric format (up to 25 digits)
- PoolID and ProviderID correctly block the reserved
gcp-prefix- All fields properly marked as immutable
- Patterns enforce GCP naming requirements
226-268: LGTM - Service account email validation is appropriate.The regex pattern correctly validates Google Service Account email format. The MinLength=38 is conservatively set (pattern minimum is 37) which is safe. Immutability markers are appropriate since changing service accounts would break WIF authentication.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (4)
5769-5785: GCP network name regex/immutability: LGTMPattern and immutability match GCP naming rules; no issues.
5791-5805: GCP subnet name regex/immutability: LGTMConsistent with Compute Engine naming and safe to make immutable.
5820-5821: Project ID regex: LGTMMatches documented constraints (start letter, a–z/0–9/-, 6–30 chars, no trailing hyphen).
5830-5837: Region format regex: LGTMEnforces hyphenated segments and numeric suffix (e.g., us-central1); excludes zones as intended.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (5)
5480-5496: LGTM: strict RFC1035-style VPC network name + immutabilityThe regex and immutability guard look correct and align with GCP naming.
5501-5516: LGTM: strict PSC subnet name + immutabilityConsistent with GCP constraints; good to lock the object atomically.
5531-5535: LGTM: project ID regex and immutabilityPattern matches GCP rules (6–30, lowercase, hyphens, no trailing hyphen) and locking is appropriate.
5618-5674: Remove the request for verification—the "gcp-" prefix validation is correct per Google Cloud's official documentation.According to Google Cloud's official IAM documentation and gcloud CLI references, the "gcp-" prefix is explicitly reserved for Workload Identity Pool IDs and Provider IDs. This restriction is documented in the gcloud IAM workload-identity-pools API reference and applies to both pool and provider identifiers. The validation rules in the CRD correctly enforce this constraint and should remain.
5726-5734: workloadIdentity immutability enforced — verify CLI/e2e populate all required fieldsGCP Workload Identity constraints confirm the concern: pool ID, provider ID, and numeric project number are immutable post-creation and must be supplied at cluster creation. The CRD correctly enforces this with the immutability rule
self == oldSelf.However, direct verification of whether CLI, e2e tests, and examples actually populate all required fields (poolID, projectNumber, providerID, and both service account emails) at creation could not be completed due to repository access constraints. Manual code review is recommended to confirm that all HostedCluster creation paths for GCP properly initialize the complete workloadIdentity object to avoid schema validation failures.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (5)
5372-5387: Network name regex + immutability look good.Pattern matches GCP constraints and object immutability is appropriate.
5393-5408: PSC subnet name regex + immutability look good.Consistent with Compute Engine naming and day-2 immutability.
5423-5423: Project ID validation looks correct.Regex and length bounds align with GCP rules.
5432-5444: Region validation is sensible.Pattern allows hyphenated regions ending in digits and rejects zone suffices; immutability OK.
5630-5631: Required WIF field looks correct.Requiring workloadIdentity under GCP is consistent with the new API surface.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (6)
4634-4649: GCP network name regex + immutability look correct.RFC1035-style pattern and object-level immutability are appropriate for VPC names.
4655-4670: PSC subnet name regex + immutability look correct.Consistent with GCP naming constraints and day-2 stability.
4685-4685: Project ID pattern tightened appropriately.6–30 chars, start letter, end alnum, hyphens allowed — matches GCP rules.
4694-4706: Region validation is solid.Pattern excludes zones and enforces trailing digits (e.g., us-central1, europe-west12). Immutability OK.
4759-4887: WIF block generally looks tight.Pool/provider ID rules, reserved-prefix guards, and object immutability are appropriate.
4892-4893: Confirm intent: workloadIdentity is required for all GCP clusters.Making workloadIdentity mandatory is a schema hard-requirement that blocks objects lacking it (and may affect upgrades of existing objects once touched). If that’s intentional for the GCP feature-gated path, all good; otherwise consider making it optional with CEL to validate internals when present.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5808-5855: Good fix on pool/provider IDs and immutabilityLeading-letter regex and 'gcp-' prefix block align with IAM WIF rules; field/object immutability is appropriate.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (9)
docs/content/reference/api.md (1)
6263-6268: Fix invalid regex (HTML anchor rendered as “Pattern”). Regenerate docs from Go comment.Pattern line shows an HTML link instead of a usable regex. Replace with the correct RFC1035‑style regex and wrap it in backticks in the Go source for
GCPResourceReference.Name, then runmake api-docs.Apply in Go comment (not directly in this generated file):
-// Pattern: "^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$" (max 63 chars), per GCP naming requirements. +// Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.This ensures the rendered docs show a copy/paste‑able regex and keep “Must start with a lowercase letter, end with a letter or digit.” intact.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4867-4996: Tie GSA domain to the configured project to catch typos.Add a cross-field CEL guard ensuring serviceAccountsRef.{controlPlane,nodePool} belong to .project.
gcp: type: object properties: ... required: - networkConfig - project - region - workloadIdentity + x-kubernetes-validations: + - message: controlPlane and nodePool GSAs must belong to the specified GCP project + rule: >- + !has(self.workloadIdentity) || !has(self.workloadIdentity.serviceAccountsRef) || + ( + self.workloadIdentity.serviceAccountsRef.controlPlane.split("@")[1] == + (self.project + ".iam.gserviceaccount.com") + && + self.workloadIdentity.serviceAccountsRef.nodePool.split("@")[1] == + (self.project + ".iam.gserviceaccount.com") + )cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5842-5892: Enforce unique label keys with list-map semantics (non-breaking, improves SSA merges).Recommend treating resourceLabels as a map keyed by "key" to reject duplicates and get stable apply behavior.
resourceLabels: maxItems: 60 type: array + x-kubernetes-list-type: map + x-kubernetes-list-map-keys: + - key items: type: object
5870-5873: If broader 'goog' reservation is intentional, clarify in description.Keep the stricter check, but add a note that any key starting with "goog" is intentionally reserved to avoid collisions with Google labels. This avoids user confusion when GCP docs mention "goog-".
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (2)
5738-5739: Required workloadIdentity — ensure all create paths populate itThis is required and immutable. Please confirm CLI/e2e/examples set spec.platform.gcp.workloadIdentity fields at creation to avoid schema failures.
You can quick-check with:
#!/bin/bash # Find GCP create paths that set workloadIdentity in HostedCluster specs rg -nP --type go --type yaml -g '!**/vendor/**' \ 'spec\.platform\.gcp\.workloadIdentity|poolID|providerID|projectNumber|serviceAccountsRef' \ cmd/cluster docs examples test || true
5554-5604: Enforce unique label keys and stable merge semantics for resourceLabelsAllowing duplicates enables last-write-wins ambiguity. Make this a list‑map keyed by “key” to enforce uniqueness and better SSA/merge behavior.
Apply:
resourceLabels: items: properties: key: ... value: ... required: - key - value type: object maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapOptional (belt-and-suspenders) CEL uniqueness check if list-map isn’t feasible now:
+ x-kubernetes-validations: + - message: resourceLabels.keys must be unique + rule: self.map(l, l.key).isUnique()cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5445-5495: Enforce unique label keys; narrow reserved prefix; keep headroom.
- Keys aren’t unique today; duplicates can lead to last-write-wins ambiguity across reconcilers. Add a CEL array-level rule to ensure uniqueness by key while preserving list semantics. Google’s guidance also expects keys to be unique per resource. (docs.cloud.google.com)
- Consider narrowing the reserved rule from any key starting with “goog” to the documented “goog-” system-prefixed family (e.g., goog-dataproc-…), to avoid blocking benign keys like “google-…”. (cloud.google.com)
Apply this focused diff under spec.platform.gcp.resourceLabels:
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. ... + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: "self.all(l, self.exists_one(x, x.key == l.key))" items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster. ... properties: key: ... - x-kubernetes-validations: - - message: Label keys starting with the reserved 'goog' prefix are not allowed - rule: '!self.startsWith(''goog'')' + x-kubernetes-validations: + - message: Label keys starting with the reserved 'goog-' prefix are not allowed + rule: "!self.startsWith('goog-')" ... maxItems: 60 type: arrayWould you like me to mirror the same uniqueness rule in the non-TechPreview CRDs for parity?
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5784: Enforce unique resourceLabels keys (avoid dup key last-write-wins).Duplicate label keys can slip through; enforce uniqueness at the array level with CEL to prevent ambiguous updates.
Apply:
resourceLabels: description: |- @@ maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4708-4757: Clarify duplicate label-key behavior (doc-only).Because resourceLabels remains an array, duplicate keys can be supplied. Consider adding a brief note in the field description stating how duplicates are handled (e.g., “last-wins” on apply) to avoid user surprises.
🧹 Nitpick comments (8)
cmd/cluster/gcp/create_test.go (1)
77-101: Consider adding negative test cases for other required fields.Currently only
missing project,missing region, andmissing networkare tested. For completeness, consider adding test cases for the other required fields (e.g.,WorkloadIdentityProjectNumber,NodePoolServiceAccount). This is optional since the validation logic is uniform.docs/content/reference/api.md (3)
5991-6008: Tighten label quota wording; cross‑reference constraints.Replace “reserves approximately 4 labels” with “reserves up to 4 labels” and add a pointer that keys/values must follow GCPResourceLabel rules to avoid surprises.
- HyperShift reserves approximately 4 labels for system use. + HyperShift reserves up to 4 labels for system use. + See GCPResourceLabel for key/value character and length constraints.
6010-6031: WIF prerequisites: add member principal variants (subject vs principalSet) for clarity.Consider noting both Google IAM member forms commonly used with WIF:
- principal://…/subject/
- principalSet://…/attribute./
This helps users match their provider attribute mapping. No behavior change.
6187-6214: Optional: include copy/paste‑able regex snippets for label key/value.Adding explicit regex (in backticks) alongside the prose improves usability and aligns with other sections that show patterns.
Also applies to: 6225-6232
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4816-4865: Enforce unique label keys to prevent duplicate labels.Add a CEL rule so duplicate keys in spec.platform.gcp.resourceLabels are rejected early.
resourceLabels: ... - maxItems: 60 - type: array + maxItems: 60 + type: array + x-kubernetes-validations: + - message: duplicate label keys are not allowed + rule: self.all(x, self.filter(y, y.key == x.key).size() <= 1)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5970-6013: Add cross-field CEL: ensure GSA emails match spec.gcp.project.Prevent misconfig by asserting both serviceAccountsRef emails are in the same project declared in spec.gcp.project.
gcp: properties: project: ... + x-kubernetes-validations: + - message: controlPlane GSA must belong to the same project as spec.platform.gcp.project + rule: '!has(self.workloadIdentity) || !has(self.workloadIdentity.serviceAccountsRef) || self.workloadIdentity.serviceAccountsRef.controlPlane.split("@", 2)[1] == self.project + ".iam.gserviceaccount.com"' + - message: nodePool GSA must belong to the same project as spec.platform.gcp.project + rule: '!has(self.workloadIdentity) || !has(self.workloadIdentity.serviceAccountsRef) || self.workloadIdentity.serviceAccountsRef.nodePool.split("@", 2)[1] == self.project + ".iam.gserviceaccount.com"'cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (2)
5619-5639: Verify “gcp-” reserved prefix for poolIDThe validation blocks poolID starting with “gcp-”. If this isn’t a documented reservation, this may reject valid pools. Please confirm and, if not reserved, drop the check.
Would you like me to remove the rule or gate it behind a feature flag if unverified?
5655-5674: Verify “gcp-” reserved prefix for providerIDSame concern as poolID. Confirm reservation or remove to avoid false negatives.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (4)
vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (22)
api/go.mod(1 hunks)api/hypershift/v1beta1/gcp.go(4 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)test/e2e/v2/tests/api_ux_validation_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- api/hypershift/v1beta1/hostedcluster_conditions.go
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
- api/hypershift/v1beta1/gcp_validation_test.go
- api/hypershift/v1beta1/hostedcluster_types.go
- cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml
- client/applyconfiguration/utils.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.goclient/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.gocmd/cluster/gcp/create.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.goapi/hypershift/v1beta1/zz_generated.deepcopy.gotest/e2e/v2/tests/api_ux_validation_test.goapi/hypershift/v1beta1/gcp.goapi/go.modapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/cluster/gcp/create_test.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamldocs/content/reference/api.mdapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (5)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
GCPServiceAccountsRefApplyConfiguration(22-25)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsRef(228-268)GCPWorkloadIdentityConfig(162-224)
test/e2e/v2/tests/api_ux_validation_test.go (2)
test/e2e/util/crd.go (1)
HasFieldInCRDSchema(15-38)hypershift-operator/controllers/hostedcluster/internal/platform/gcp/gcp.go (1)
GCP(34-34)
api/hypershift/v1beta1/gcp.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
cmd/cluster/gcp/create_test.go (2)
support/globalconfig/network.go (1)
NetworkConfig(23-29)cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Red Hat Konflux / hypershift-release-mce-211-on-pull-request
- GitHub Check: Red Hat Konflux / hypershift-operator-main-on-pull-request
- GitHub Check: Red Hat Konflux / hypershift-cli-mce-211-on-pull-request
🔇 Additional comments (47)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsref.go (1)
1-47: LGTM!Auto-generated apply configuration follows the standard pattern with proper fluent builder methods.
cmd/cluster/gcp/create.go (3)
18-28: LGTM!New flag constants are well-named and follow the existing naming convention.
93-113: Verify that all new flags should be required.All seven new flags are marked as required, which is a breaking change for existing GCP cluster creation workflows. Please confirm this is intentional — users will now need to provide
--network,--private-service-connect-subnet, and all workload identity flags to create GCP clusters.
175-202: LGTM!The
ApplyPlatformSpecificsfunction correctly maps CLI options to theGCPPlatformSpecstructure, including the nestedNetworkConfigandWorkloadIdentityfields.client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
1-65: LGTM!Auto-generated apply configuration correctly composes with
GCPServiceAccountsRefApplyConfigurationand follows the standard fluent builder pattern.cmd/cluster/gcp/create_test.go (2)
22-60: LGTM!Test coverage for
ApplyPlatformSpecificscomprehensively validates all new fields are correctly mapped to theHostedClusterspec.
130-150: LGTM!Integration test correctly includes all new required CLI flags and validates the complete rendering flow.
test/e2e/v2/tests/api_ux_validation_test.go (2)
343-672: LGTM!Comprehensive E2E validation coverage for GCP Workload Identity Federation, including edge cases for reserved prefixes, format validation, and constraint boundaries.
1952-1964: LGTM!Helper function encapsulates common test pattern cleanly. The dual cleanup (defer + explicit delete) is documented and ensures resource cleanup in all scenarios.
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
20-47: Generated apply configuration for GCPResourceLabel looks correctThe struct shape and fluent builder methods follow the standard applyconfiguration-gen pattern and correctly model the
key/valuefields; no issues from a correctness or maintainability standpoint.docs/content/reference/api.md (4)
5954-5959: I'll help verify that the region validation documentation matches the actual implementation. Let me search for the GCPPlatformSpec region validation logic.
<function_calls>
#!/bin/bashFind GCPPlatformSpec and region validation rules
Search in Go files first
rg -nP -C3 'GCPPlatformSpec' --type go | head -50
Then search for region validation patterns
rg -nP 'region.pattern|x-kubernetes-validations' -g '**/.yaml' | head -50
</function_calls><function_calls>
#!/bin/bashFind CRD and API definition files
fd -e yaml -e yml | grep -i 'crd|openapi' | head -20
</function_calls><function_calls>
#!/bin/bashBroader search for GCPPlatformSpec
rg 'GCPPlatformSpec' -l | head -10
</function_calls>
6316-6324: Based on my web search, I can confirm that the review comment's concern appears valid. Here's why:Key Finding:
roles/iam.serviceAccountUseris specifically for attaching/using a pre-existing service account on resources. It does not grant permissions to:
- Create or manage service accounts
- Mint short-lived credentials
- Impersonate via API or CLI (requires
roles/iam.serviceAccountTokenCreatorinstead)For a control plane operator that "manages control plane infrastructure and resources," the appropriate roles would typically be:
roles/iam.serviceAccountAdmin(if it must create/manage service accounts)roles/iam.serviceAccountTokenCreator(if it must mint tokens for workloads)roles/storage.admin✓ (correctly listed; for bucket management)However, I cannot access the repository to verify the actual
cmd/infra/gcp/iam-bindings.jsonfile due to clone errors. The documentation should be cross-checked against that authoritative source to confirm whetherroles/iam.serviceAccountUseris indeed listed or if a different role is actually required.**Validate controlPlane GSA roles in
cmd/infra/gcp/iam-bindings.json— confirm whetherroles/iam.serviceAccountUseror a different service account management role (e.g.,roles/iam.serviceAccountAdminorroles/iam.serviceAccountTokenCreator) is actually defined for the controlPlane operator. If the binding uses a different role, update the documentation to match.
6289-6307: Based on my research, I can now verify the review comment concerns. The web search results confirm that:
- roles/iam.serviceAccountUser is indeed missing from the documented IAM roles for the nodePool GSA
- This role is critical for scenarios where the controller GSA needs to attach/bind a different service account to VM resources
- The distinction between when this role is needed (different SAs) vs. not needed (same SA via WIF) is valid and important for least-privilege security
However, I cannot fully verify the exact contents of
cmd/infra/gcp/iam-bindings.jsondue to repository access limitations. The review comment's concerns are substantive and the documentation appears incomplete.
Document missing roles/iam.serviceAccountUser for nodePool GSA and clarify least-privilege requirements.
The nodePool GSA documentation omits
roles/iam.serviceAccountUser, which is required when the controller GSA needs to attach a different service account to VM resources. Add:
roles/iam.serviceAccountUseris required only if the VM-attached SA differs from the controller's GSA (WIF impersonation scenario); not needed when using the same GSA via WIF.Verify that the documented role list (
roles/compute.instanceAdmin.v1,roles/compute.networkAdmin) matches the complete set incmd/infra/gcp/iam-bindings.jsonand includes any additional roles such as storage, logging, or monitoring roles required for CAPG.
5038-5049: Yes, please search the HyperShift GitHub repo and API docs for the exact HostedCluster/HostedControlPlane status condition type names, specifically looking for:
- ValidGCPCredentials
- ValidGCPWorkloadIdentity
- ValidConfiguration
I need to verify these exact names match the Go constant definitions.
api/hypershift/v1beta1/zz_generated.deepcopy.go (5)
1488-1495: LGTM! Proper deep copy implementation for GCPPlatformSpec.The generated code correctly handles:
- ResourceLabels slice: nil-checked, properly allocated, and per-element deep copied
- WorkloadIdentity: shallow copy is appropriate since GCPWorkloadIdentityConfig contains only value types (strings)
1614-1622: LGTM! Correct deep copy for pointer field.The Value field (a pointer to string) is properly deep copied with nil check, allocation, and value copy. This follows the standard deep copy pattern.
1649-1652: LGTM! Shallow copy is correct for value-type struct.GCPServiceAccountsRef contains only string fields (NodePool, ControlPlane), so the shallow copy via
*out = *inis correct and efficient.
1664-1668: LGTM! Shallow copy is correct for value-type struct.GCPWorkloadIdentityConfig and its nested ServiceAccountsRef contain only string fields, so shallow copy is correct and efficient.
3441-3441: LGTM! Ensures proper deep copy of nested GCP structures.Calling
(*in).DeepCopyInto(*out)ensures that GCPPlatformSpec and all its nested structures (including the ResourceLabels slice and WorkloadIdentity) are properly deep copied. This is consistent with how other platform specs are handled.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (4)
4742-4757: LGTM: GCP VPC/subnet name rules and immutability are correct.Regex matches RFC1035-style names; immutability guards look right.
Also applies to: 4763-4778
4793-4797: LGTM: Project ID pattern/immutability.6–30 chars, starts with letter, no trailing hyphen — good.
4802-4814: LGTM: Region format validation.Pattern enforces hyphenated segments and numeric suffix (e.g., us-central1).
4897-4900: LGTM: Reserved 'gcp-' prefix blocked for WIF pool/provider IDs.Matches Google’s reservation; immutability is appropriate.
Also applies to: 4932-4936
api/hypershift/v1beta1/gcp.go (6)
7-17: LGTM! Clean pattern update with excellent documentation.The updated regex pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$is more concise than the previous version while maintaining the same GCP naming enforcement (start with letter, end with letter/digit, hyphens allowed in middle). The comprehensive documentation with GCP references is helpful.
20-54: LGTM! Thorough RFC1035 validation with reserved prefix protection.The GCPResourceLabel implementation is solid:
- Key validation correctly enforces RFC1035 rules and blocks the reserved 'goog' prefix via CEL validation
- Value pattern
^$|^[0-9a-z]([0-9a-z-]{0,61}[0-9a-z])?$explicitly allows empty strings as per GCP requirements- Documentation clearly distinguishes Compute Engine constraints from other GCP services
- Pointer type for Value appropriately handles the nil vs empty string distinction
74-82: LGTM! Proper immutability constraints for network config.The CEL validations correctly enforce immutability on network infrastructure fields, preventing accidental changes that could break cluster connectivity.
98-98: LGTM! Strengthened validation patterns and well-designed API surface.The updates to GCPPlatformSpec are excellent:
- Project pattern now strictly enforces the 6-30 character constraint inline with the regex
- Region pattern correctly validates region format and rejects zone suffixes (e.g., "us-central1-a")
- ResourceLabels with MaxItems=60 appropriately reserves headroom within GCP's 64-label limit
- WorkloadIdentity field design is sound with comprehensive prerequisites documentation
Also applies to: 115-116, 131-139, 141-157
159-224: LGTM! Comprehensive WIF configuration with proper validation.The GCPWorkloadIdentityConfig implementation is excellent:
- ProjectNumber validation correctly handles GCP numeric project identifiers
- PoolID and ProviderID patterns enforce GCP naming rules (4-32 chars, start with letter, no trailing hyphens)
- CEL validations appropriately block the reserved 'gcp-' prefix on both identifiers
- Immutability constraints prevent breaking the authentication chain post-creation
- Documentation provides clear guidance on prerequisites and where to obtain values
226-268: LGTM! Robust service account validation with excellent IAM documentation.The GCPServiceAccountsRef implementation is solid:
- Pattern correctly validates the full GSA email format including domain
- MinLength=38 is appropriately conservative (actual pattern minimum is 37, but being 1 char off is safe)
- Immutability prevents breaking WIF bindings
- Documentation of required IAM roles with reference to authoritative source (iam-bindings.json) is excellent
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (3)
5769-5785: GCP name regexes and immutability look solid.Patterns match GCE naming rules and immutability guards are correct. No action needed.
Also applies to: 5791-5805
5907-5928: The "gcp-" prefix constraint is correctly enforced per official Google Cloud documentation.GCP officially reserves the "gcp-" prefix for Workload Identity Federation pool and provider IDs and prohibits its use. This is documented in the gcloud IAM workload-identity-pools CLI documentation and Workload Identity Federation configuration pages. The validation constraint
!self.startsWith('gcp-')accurately enforces this GCP requirement and should remain in place.
6011-6022: Based on my investigation, I've reached the limits of what can be verified without direct repository access. Here's what I've learned:Verified Context:
- GCP Workload Identity Federation is supported in Red Hat's OpenShift/HyperShift implementation (not upstream)
- It uses external account credentials and OIDC token exchange
- The immutability constraint makes sense for security (prevents unintended credential changes)
Unverifiable (repo access required):
- Whether
workloadIdentityis required only in the CustomNoUpgrade CRD variant- Whether standard (non-CustomNoUpgrade) hostedclusters CRD files also include this requirement
The review comment's core request—to verify that workloadIdentity gating is scoped to CustomNoUpgrade and not present in standard CRDs—cannot be confirmed due to infrastructure constraints preventing repository access.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (6)
5480-5496: LGTM: GCP network name regex + immutabilityNaming rules and immutability guard look correct and aligned with GCP.
5501-5516: LGTM: PSC subnet name regex + immutabilityConsistent with network name rules; immutability guard is appropriate.
5522-5535: LGTM: GCP project ID validationPattern/length and immutability look good.
5540-5552: LGTM: GCP region validationPattern enforces region (not zone) and immutability; looks correct.
5694-5701: LGTM: service account email regex/min lengthRegex and minLength=38 match the shortest valid GSA email; immutability guard is fine.
5714-5721: LGTM: nodePool service account email validationConsistent with controlPlane; looks good.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (5)
5372-5381: GCP network and subnet name validations look correct and immutable.Regex and immutability for VPC network name align with GCP limits. Same pattern is reused elsewhere; good consistency.
Also applies to: 5385-5387
5393-5402: PSC subnet name validation/immutability LGTM.Matches Compute Engine naming rules; immutability guard is appropriate.
Also applies to: 5406-5408
5414-5427: Project ID regex matches GCP rules.6–30 chars, starts with a letter, hyphens allowed, no trailing hyphen. Immutability is appropriate.
5432-5444: Region pattern excludes zones and enforces digit suffix — good.Pattern requires at least one hyphen and trailing digits (e.g., us-central1), which blocks zone forms like us-central1-a. Immutability is correct.
5497-5625: WIF IDs: ‘gcp-’ prefix block and immutability are correct.
- Google reserves the gcp- prefix for pool/provider IDs; your validations enforce that and immutability prevents drift. (pulumi.com)
- GSA email regex is appropriately constrained to valid account/project IDs and domain.
Two confirmations:
- Making spec.platform.gcp.workloadIdentity required (line 5630 context) is intentional for all new GCP clusters? Any upgrade/defaulting concerns?
- Label character policy here is stricter than generic GCP label rules (which allow underscores). If that’s a deliberate “Compute Engine/RFC1035-only” stance, please confirm tests cover services that might attach labels outside Compute (to avoid unexpected rejections). (docs.cloud.google.com)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (4)
4634-4650: LGTM: GCP network name rules and immutability.Pattern and immutability read well and match GCP constraints.
4655-4670: LGTM: PSC subnet name rules and immutability.Consistent with GCP naming and day‑2 safety.
4685-4685: LGTM: Project ID regex tightened.Enforces 6–30 chars, start alpha, end alnum, hyphens allowed; matches GCP rules.
4694-4703: LGTM: Region format regex.Hyphenated segments ending with digits; blocks zone suffixes; good.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (10)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (2)
4708-4756: Labels schema is good; consider clarifying duplicate-key behavior (or block duplicates).Current array allows duplicate keys; controllers typically end up last-wins. If list-map is out (per earlier thread), add either:
- Option A (docs-only): Append to description that duplicate keys are rejected/undefined and last-wins may occur.
- Option B (CEL): Enforce uniqueness without changing list type.
Example patch for Option B (under resourceLabels):
resourceLabels: ... maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self.map(x, x.key).all(k, self.map(y, y.key).exists_one(kk, kk == k))
4758-4886: WIF schema/validation LGTM; thanks for fixing GSA minLength and locking fields.
- Strong per-field patterns and immutability.
- GSA email minLength set to 37 resolves the earlier off‑by‑one.
docs/content/reference/api.md (1)
6264-6268: Replace broken regex (HTML anchor rendered into pattern).The “Pattern” line isn’t a valid regex and renders an HTML anchor. Use a copy/paste‑able regex and keep the 63‑char note.
-Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. +Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Also keep the surrounding prose: “Must start with a lowercase letter and end with a letter or digit.”
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5842-5891: Enforce unique label keys via list‑map semantics.Prevents accidental duplicate keys and improves SSA merge behavior. Non‑breaking at API surface.
resourceLabels: maxItems: 60 type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map items: type: object
5928-5941: Tighten projectNumber length to 19 digits (int64 upper bound).25 allows invalid lengths; 19 matches numeric GCP project numbers.
- maxLength: 25 + maxLength: 19cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (3)
5604-5733: Required+immutable workloadIdentity — verify create paths are wiredThese fields are required and immutable. Ensure CLI/e2e/examples populate poolID, projectNumber, providerID, and both service account emails at creation; otherwise CRD validation will block cluster creation.
If gaps remain, wire infra output into HostedCluster spec population or add flags to accept user values. Based on earlier repo sweep, ...
5554-5603: Enforce unique label keys for resourceLabelsPrevent duplicate keys by declaring list‑map semantics keyed by "key".
Apply:
resourceLabels: items: properties: key: ... value: ... required: - key - type: object + type: object maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapThis avoids last‑write‑wins ambiguity and improves merge/apply behavior. Based on previous feedback, ...
5694-5696: Minimum length for GSA emails should be 38, not 37Shortest valid is 6 (name) + 1 (@) + 6 (project) + 25 (suffix) = 38. Bump for both fields.
- minLength: 37 + minLength: 38Do this in serviceAccountsEmails.controlPlane and serviceAccountsEmails.nodePool.
Also applies to: 5714-5716
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5446-5494: Enforce unique label keys at array level (keep list semantics).Keys can repeat across items today. Add a CEL array-level rule to ensure uniqueness by key while preserving order and avoiding list-map semantics.
Apply this diff under gcp.resourceLabels:
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster. ... maxItems: 60 type: arraycmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5783: Enforce unique label keys in resourceLabels (avoid duplicate keys).Duplicate keys are currently allowed, causing ambiguous last-write-wins behavior and potential API update failures. Add an array-level CEL to enforce key uniqueness. You can keep maxItems at 60 (headroom) or switch to 64 per team preference—either way, ensure uniqueness.
Apply under spec.platform.gcp.resourceLabels:
resourceLabels: description: |- @@ maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key)) items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster.Optional: mirror this with a kubebuilder XValidation tag on the Go field to keep generators in sync. Based on prior discussion, avoiding list-map semantics while using CEL meets the goal.
🧹 Nitpick comments (4)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4956-4957: Correct minLength for GSA email fields (off by one).Minimum valid length is 38 chars (6 local + 1 @ + 6 project + 25 suffix). Current
minLength: 37is inconsistent.- minLength: 37 + minLength: 38 ... - minLength: 37 + minLength: 38Also applies to: 4976-4977
docs/content/reference/api.md (1)
6298-6324: Add conditional note for Service Account User role when VM SA differs.When the VM’s attached GSA differs from the controller’s GSA, the controller needs iam.serviceAccounts.actAs (typically via roles/iam.serviceAccountUser) on that VM GSA to attach it to instances. Add a one‑liner to prevent misconfig.
This GSA requires the following IAM roles: - roles/compute.instanceAdmin.v1 (Compute Instance Admin v1) - roles/compute.networkAdmin (Compute Network Admin) +Note: If the VM’s service account is distinct from this controller GSA, also grant +`roles/iam.serviceAccountUser` on that VM service account to this controller GSA so it +can attach the SA to instances.Ensure this matches your authoritative bindings (cmd/infra/gcp/iam-bindings.json).
cmd/cluster/gcp/create.go (1)
93-113: Consider adding client-side validation for complex field patterns.The current validation only checks for non-empty values, which is consistent with the existing pattern for
ProjectandRegion. However, the new fields have complex API-level validation rules (regex patterns, length constraints, and reserved prefix checks), and all fields are immutable once the cluster is created.Without client-side validation, users will discover validation errors only after attempting cluster creation, and fixing them requires deleting and recreating the entire cluster. Consider adding pattern validation here to provide immediate feedback, especially for:
WorkloadIdentityPoolIDandWorkloadIdentityProviderID(cannot start with 'gcp-', must match^[a-z]([a-z0-9-]{2,30}[a-z0-9])$)- Service account emails (must match email format pattern)
WorkloadIdentityProjectNumber(must be numeric)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5730-5732: Reduce immutability duplication (optional)Top‑level “WorkloadIdentity is immutable” plus per‑field immutability is redundant and can double error noise. Keep either the top‑level or the per‑field rules.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (12)
api/go.sumis excluded by!**/*.sumapi/vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/lru/lru.gois excluded by!**/vendor/**api/vendor/modules.txtis excluded by!**/vendor/**go.sumis excluded by!**/*.sumvendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/lru/lru.gois excluded by!vendor/**,!**/vendor/**vendor/modules.txtis excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (16)
api/go.mod(2 hunks)api/hypershift/v1beta1/gcp.go(3 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)go.mod(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
cmd/cluster/gcp/create.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/cluster/gcp/create_test.goapi/go.modgo.modclient/applyconfiguration/utils.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.goapi/hypershift/v1beta1/zz_generated.deepcopy.godocs/content/reference/api.mdapi/hypershift/v1beta1/gcp.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (5)
cmd/cluster/gcp/create.go (1)
api/hypershift/v1beta1/gcp.go (4)
GCPNetworkConfig(71-83)GCPResourceReference(6-18)GCPWorkloadIdentityConfig(164-226)GCPServiceAccountsEmails(230-270)
cmd/cluster/gcp/create_test.go (3)
hypershift-operator/controllers/hostedcluster/internal/platform/gcp/gcp.go (1)
GCP(34-34)support/globalconfig/network.go (1)
NetworkConfig(23-29)cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
client/applyconfiguration/utils.go (3)
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabelApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmailsApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfigApplyConfiguration(22-27)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPServiceAccountsEmails(230-270)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-54)GCPServiceAccountsEmails(230-270)GCPWorkloadIdentityConfig(164-226)
🔇 Additional comments (43)
go.mod (1)
295-297: Replace pin fork8s.io/utilslooks appropriate; just confirm no newer-API usageAligning
k8s.io/utilsto the Kubernetes v1.32.3 pseudo‑version viareplaceis a reasonable compatibility move and the inline comment is clear. Please just ensure there are no call sites relying on symbols added in the laterv0.0.0-20250321185631-1f6e0b77f77eversion so this pin doesn’t introduce subtle compile/runtime regressions if other deps were updated earlier.client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
20-47: GCPServiceAccountsEmails applyconfiguration is consistent and correctThe generated applyconfiguration type and its builder methods follow the usual pattern (pointer fields, chainable setters) and correctly mirror the underlying
GCPServiceAccountsEmailsshape. No issues from a correctness or maintainability standpoint.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (5)
4634-4650: Network name validation + immutability look solid.Pattern matches GCP VPC naming and the field is immutable. LGTM.
4655-4670: PSC subnet name validation + immutability are correct.Matches GCP resource naming; immutability guard is appropriate.
4685-4689: Project ID regex matches GCP rules.6–30 chars, starts with letter, no trailing hyphen; immutability enforced. LGTM.
4694-4706: Region format tightened appropriately.Requires at least one hyphen and digit-suffixed region; zones like “us-central1-a” are excluded; immutability enforced. LGTM.
4894-4900: Good cross-field project consistency checks.CEL ensures both GSAs belong to spec.platform.gcp.project. This prevents runtime misconfig. LGTM.
api/go.mod (1)
10-10: LGTM! Dependency pinning correctly implemented.The direct requirement for
k8s.io/utilscombined with the replace directive properly pins the module to the version required by Kubernetes v1.32.3 (v0.0.0-20241104100929-3ea5e8cea738). This approach ensures compatibility with your k8s.io/api v0.32.3 and k8s.io/apimachinery v0.32.3 dependencies while following the agreed-upon solution from the previous review discussion.Also applies to: 91-92
client/applyconfiguration/utils.go (1)
160-167: LGTM! New GCP WIF types properly integrated.The three new apply configuration cases for GCP Workload Identity Federation types (
GCPResourceLabel,GCPServiceAccountsEmails,GCPWorkloadIdentityConfig) are correctly integrated into the factory function. They follow the established pattern, maintain alphabetical ordering within the GCP section, and match the type definitions shown in the relevant code snippets.cmd/cluster/gcp/create.go (4)
18-28: LGTM!Flag constants are well-named and follow the existing kebab-case convention for CLI flags.
38-57: LGTM!The new fields are well-documented and appropriately typed for capturing CLI input.
64-70: LGTM!Flag bindings are correct, and the help text provides useful context about obtaining values from the
hypershift infra create gcpcommand output.
176-202: LGTM!All new GCP configuration fields are correctly mapped from CLI options to the API types. The structure matches the expected
GCPNetworkConfigandGCPWorkloadIdentityConfigtypes with all required fields populated.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (6)
5769-5785: LGTM: network name rules and immutability are correct for GCP.
5791-5805: LGTM: PSC subnet name rules and immutability look good.
5820-5821: LGTM: project ID pattern matches documented constraints (6–30, starts with letter, hyphen allowed, no trailing hyphen).
5830-5838: LGTM: region pattern excludes zones and requires trailing digits; sensible validation.
6019-6021: LGTM: WorkloadIdentity immutability is explicit and appropriate while gated.
6029-6036: LGTM: cross-field check ensures GSAs belong to specified project.api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
1485-1496: LGTM! Auto-generated deepcopy methods are correct.The generated deepcopy code correctly handles:
- Slice deep-copy for
ResourceLabelswith per-elementDeepCopyIntocalls- Pointer field handling for
GCPResourceLabel.Value *string- Value copying for structs without pointer fields
Also applies to: 1614-1678
cmd/cluster/gcp/create_test.go (1)
22-178: LGTM! Test coverage properly validates new GCP fields.The tests correctly:
- Verify
ApplyPlatformSpecificswiring for new network, WIF, and service account fields- Add validation test cases for missing required fields (including new
networkfield)- Include new CLI flags in the rendering test
api/hypershift/v1beta1/gcp.go (5)
6-18: Improved pattern for GCPResourceReference.The updated pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$is more concise than the previous version and explicitly prevents names ending with hyphens, which aligns better with GCP naming requirements.
20-54: GCPResourceLabel implementation is consistent and well-documented.The field markers are now consistent:
Key: required string with RFC1035 pattern and reserved prefix validationValue: optional*stringwithomitempty, allowing empty strings per GCP APIThe MaxItems=60 for ResourceLabels correctly reserves ~4 labels for system use out of GCP's 64-label limit.
Also applies to: 133-141
100-100: Validation patterns for Project and Region are correct.Both patterns align with GCP requirements:
- Project pattern (
^[a-z]([a-z0-9-]{4,28}[a-z0-9])$): Correctly enforces 6-30 character length (1 start + 4-28 middle + 1 end)- Region pattern (
^[a-z]+(-[a-z0-9]+)+[0-9]+$): Uses regex backtracking to ensure trailing digits aren't consumed by the middle section, correctly matching regions likeus-central1while rejecting zone suffixes likeus-central1-aAlso applies to: 117-117
245-248: Service account email validation correctly aligned with pattern.The
MinLength=37on lines 246 and 266 correctly matches the minimum length enforced by the pattern:
- Service account name: 6 chars minimum
@separator: 1 char- Project ID: 6 chars minimum
.iam.gserviceaccount.com: 24 chars- Total: 37 chars minimum ✓
This addresses the previous review concern.
Also applies to: 265-268
143-226: Comprehensive WIF configuration with proper immutability.The
GCPWorkloadIdentityConfigtype includes:
- Clear documentation of WIF prerequisites and setup requirements
- Proper validation patterns (numeric ProjectNumber, RFC1035-style PoolID/ProviderID)
- Reserved prefix validation (
!self.startsWith('gcp-'))- Immutability enforcement at the field level
The design is well-structured for keyless authentication.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (5)
5480-5489: GCP network name validation + immutability look solidPattern and immutability rule match GCP naming guidance. No changes needed.
Also applies to: 5493-5496
5501-5511: PSC subnet name validation + immutability look solidPattern and immutability rule are correct and consistent.
Also applies to: 5514-5516
5523-5535: Project ID rules are consistentLength, charset, and pattern align; end‑char constraint prevents trailing hyphen. Good as‑is.
5540-5552: Region pattern is correctForces at least one hyphen and trailing digits; excludes zone suffixes. Looks good.
5634-5637: Constraint is correctly documented and should be retainedThe "gcp-" prefix restriction for pool and provider IDs is a documented GCP requirement. Per Google Cloud IAM documentation, the prefix "gcp-" is reserved and cannot be used for Workload Identity Federation pool or provider IDs. This validation rule correctly enforces GCP's API constraints and should not be removed.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (6)
5372-5387: GCP network name + immutability: LGTMPattern and immutability rule align with GCP RFC1035-style naming and day-2 stability.
5393-5408: GCP PSC subnet name + immutability: LGTMConsistent with Compute Engine naming and immutable infra wiring.
5414-5427: Project ID pattern + immutability: LGTMConstraints match GCP project-id rules (6–30, lowercase/digits/hyphen, leading letter, no trailing hyphen).
5432-5445: Region validation: LGTMRegex enforces hyphenated region names ending with digits and excludes zones (e.g., “-a”). Immutability is appropriate.
5567-5615: Service Account email regex + same-project rules: LGTMEmail patterns are tight and cross-field checks ensure both GSAs belong to the declared project. Good hardening.
Also applies to: 5632-5638
5518-5530: The 'gcp-' prefix restriction is officially reserved by Google Cloud and the validation rule is correct—retain it.According to Google Cloud's official Workload Identity documentation, the "gcp-" prefix is explicitly reserved for pool IDs and may not be used. This validation rule correctly implements Google's official constraint. The other constraints (4–32 characters, pattern
[a-z0-9-], start/end with alphanumeric, immutability) are also accurate per GCP specifications. The rule should remain unchanged.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (6)
5661-5670: LGTM — GCP network name pattern and immutability are correct.Pattern matches GCP rules; object immutability via self == oldSelf is consistent.
Also applies to: 5674-5676
5682-5691: LGTM — PSC subnet name pattern and immutability are correct.Matches GCP subnet naming and freezes day‑2 changes as intended.
Also applies to: 5695-5697
5703-5716: LGTM — Project ID regex.Length, charset, start/end constraints align with GCP requirements.
5718-5733: LGTM — Region format tightening.Pattern excludes zones and enforces trailing digits; immutability is appropriate.
5785-5914: LGTM — WIF pool/provider IDs, reserved prefixes, and immutability.
- Start-with-letter enforced.
- Reserved “gcp-” blocked.
- Field immutability guarded.
5921-5927: LGTM — Bind SA emails to the configured project.CEL rules correctly guard cross-field consistency for controlPlane/nodePool GSAs.
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (7)
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5918-5936: projectNumber max length too permissive; cap at 19 digits.GCP project numbers are int64; 19 digits max suffices. Tighten to reduce accidental invalid inputs.
- maxLength: 25 + maxLength: 19cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5781: Enforce unique label keys at array level to prevent duplicatesCurrently duplicates are possible; add a CEL
x-kubernetes-validationson the array so keys are unique. KeepmaxItems: 60headroom.resourceLabels: description: |- @@ maxItems: 60 type: array + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))docs/content/reference/api.md (1)
6262-6268: Fix broken regex/pattern for GCP resource names (doc bug).The “Pattern” contains an HTML anchor, not a regex. Replace with a valid, copy/paste‑able pattern and keep the 63‑char constraint. Also ensure the prose states “Must start with a lowercase letter, end with a letter or digit.”
Apply this doc change:
-Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. +Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Tip: wrap the regex in backticks in the Go comment for GCPResourceReference.Name and re‑generate the docs (make api-docs) to avoid Markdown auto-linking.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (3)
5554-5601: Enforce uniqueness of resourceLabels by key (use list‑map).The array permits duplicate label keys; this causes last‑write‑wins ambiguity and poor merge semantics. Make it a list‑map keyed by "key".
Apply at the resourceLabels level:
resourceLabels: items: properties: key: ... value: ... required: - key type: object maxItems: 60 - type: array + type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: map
5708-5714: GSA email minLength off by 1 (nodePool).Same as above; increase to 38 for accuracy.
- minLength: 37 + minLength: 38
5688-5694: GSA email minLength off by 1 (controlPlane).Shortest valid address is 6 + 1 + 6 + 25 = 38 chars. Bump minLength to 38.
- minLength: 37 + minLength: 38cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5446-5493: Enforce unique resourceLabels keys via CEL (no list-map semantics).Duplicate keys can cause ambiguous merges. Add an array-level CEL rule to guarantee uniqueness while preserving list semantics.
Apply:
resourceLabels: description: |- resourceLabels are applied to all GCP resources created for the cluster. ... + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: 'self.all(l, self.exists_one(x, x.key == l.key))' items: description: |- GCPResourceLabel is a label to apply to GCP resources created for the cluster.(Based on prior discussion; keeps list semantics while preventing duplicates.)
🧹 Nitpick comments (11)
api/go.mod (1)
10-10: Align the direct require version with the replace directive for clarity.The direct require on Line 10 specifies
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e(March 2025), but the replace directive on Line 92 pins it tov0.0.0-20241104100929-3ea5e8cea738(November 2024, matching Kubernetes 1.32.3). While the replace directive ensures the correct version is used, having a different version in the require block can confuse developers about which version is actually in effect.Consider updating Line 10 to use the same pseudo-version as the replace directive:
- k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738api/hypershift/v1beta1/gcp_validation_test.go (2)
9-65: Consider adding validation assertions to strengthen test coverage.While the test documents valid
GCPResourceLabelexamples, it only checks thatKeyis non-empty (Line 60-62). The test doesn't verify the actual validation rules enforced by the CRD markers:
- Key pattern:
^[a-z][a-z0-9_-]{0,62}$- Reserved prefix check: keys starting with
googshould be rejected- Value pattern:
^$|^[a-z0-9_][a-z0-9_-]{0,62}$Consider adding negative test cases and assertions that actually validate the patterns, or add integration tests that verify the CRD validation rules reject invalid inputs.
67-107: Consider adding pattern validation to region tests.Similar to
TestGCPResourceLabel, this test only verifies that region strings are non-empty (Line 102-104) without actually validating the expected region format pattern. Consider adding assertions that verify the region format matches GCP's region naming conventions or add negative test cases for invalid region formats.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5842-5890: Enforce unique label keys; clarify underscore policy.
- Recommend map semantics to prevent duplicate label keys and improve SSA merges.
- The descriptions allow underscores; if the intent is RFC1035 (no underscores) for Compute Engine, tighten the patterns or update text to avoid confusion.
Apply uniqueness with list-map:
resourceLabels: @@ maxItems: 60 type: array + x-kubernetes-list-map-keys: + - key + x-kubernetes-list-type: mapIf RFC1035-only keys/values are intended, consider:
- pattern: ^[a-z][a-z0-9_-]{0,62}$ + pattern: ^[a-z]([a-z0-9-]{0,62})$ # no underscoresOtherwise, keep current patterns and adjust docs to state underscores are allowed on GCE.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5674-5677: Prefer field‑level immutability over object‑level for networkUse immutability on properties (e.g., name) instead of
self == oldSelfon the whole object to avoid freezing future optional fields.- x-kubernetes-validations: - - message: Network is immutable - rule: self == oldSelf + # Keep the object extensible; enforce immutability on fields under properties.name + # (name already has pattern/max/min; add:) + properties: + name: + x-kubernetes-validations: + - message: network name is immutable + rule: self == oldSelf
5695-5697: Same for privateServiceConnectSubnet: scope immutability to fieldsAvoid
self == oldSelfat object level; pin immutability toproperties.nameso new optional fields can be added later without breaking updates.- x-kubernetes-validations: - - message: Private Service Connect subnet is immutable - rule: self == oldSelf + properties: + name: + x-kubernetes-validations: + - message: Private Service Connect subnet name is immutable + rule: self == oldSelftest/e2e/v2/tests/api_ux_validation_test.go (2)
1952-1964: Double deletion is redundant but harmless.The explicit
client.Deletecall on line 1962 after creation is redundant with the deferred cleanup on lines 1954-1956. While this doesn't cause functional issues (delete is idempotent), it adds unnecessary API calls.Consider removing the explicit delete since defer already handles cleanup:
func testHostedClusterCreation(ctx context.Context, client crclient.Client, file string, mutate func(*hyperv1.HostedCluster)) error { hostedCluster := assets.ShouldHostedCluster(content.ReadFile, fmt.Sprintf("assets/%s", file)) defer func() { _ = client.Delete(ctx, hostedCluster) }() mutate(hostedCluster) - err := client.Create(ctx, hostedCluster) - // Explicitly delete the resource after creation attempt, in addition to defer - // This matches the original test behavior and ensures cleanup even if creation fails - _ = client.Delete(ctx, hostedCluster) - return err + return client.Create(ctx, hostedCluster) }
1969-1980: Same redundant deletion pattern in testNodePoolCreation.Same observation as the HostedCluster helper - the explicit delete is redundant with defer.
docs/content/reference/api.md (1)
5954-5959: Region format text is accurate; consider adding a regex for copy/paste.Optional: add a pattern like
^[a-z]+(?:-[a-z0-9]+)*[0-9]$to help users validate inputs locally. Keep the examples as-is.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5547-5549: Region: drop minLength (pattern already enforces structure).minLength: 1 is redundant and misleading given the strict regex; remove it to avoid confusion.
- minLength: 1 pattern: ^[a-z]+(-[a-z0-9]+)+[0-9]+$cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5458-5487: Clarify underscore policy for label keys/values or adjust regex to match RFC1035.Descriptions and regex allow underscores (
_), but PR objectives mention RFC1035-compliant labels (no underscores). Please confirm intended policy:
- If RFC1035 (no
_) is desired, tighten patterns:
- key:
^[a-z]([-a-z0-9]{0,62})$- value:
^$|^[a-z0-9]([-a-z0-9]{0,62})$- Otherwise, update docs to explicitly allow underscores to match current regex.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (14)
api/go.sumis excluded by!**/*.sumapi/vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/lru/lru.gois excluded by!**/vendor/**api/vendor/modules.txtis excluded by!**/vendor/**go.sumis excluded by!**/*.sumvendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/lru/lru.gois excluded by!vendor/**,!**/vendor/**vendor/modules.txtis excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (23)
api/go.mod(2 hunks)api/hypershift/v1beta1/gcp.go(3 hunks)api/hypershift/v1beta1/gcp_validation_test.go(1 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(3 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(3 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(3 hunks)docs/content/reference/api.md(5 hunks)go.mod(1 hunks)test/e2e/v2/tests/api_ux_validation_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
- go.mod
- client/applyconfiguration/utils.go
- api/hypershift/v1beta1/hostedcluster_conditions.go
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
- client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go
- api/hypershift/v1beta1/hostedcluster_types.go
- client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go
- cmd/cluster/gcp/create.go
- client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
cmd/cluster/gcp/create_test.goapi/go.modtest/e2e/v2/tests/api_ux_validation_test.goapi/hypershift/v1beta1/gcp_validation_test.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlapi/hypershift/v1beta1/zz_generated.deepcopy.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamldocs/content/reference/api.mdapi/hypershift/v1beta1/gcp.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
🧬 Code graph analysis (4)
cmd/cluster/gcp/create_test.go (3)
hypershift-operator/controllers/hostedcluster/internal/platform/gcp/gcp.go (1)
GCP(34-34)support/globalconfig/network.go (1)
NetworkConfig(23-29)cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
test/e2e/v2/tests/api_ux_validation_test.go (2)
test/e2e/util/crd.go (1)
HasFieldInCRDSchema(15-38)hypershift-operator/controllers/hostedcluster/internal/platform/gcp/gcp.go (1)
GCP(34-34)
api/hypershift/v1beta1/gcp_validation_test.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-52)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-52)GCPServiceAccountsEmails(228-268)GCPWorkloadIdentityConfig(162-224)
🔇 Additional comments (36)
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
42-53: LGTM!The test fixture correctly reflects the new GCP Workload Identity Federation API structure, including network configuration and service account email references. The values are consistent with the test inputs in
create_test.go.cmd/cluster/gcp/create_test.go (3)
30-59: LGTM!The test comprehensively validates the new GCP Workload Identity Federation fields:
- Verifies all new fields (
Network,PrivateServiceConnectSubnet,WorkloadIdentity*, service accounts) are properly populated in the options- Confirms fields propagate correctly to
HostedCluster.Spec.Platform.GCP.WorkloadIdentityandNetworkConfig- Includes proper assertions for the nested
ServiceAccountsEmailsstructure
65-116: LGTM!Excellent validation test coverage:
- Defines a complete
validOptsbaseline with all required WIF fields- Tests missing required fields individually (
project,region,network)- Verifies appropriate error messages are returned
- Confirms valid options pass without errors
139-145: LGTM!The integration test correctly includes all new required CLI flags for GCP Workload Identity Federation, ensuring the end-to-end cluster creation flow can render manifests with the new WIF configuration.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (3)
5769-5785: GCE resource naming + immutability look solid.Name regexes and self==oldSelf immutability checks for network and PSC subnet align with GCE rules. LGTM.
Also applies to: 5791-5805
5820-5821: Project ID and region validations are appropriate.
- Project ID pattern enforces 6–30, start letter, no trailing hyphen.
- Region pattern excludes zones and requires trailing digits (e.g., us-central1). LGTM.
Also applies to: 5836-5837
6027-6035: Cross-field GSA/project consistency checks are good.Ends-with validation ties GSAs to the configured project domain correctly. LGTM.
api/hypershift/v1beta1/gcp.go (5)
7-52: LGTM: GCP resource naming and labeling validation is comprehensive.The updated patterns for resource names and labels correctly enforce GCP requirements. The resolution of the
GCPResourceLabel.Valuefield (now properly marked+optionalwith pointer type) addresses the previous review concern.
84-85: LGTM: CEL validation correctly implemented.The service account email validation now uses
contains('@')andendsWith()instead of the invalidsplit('@', 2)[1]syntax from earlier iterations. This correctly verifies that service accounts belong to the specified project.
141-224: LGTM: Workload Identity Federation configuration is well-validated.The WIF types include comprehensive validation:
- Numeric project number pattern and length constraints
- PoolID and ProviderID patterns correctly enforce 4-32 character length
- Reserved prefix validation blocks "gcp-" prefix conflicts
- Immutability markers prevent breaking changes to authentication chain
The decision to make
WorkloadIdentityrequired is appropriate given the feature-gated status of GCP support.
226-268: LGTM: Service account email validation is correctly implemented.The GSA email pattern and length constraints are now consistent (MinLength=37 correctly matches the pattern's minimum). The previous discrepancy flagged in past reviews has been resolved in commit c5e1417.
Both
NodePoolandControlPlanefields share the same comprehensive validation, which ensures consistency across service account references.
115-115: Based on my verification, I can now provide an assessment:Verification Results:
Pattern correctness: The regex
^[a-z]+(-[a-z0-9]+)+[0-9]+$is correct and comprehensive. It successfully matches all GCP region naming patterns:
- ✓ us-central1, us-east1, us-east4, us-east5
- ✓ europe-west1 through europe-west12
- ✓ northamerica-northeast1, northamerica-northeast2
- ✓ asia-northeast1, asia-south1, australia-southeast1
- ✓ southamerica-east1, southamerica-west1
Backtracking concern: The regex engine's backtracking is normal and not problematic. The
(-[a-z0-9]+)+segment correctly forces the engine to backtrack when necessary to ensure the final[0-9]+requirement is satisfied.Testing verification: I cannot access the repository to confirm whether
gcp_validation_test.goexists or contains test cases for this pattern.
Verify region pattern against GCP's official naming conventions.
The pattern
^[a-z]+(-[a-z0-9]+)+[0-9]+$correctly validates all GCP region formats (us-central1, europe-west1-12, northamerica-northeast1, etc.). Regex backtracking here is expected behavior and not a concern. Ensure test coverage exists ingcp_validation_test.gowith representative examples like us-central1, europe-west12, and northamerica-northeast1 to maintain pattern validation confidence across GCP regions.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (6)
5712-5716: Project ID regex looks correctPattern enforces 6‑30, starts with letter, allowed hyphen, ends alnum. LGTM.
5721-5733: Region pattern is aligned with GCP regions (ends with digits, not zones)Blocks zone suffices like
-aand requires at least one hyphen. LGTM.
5809-5816: poolID: start‑with‑letter and reserved prefix guard — goodRegex and
!self.startsWith('gcp-')match GCP rules. LGTM.
5845-5852: providerID: mirrors poolID constraints correctlyStart‑with‑letter + reserved prefix + immutability. LGTM.
5873-5881: Service account email regex and immutability look rightModern domain only and project/local‑part bounds enforced; immutability set. LGTM.
Also applies to: 5893-5899
5919-5927: Cross‑field validation tying SA emails to project — good
endsWith('@'+project+'.iam.gserviceaccount.com')ensures alignment with configured project. LGTM.test/e2e/v2/tests/api_ux_validation_test.go (6)
343-350: LGTM - BeforeEach follows established pattern.The BeforeEach correctly checks for GCP field availability in the CRD schema before running tests, matching the pattern used in the existing "GCP platform validation" context (lines 299-306).
352-378: Good comprehensive test for valid WIF configuration.The test covers all required WIF fields including
ProjectNumber,PoolID,ProviderID, andServiceAccountsRefwith properly formatted values.
380-453: Thorough validation coverage for WIF field constraints.Tests cover key validation scenarios: non-numeric project number, reserved
gcp-prefix on poolID, minimum length constraints. The expected error messages align with the validation rules defined in the API types.
455-528: Good coverage for providerID and service account email validation.Tests verify reserved prefix rejection for providerID and invalid email format detection for both NodePool and ControlPlane service accounts.
530-610: Resource label validation tests cover important edge cases.Tests include valid labels, empty values, nil values, and these correctly expect success - matching GCP's label requirements where empty values are allowed.
612-671: Good coverage for reserved prefix and max items constraints.Tests for the
googreserved prefix and the 60-item limit on resource labels are correctly implemented.api/hypershift/v1beta1/zz_generated.deepcopy.go (4)
1488-1496: Generated deepcopy correctly handles new GCP fields.The auto-generated code properly:
- Nil-checks and deep copies the
ResourceLabelsslice with element-wiseDeepCopyInto- Copies
WorkloadIdentityby value (correct sinceGCPWorkloadIdentityConfigcontains no pointer fields)
1614-1632: GCPResourceLabel deepcopy correctly handles optional Value pointer.The generated code properly allocates a new string pointer when
Valueis non-nil, preventing shared pointer references between copies.
1649-1678: GCPServiceAccountsEmails and GCPWorkloadIdentityConfig deepcopy implementations are correct.Both types contain only value types (strings and embedded structs with strings), so the simple value assignment is the correct approach.
3438-3442: PlatformSpec.DeepCopyInto correctly updated for GCP.The change from
**out = **into(*in).DeepCopyInto(*out)is necessary becauseGCPPlatformSpecnow contains a slice (ResourceLabels) requiring proper deep copy semantics.docs/content/reference/api.md (5)
6181-6235: GCPResourceLabel rules align with Compute Engine label spec.Underscores allowed, key starts with lowercase letter, and reserved “goog” noted. LGTM.
5038-5049: I'm unable to complete the verification due to repository access issues. However, I can assess the review comment itself:The original review comment is structured as a verification request rather than a finalized review. It asks for confirmation that condition type names match across the codebase, but this task requires examining:
- Go API constants/types in
api/hypershift/v1beta1- CRD YAML status descriptors
- Documentation in
docs/content/reference/api.mdSince:
- The repository clone failed, I cannot execute the verification script
- The review comment itself contains an unexecuted `` block
- The names "ValidGCPCredentials" and "ValidGCPWorkloadIdentity" appear in the documentation snippet but remain unvalidated against the source code
The review comment cannot be finalized without direct codebase access to cross-reference the condition type definitions.
Please retry this verification task, or if you have direct access to the repository, you can manually run the provided
rgcommand to search for these condition type names inapi/**/*.goandconfig/**/*.yamlfiles to confirm consistency.
6331-6416: Documentation constraint inaccuracy: start character rule differs from Google's specification.The review verified correctly that poolID/providerID constraints (length 4–32, hyphens allowed, cannot start/end with hyphen, "gcp-" prefix reserved) match Google's current WIF requirements.
However, the documentation states IDs "must start with a lowercase letter," but Google's actual constraint is that IDs must start and end with an alphanumeric character (letters or digits). This means the documentation is overly restrictive—digits are valid starting characters per Google's specification.
Correct the constraint documentation to: "Must be 4–32 characters, start and end with an alphanumeric character (a–z or 0–9), and contain only lowercase letters, digits, and hyphens."
Cannot verify CRD CEL/regex validations without repository access.
6289-6327: Based on the web search results, I now have sufficient evidence to rewrite the review comment. The search results clearly distinguish between the roles and provide strong evidence that the review comment's concern is valid.
Verify IAM role alignment with WIF architecture: serviceAccountUser vs workloadIdentityUser for controlPlane GSA.
The documentation currently lists
roles/iam.serviceAccountUserfor the controlPlane GSA. However, standard GCP Workload Identity Federation best practices indicate:
roles/iam.workloadIdentityUseris the correct role for external/federated principals to impersonate a GSA via WIFroles/iam.serviceAccountUseris for attaching a SA to GCP resources and does not enable impersonation token mintingIf Hypershift's GCP infrastructure uses WIF for external identity federation (common pattern), the documented role should be
roles/iam.workloadIdentityUserinstead. Please reconcile the documented roles againstcmd/infra/gcp/iam-bindings.jsonand confirm the WIF setup to ensure consistency.
5992-6030: Based on my verification attempts, I was unable to access the HyperShift repository's CRD definitions through available tools (repository cloning failed, and web searches for the specific CRD files were inconclusive). Without direct access to the CRD schema files, I cannot definitively verify the claims about:
- Immutability enforcement for
workloadIdentityfields (whetherx-kubernetes-validationsrules exist)- In-place propagation support for
resourceLabels- System label headroom (~4 labels reserved by HyperShift) matching implementation
The only verified fact is that GCP enforces a 64-label maximum per resource, which the documentation correctly states.
Manual verification needed: Check the CRD schema in
api/v1beta1/gcpplatform_types.goor corresponding YAML to confirm immutability rules and resource label validation.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4985-5008: LGTM: WIF immutability and CEL domain guards look correct.
- ‘gcp-’ reserved-prefix checks and field immutability are enforced.
- Email domain checks use contains/endsWith and align with required
projectdomain.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5630-5638: Nice cross-field validation for GSA domain vs project.The
endsWith('@' + self.project + '.iam.gserviceaccount.com')checks are concise and effective.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4882-4900: Nice: immutable WIF block and project-matching for GSAs.The immutability guard on workloadIdentity and the endsWith checks that GSA emails belong to spec.platform.gcp.project look good. The minLength=37 fix also matches the shortest valid address.
0c60104 to
9b470e5
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (11)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4846-4847: Regression: GSA email minLength off by one (rejects valid 6-char IDs).Minimal valid address is 37 chars: 6(sa)+1(@)+6(project)+24(".iam.gserviceaccount.com"). Current minLength 38 is too strict for both controlPlane and nodePool.
Please apply:
- minLength: 38 + minLength: 37at both occurrences.
Also applies to: 4866-4867
docs/content/reference/api.md (2)
6299-6304: Fix broken regex/pattern for GCP resource names (doc bug).The “Pattern” includes an HTML anchor and isn’t a valid, copy/paste‑able regex. Replace it with the correct regex wrapped in code formatting and keep the 63‑char note.
Apply this doc change:
-Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. +Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Also ensure the surrounding prose still states “Must start with a lowercase letter and end with a letter or digit.”
6246-6270: Allow underscores in GCP label keys/values; update charset rules.Compute Engine labels permit underscores in keys and values. The current text limits to letters/digits/hyphens only. Please update both key and value descriptions to allow “lowercase letters, digits, underscores (_), and hyphens (-)”, keep start/end rules and 63‑char limits, and retain the reserved “goog” note.
Suggested edits:
-Contain only lowercase letters, digits, or hyphens +Contain only lowercase letters, digits, underscores (_), or hyphens (-)Make the same adjustment for value, while keeping “empty allowed”.
api/hypershift/v1beta1/gcp.go (1)
242-244: MinLength should be 37 to match the pattern's enforced minimum.The regex pattern enforces a minimum of 37 characters:
- Service account name: 6 chars min (
[a-z][a-z0-9-]{4,28}[a-z0-9])@: 1 char- Project ID: 6 chars min (same pattern)
- Domain suffix: 24 chars (
.iam.gserviceaccount.com)- Total: 37 chars
Setting
MinLength=38incorrectly rejects valid 37-character emails.Apply this diff to both fields:
-// +kubebuilder:validation:MinLength=38 +// +kubebuilder:validation:MinLength=37Also applies to: 262-264
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (2)
5926-5939: projectNumber maxLength too large for int64.Project numbers are int64; cap at 19 digits or drop maxLength and rely on the numeric regex.
- maxLength: 25 + maxLength: 19Do Google Cloud project numbers fit within signed 64-bit integers (i.e., at most 19 digits)?
5981-5986: Service account email minLength: prefer relying on regex.minLength=38 can drift from the regex and observed minima; drop minLength to avoid false rejects.
- minLength: 38- minLength: 38#!/bin/bash # Compute minimal email length implied by the regex (6-char local + '@' + 6-char proj + '.iam.gserviceaccount.com') python - <<'PY' local_min = 6 proj_min = 6 suffix = len("@.iam.gserviceaccount.com") # 25 print("Computed minimum:", local_min + 1 + proj_min + (suffix-1)) # Show working if needed PYAlso applies to: 6001-6006
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5431-5443: Fix region regex and description (rejects valid regions like northamerica-northeast1).
- Current pattern
^[a-z]+-[a-z]+[0-9]+$only allows one hyphen and fails for multi‑segment regions (e.g., northamerica-northeast1).- Description also incorrectly says “exactly one hyphen.”
Use a pattern that allows one or more hyphen‑separated segments and ends with digits, and update the prose accordingly.
Apply:
- Must be in the form of <geographic-area>-<location><number> (e.g., us-central1, europe-west12). - Must contain exactly one hyphen separating the geographic area from the location. + Must be in the form of <area>-<location><number> (e.g., us-central1, europe-west12, northamerica-northeast1). + Must contain at least one hyphen; the final segment must end with one or more digits. @@ - pattern: ^[a-z]+-[a-z]+[0-9]+$ + # allow multi-segment areas/locations; last segment must end with digit(s) + pattern: ^[a-z]+(?:-[a-z]+)*-[a-z]+[0-9]+$cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5552-5601: Label value pattern is too restrictive compared to GCP requirements; update to support underscores and leading digitsGCP Compute Engine label values allow lowercase letters, digits, underscores, and hyphens, with no requirement for a leading letter. The current pattern
^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$rejects valid GCP labels like"2025","_prod", and"team_alpha". The pattern must permit underscores anywhere and leading digits/underscores to match GCP's actual constraints.Suggested update:
- Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + Empty values are allowed by GCP. If non-empty, it must contain only lowercase letters, digits, underscores, or hyphens. @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z0-9_][-a-z0-9_]{0,61}[a-z0-9_]$|^[a-z0-9_]$api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4742-4757: WIF schema, naming patterns, and CEL guards look solid.
- Network/subnet name patterns and immutability: OK.
- Project ID pattern and region format: OK.
- WIF pool/provider ID formats with reserved 'gcp-' prefix: OK.
- CEL endsWith guard tying GSAs to project: OK.
- workloadIdentity required under the feature gate: acknowledged.
Also applies to: 4763-4778, 4793-4794, 4801-4813, 4877-4898, 4914-4934, 4994-4998, 5000-5008
4846-4854: Label value regex and description must permit underscores per GCP documentation.GCP Compute Engine label values allow lowercase letters, digits, underscores, and hyphens. The current regex pattern and description incorrectly exclude underscores. Update both to match the actual GCP requirements:
- Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, + and may contain only lowercase letters, digits, underscores (_), or hyphens (-), and end with a lowercase letter or digit. @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z]([-a-z0-9_]{0,61}[a-z0-9])?$cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5734-5782: Label regex rejects valid GCP labels (missing underscores) — update patternsGCP Compute Engine labels allow underscores in both keys and values. Current patterns disallow "_", causing valid labels to be rejected at admission. Update both key and value patterns to include underscores.
Apply:
- pattern: ^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^[a-z]([a-z0-9_-]{0,61}[a-z0-9])?$- pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z]([a-z0-9_-]{0,61}[a-z0-9])?$Also update the descriptions to mention underscores and dashes (they currently say "hyphens only").
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (6)
api/go.sumis excluded by!**/*.sumapi/vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/lru/lru.gois excluded by!**/vendor/**api/vendor/modules.txtis excluded by!**/vendor/**go.sumis excluded by!**/*.sum
📒 Files selected for processing (21)
api/go.mod(1 hunks)api/hypershift/v1beta1/gcp.go(3 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(2 hunks)docs/content/reference/api.md(5 hunks)go.mod(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- go.mod
🚧 Files skipped from review as they are similar to previous changes (6)
- client/applyconfiguration/utils.go
- client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go
- cmd/cluster/gcp/create_test.go
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
- api/go.mod
- cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.goclient/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.goapi/hypershift/v1beta1/hostedcluster_conditions.goapi/hypershift/v1beta1/hostedcluster_types.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/cluster/gcp/create.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamldocs/content/reference/api.mdcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlapi/hypershift/v1beta1/zz_generated.deepcopy.goapi/hypershift/v1beta1/gcp.go
🧬 Code graph analysis (4)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
api/hypershift/v1beta1/hosted_controlplane.go (1)
ConditionType(294-294)
cmd/cluster/gcp/create.go (1)
cmd/util/util.go (1)
ValidateRequiredOption(11-16)
api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
api/hypershift/v1beta1/gcp.go (3)
GCPResourceLabel(23-50)GCPServiceAccountsEmails(227-267)GCPWorkloadIdentityConfig(161-223)
api/hypershift/v1beta1/gcp.go (2)
test/e2e/util/external_oidc.go (1)
Key(289-292)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
🪛 golangci-lint (2.5.0)
api/hypershift/v1beta1/gcp.go
[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn
(typecheck)
🔇 Additional comments (41)
api/hypershift/v1beta1/zz_generated.deepcopy.go (3)
1488-1493: LGTM! Correct deepcopy implementation for new GCP fields.The deepcopy logic is correctly implemented:
ResourceLabelsslice is properly allocated and copied using the standard pattern for slices of value-type structs.WorkloadIdentitystruct assignment is appropriate sinceGCPWorkloadIdentityConfigand its nested types contain only string fields (no pointers, slices, or maps).
1612-1671: LGTM! New GCP type deepcopy methods are correct.The deepcopy implementations for the three new GCP types are appropriate:
- All types contain only string fields or nested structs with string fields.
- Shallow struct copying via
*out = *inis correct and efficient for value types.- The pattern is consistent with similar types throughout the file.
3434-3434: LGTM! Correct deepcopy pattern for GCP platform.The change from shallow copy to calling
DeepCopyIntois necessary and correct becauseGCPPlatformSpecnow contains theResourceLabelsslice field that requires proper deep copying. This pattern is consistent with other platform types in the file.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4634-4650: LGTM: GCP naming/immutability, labels, and WIF validations look solid.
- Network/subnet names and immutability are aligned with GCE constraints.
- Project/region regexes and docs are clear and restrictive in the right ways.
- Label key/value patterns block reserved 'goog' prefix and enforce RFC1035-like rules; list-map enforces unique keys.
- WIF: pool/provider IDs, projectNumber, and overall immutability checks are well-scoped; project match checks for GSAs are in place.
No further action from me here.
Also applies to: 4655-4670, 4685-4689, 4693-4705, 4706-4755, 4756-4826, 4892-4900
api/hypershift/v1beta1/hostedcluster_types.go (1)
133-135: LGTM!The constant follows the established pattern for ClusterAPI provider image overrides and is properly documented.
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: LGTM!The new GCP validation conditions are well-structured and follow the established pattern for platform-specific validation. The separation between credential validation and Workload Identity configuration is appropriate and the documentation clearly indicates the external intervention that may be required.
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
1-47: LGTM!This is generated code that follows the standard apply configuration pattern. The implementation provides proper constructor and fluent builder methods for GCPServiceAccountsEmails configuration.
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
1-47: LGTM!This is generated code that follows the standard apply configuration pattern. The implementation provides proper constructor and fluent builder methods for GCPResourceLabel configuration.
docs/content/reference/api.md (1)
5062-5072: New GCP condition types look good.The additions for ValidGCPCredentials and ValidGCPWorkloadIdentity are clear and consistent with the rest of the condition set.
cmd/cluster/gcp/create.go (3)
18-28: LGTM! Well-structured flag definitions and options.The new GCP WIF-related fields are properly defined with clear naming and documentation. The help text appropriately references
hypershift infra create gcpoutput for obtaining the required values.Also applies to: 37-57
93-113: Validation logic correctly enforces all required WIF fields.The validation follows the established pattern and properly ensures all WorkloadIdentity configuration is provided. This aligns with the confirmed design decision for WIF-only GCP support at this stage.
175-198: Correct mapping of CLI options to GCPPlatformSpec.The
ApplyPlatformSpecificsmethod properly populates the nestedGCPNetworkConfigandGCPWorkloadIdentityConfigstructures with all required fields from the validated options.api/hypershift/v1beta1/gcp.go (5)
6-18: LGTM! GCPResourceReference pattern and documentation improved.The updated regex pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$correctly allows both single-character names (a) and multi-character names ending with alphanumeric, conforming to GCP naming standards.
20-50: GCPResourceLabel type correctly implements GCP Compute Engine label constraints.The key validation properly blocks the reserved
googprefix via XValidation. The value field correctly allows empty strings as permitted by GCP. The pattern enforces RFC1035-compliant naming (no underscores, lowercase only).
66-79: LGTM! Immutability constraints properly applied to network configuration.The XValidation rules correctly use
self == oldSelfCEL syntax to enforce immutability of VPC network and Private Service Connect subnet after cluster creation.
82-83: Cross-field validation correctly ensures service accounts belong to the project.The XValidation rules use
contains('@')andendsWith()CEL functions to verify that both service account emails match the project specified inself.project. This approach avoids the previously flaggedsplit()syntax issue.
158-223: GCPWorkloadIdentityConfig properly validates WIF resource identifiers.The configuration correctly enforces:
- Numeric project number format
- Pool/Provider ID constraints (4-32 chars, no
gcp-prefix)- Immutability via XValidation rules
The documentation helpfully references
hypershift infra create gcpas the source for these values.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (6)
5769-5784: GCP network/subnet naming + immutability: LGTM.Patterns match GCP rules; immutability on the object is correct.
5820-5821: Project ID regex: LGTM.Matches GCP format and aligns with min/max length.
5841-5890: Resource labels schema: LGTM.
- Map semantics prevent duplicate keys.
- RFC1035‑style key/value patterns consistent with stated intent.
- Reserved 'goog' prefix ban is documented and enforced.
If you want stronger clarity, add “This is stricter than some GCP services; intentionally RFC1035 for Compute Engine resources.”
5904-5960: WIF pool/provider IDs: LGTM.Length/patterns, ‘gcp-’ reservation, and immutability look correct.
6026-6035: Cross‑field SA domain check: LGTM.endsWith validation ties SA emails to the same project ID as intended.
5826-5837: Regex pattern is correct for all current GCP regions.The pattern
^[a-z]+-[a-z]+[0-9]+$successfully matches all current Google Cloud regions including: us-central1, europe-west12, northamerica-northeast1, australia-southeast2, asia-south1, southamerica-east1, me-central1, me-west1, africa-south1, and all other variations. No modifications needed.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (6)
5372-5381: LGTM: GCP network name rules and immutability.Pattern and immutability align with GCP constraints.
Also applies to: 5385-5387
5393-5402: LGTM: PSC subnet name rules and immutability.Consistent with GCP subnet naming.
Also applies to: 5406-5408
5423-5423: LGTM: GCP project ID pattern.Length and character rules are correct; hyphen not allowed at end is enforced.
5445-5493: resourceLabels: confirm list semantics and parity across CRDs.You’ve chosen x-kubernetes-list-type: map keyed by “key” (good for uniqueness). Please confirm this intent is applied consistently to the non‑TechPreview CRDs to avoid drift. If parity isn’t desired, call it out in docs.
5494-5622: LGTM: Workload Identity Federation schema.Field shapes, immutability, and email patterns look solid.
If you want an extra guard, we can add a CEL rule ensuring controlPlane/nodePool emails are not identical (optional).
5630-5638: LGTM: SA email ↔ project cross-field validation.Simple and effective domain check against spec.gcp.project.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (6)
5480-5496: GCP VPC network name: regex + immutability look goodPattern matches GCP naming and locks the field. LGTM.
5501-5516: PSC subnet name: regex + immutability look goodConsistent with GCP naming and prevents day‑2 drift. LGTM.
5531-5531: Project ID validation looks correctLength, charset, start/end constraints align with GCP guidance. LGTM.
5539-5548: Region format check is reasonableThe pattern enforces “area-locationN” and excludes zone suffixes. LGTM.
If you want extra safety, verify it still admits all current regions (e.g., northamerica-northeast1, australia-southeast2) as GCP adds regions over time.
5738-5746: Same‑project SA checks: nice cross‑field guardEndsWith checks for controlPlane/nodePool against spec.platform.gcp.project are clear and cheap. LGTM.
5602-5730: Keep "gcp-" prefix validation — it's officially requiredThe "gcp-" prefix restriction is documented in Google Cloud's official Workload Identity documentation and REST API reference. The validation rules correctly implement this official constraint and should not be removed.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (6)
5661-5670: GCP network name validation looks goodPattern and immutability match GCP resource naming rules.
Also applies to: 5674-5677
5682-5691: PSC subnet name validation looks goodPattern and immutability align with GCP subnet naming.
Also applies to: 5695-5697
5712-5712: Project ID regex is correctEnforces 6–30 chars, starts with letter, no trailing hyphen.
5720-5729: Region pattern acceptableCovers current region formats and excludes zone suffixes.
5783-5852: poolID/providerID regex tightened correctlyNow requires leading letter and blocks reserved “gcp-” prefix; immutability is appropriate.
5854-5899: Service account email validation is solidDomain constrained to PROJECT_ID.iam.gserviceaccount.com, hardened local/project patterns, and minLength consistent.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (1)
api/hypershift/v1beta1/gcp.go(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
api/hypershift/v1beta1/gcp.go
🧬 Code graph analysis (1)
api/hypershift/v1beta1/gcp.go (1)
client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)
🪛 golangci-lint (2.5.0)
api/hypershift/v1beta1/gcp.go
[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn
(typecheck)
🔇 Additional comments (8)
api/hypershift/v1beta1/gcp.go (8)
7-16: LGTM - Pattern simplification improves clarity.The updated regex pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$is cleaner and aligns well with GCP resource naming requirements. The change from the previous pattern maintains the same constraints (start with lowercase letter, end with lowercase letter or number, hyphens allowed in the middle) with improved readability.
20-50: LGTM - GCPResourceLabel implementation is sound.The label validation correctly implements GCP Compute Engine label requirements:
- Key validation enforces RFC1035-like naming with the reserved "goog" prefix check
- Value is properly optional with support for empty strings per GCP API
- All constraints align with GCP documentation
70-78: LGTM - Immutability rules are appropriate.Making Network and PrivateServiceConnectSubnet immutable after cluster creation is correct, as changing VPC configuration post-creation would break cluster connectivity.
82-83: LGTM - CEL validation correctly enforces project membership.The XValidation rules properly verify that service account emails belong to the same project using
contains('@')andendsWith(). This approach avoids the invalidsplit('@', 2)syntax from earlier drafts.
96-114: LGTM - Project and Region patterns are correctly tightened.Both patterns now properly enforce GCP naming requirements:
- Project: enforces 6-30 character length with proper start/end constraints
- Region: requires exactly one hyphen and trailing digits, correctly excluding zone suffixes
128-138: LGTM - ResourceLabels configuration is appropriate.The
listType=mapwithlistMapKey=keyensures unique keys, andMaxItems=60appropriately reserves headroom for system labels within GCP's 64-label limit.
140-156: LGTM - WorkloadIdentity configuration is well-documented.The field is correctly marked as required and immutable, with comprehensive documentation covering prerequisites and the authentication chain. The
omitzerotag is appropriate for the struct field.
158-223: LGTM - WIF configuration validation is comprehensive.All fields have appropriate validation:
- ProjectNumber correctly validates numeric GCP project identifiers
- PoolID and ProviderID patterns enforce 4-32 character length with proper constraints
- Reserved "gcp-" prefix checks prevent conflicts with Google system resources
- Immutability protects the authentication chain
746f28a to
3231ee8
Compare
Update vendor files and dependencies to support upcoming GCP WIF types: - k8s.io/utils updates for compatibility - Go module dependency updates These dependency updates are required for the GCP Workload Identity Federation implementation and ensure compatibility across the codebase. Signed-off-by: Amador Pahim <apahim@redhat.com> Commit-Message-Assisted-by: Claude (via Claude Code)
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (10)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4846-4848: Fix off‑by‑one: GSA email minLength 38 rejects valid addresses.Minimal valid length is 37 (6 + 1 + 6 + 24). Pattern already permits 37; schema must too.
Apply:
- minLength: 38 + minLength: 37And for nodePool:
- minLength: 38 + minLength: 37Verification (also checks other CRD variants):
#!/bin/bash rg -nC2 -e 'gserviceaccount\.com' -e 'minLength:\s*3[7-8]' api cmd | sed -n '1,200p'Also applies to: 4866-4868
docs/content/reference/api.md (1)
6299-6304: Fix broken regex/pattern for GCP resource names (doc bug).Pattern currently includes an HTML anchor and is not a valid regex. Replace with a copy/paste‑able pattern and keep the 63‑char note.
Use:
- Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. + Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Note: Put the regex in backticks in the source Go comment (e.g., api/hypershift/v1beta1/gcp.go), then regenerate docs (make api-docs).
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4846-4854: Allow underscores in label values per GCE docs.Compute Engine label values may include underscores; current regex/description reject them. Update both to avoid blocking valid inputs.
Suggested change:
- description: |- - value is the value part of the label. A label value can have a maximum of 63 characters. - Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + description: |- + value is the value part of the label. A label value can have a maximum of 63 characters. + Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, + and may contain only lowercase letters, digits, underscores (_), or hyphens (-). @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z][a-z0-9_-]{0,62}$To verify there are no lingering non-underscore patterns across generated CRDs and sources, run:
#!/bin/bash # Find label value patterns that still exclude underscores rg -n -C2 -S "pattern:\s*\^\$\|\^\[a-z]\(\[-a-z0-9\]\{0,61\}\[a-z0-9\]\)\?\$" api/ cmd/ || true # Show occurrences that already include underscores (expected) rg -n -C2 -S "pattern:\s*\^\$\|\^\[a-z]\[a-z0-9_-\]\{0,62\}\$" api/ cmd/ || trueapi/hypershift/v1beta1/gcp.go (1)
242-244: Adjust MinLength from 38 to 37 to match the pattern's actual minimum.The regex pattern enforces a minimum of 37 characters:
- Service account name: 6 chars min (
[a-z]+[a-z0-9-]{4,28}(min 4) +[a-z0-9])@: 1 char- Project ID: 6 chars min
- Domain: 24 chars (
.iam.gserviceaccount.com)- Total: 37 chars
Setting
MinLength=38creates an off-by-one error where valid 37-character emails likeaaaaaa@bbbbbb.iam.gserviceaccount.comwould be rejected.Apply this diff to both fields:
-// +kubebuilder:validation:MinLength=38 +// +kubebuilder:validation:MinLength=37Also applies to: 262-264
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (2)
5431-5440: Region regex fix looks correct.Accepts valid regions (e.g., us-central1, europe-west12, northamerica-northeast1) and rejects zones; description aligns.
5445-5493: Labels: uniqueness + headroom implemented correctly.Using list-map semantics keyed by ‘key’ with maxItems: 60 prevents duplicates and preserves system label headroom.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5565-5593: GCP label value pattern is too restrictive; must allow underscores and leading digits.According to official GCP documentation, Compute Engine label values allow lowercase letters, digits, underscores, and hyphens. The current pattern
^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$incorrectly forbids underscores and requires leading letters instead of allowing leading digits.Apply:
- pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z0-9][a-z0-9_-]{0,62}$Update the description to mention "letter or digit" instead of just "lowercase letter" and add "underscores (_) allowed."
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5919-5927: Fix project match: endsWith() is spoofable; compare domain exactly after '@'.Suffix collisions like sa@other-myproj.iam.gserviceaccount.com will pass for project "myproj". Split on '@' and compare the domain exactly.
- rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.contains('@') - && self.workloadIdentity.serviceAccountsEmails.controlPlane.endsWith('@' - + self.project + '.iam.gserviceaccount.com') + rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.split("@", 2)[1] == self.project + ".iam.gserviceaccount.com" ... - rule: self.workloadIdentity.serviceAccountsEmails.nodePool.contains('@') - && self.workloadIdentity.serviceAccountsEmails.nodePool.endsWith('@' - + self.project + '.iam.gserviceaccount.com') + rule: self.workloadIdentity.serviceAccountsEmails.nodePool.split("@", 2)[1] == self.project + ".iam.gserviceaccount.com"
5734-5781: Label regex too strict; allow underscores and relaxed ending per GCP label rules.Keys/values currently reject valid labels (no “_”, no trailing “-”). GCP labels allow underscores; values may be empty and need not start with a letter. Update patterns to match GCP behavior.
- pattern: ^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^[a-z][a-z0-9_-]{0,62}$ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z0-9_-]{1,63}$Optional (list semantics): prefer array + CEL uniqueness over listType=map to avoid SSA merge surprises.
- x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5926-5939: Tighten projectNumber maxLength to match GCP int64 limitsGCP project numbers are int64 values with a maximum of 19 decimal digits (9,223,372,036,854,775,807). Reduce maxLength from 25 to 19 to enforce stricter validation and prevent accepting invalid inputs.
- maxLength: 25 + maxLength: 19
🧹 Nitpick comments (5)
docs/content/reference/api.md (2)
6220-6272: Align label charset with GCP Compute labels (underscores).Doc says keys/values allow only letters, digits, hyphens. Compute Engine labels allow underscores (_) too; keys 1–63 chars, start with a lowercase letter; values up to 63, empty allowed.
Please update the copy to include underscores (and keep the reserved "goog" prefix note), or explicitly state you’re intentionally stricter than GCP.
Would you verify against the latest “Organize resources using labels” docs and adjust this section accordingly?
6325-6366: Document least‑privilege for nodePool GSA; add SA User nuance.Add that when the VM SA differs from the controller’s GSA, grant roles/iam.serviceAccountUser on that VM SA; if using roles/iam.workloadIdentityUser to impersonate the same SA, SA User isn’t needed.
Suggested tweak:
This GSA requires the following IAM roles: - roles/compute.instanceAdmin.v1 (Compute Instance Admin v1) - roles/compute.networkAdmin (Compute Network Admin) + - If a distinct VM service account is attached to instances, also grant + roles/iam.serviceAccountUser on that VM SA to the controller GSA.Ensure this aligns with cmd/infra/gcp/iam-bindings.json.
cmd/cluster/gcp/create_test.go (1)
62-75: Validation tests correctly cover new required flags; consider adding a couple more casesUsing a fully-populated
validOptsand then deriving “missing X” cases is a solid pattern and the new tests for missingproject,region, andnetworkalign with the CLI validation messages. Since the implementation now also requiresprivate-service-connect-subnet, WIF IDs, and both service accounts, you might optionally add a couple of representative “missing workload identity field” cases to catch regressions in those error paths as well, but this is not strictly required.Also applies to: 77-101, 103-115
cmd/cluster/gcp/create.go (1)
85-113: Requiring all WIF/network fields at validation time matches the WIF-only design; optional: add shallow format checksThe validation now enforces presence of
network, PSC subnet, WIF project number, pool/provider IDs, and both service account emails, which is appropriate given the current “Workload Identity only” support. This ensures incomplete CLI invocations fail fast before attempting cluster creation.If you want to improve UX further, you could optionally add lightweight format checks here (e.g., numeric check for project number, or a basic GSA email shape) to surface obvious mistakes earlier instead of relying solely on API/CRD validation, but that’s not strictly necessary.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5841-5890: Labels: uniqueness is enforced; consider clarifying reserved-prefix wording
- Good: list-map semantics prevent duplicate keys; RFC1035-style constraints are consistent for Compute Engine.
- Wording nit: the description states “GCP reserves the 'goog' prefix...”, while the validation intentionally blocks any 'goog*'. Clarify it’s a product choice to avoid confusion with Google-reserved 'goog-'.
Apply wording tweak:
- GCP reserves the 'goog' prefix for system labels. + We reserve any key starting with 'goog' to avoid collisions with Google‑reserved 'goog-' system labels.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (14)
api/go.sumis excluded by!**/*.sumapi/vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/lru/lru.gois excluded by!**/vendor/**api/vendor/modules.txtis excluded by!**/vendor/**go.sumis excluded by!**/*.sumvendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/lru/lru.gois excluded by!vendor/**,!**/vendor/**vendor/modules.txtis excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (22)
api/go.mod(1 hunks)api/hypershift/v1beta1/gcp.go(3 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(2 hunks)docs/content/reference/api.md(5 hunks)go.mod(1 hunks)test/e2e/v2/tests/api_ux_validation_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- api/hypershift/v1beta1/hostedcluster_conditions.go
- api/hypershift/v1beta1/hostedcluster_types.go
- client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go
- client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go
- cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
- client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
go.modclient/applyconfiguration/utils.goapi/go.modcmd/cluster/gcp/create.gotest/e2e/v2/tests/api_ux_validation_test.gocmd/cluster/gcp/create_test.goapi/hypershift/v1beta1/zz_generated.deepcopy.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/gcp.godocs/content/reference/api.mdcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml
🧬 Code graph analysis (5)
client/applyconfiguration/utils.go (4)
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabelApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReferenceApplyConfiguration(22-24)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmailsApplyConfiguration(22-25)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfigApplyConfiguration(22-27)
cmd/cluster/gcp/create.go (4)
cmd/util/util.go (1)
ValidateRequiredOption(11-16)api/hypershift/v1beta1/gcp.go (4)
GCPNetworkConfig(67-79)GCPResourceReference(6-18)GCPWorkloadIdentityConfig(161-223)GCPServiceAccountsEmails(227-267)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfig(31-33)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmails(29-31)
test/e2e/v2/tests/api_ux_validation_test.go (3)
test/e2e/util/crd.go (1)
HasFieldInCRDSchema(15-38)api/hypershift/v1beta1/hostedcluster_types.go (2)
HostedCluster(2013-2026)GCPPlatform(1205-1205)api/hypershift/v1beta1/gcp.go (6)
GCPPlatformSpec(84-156)GCPNetworkConfig(67-79)GCPResourceReference(6-18)GCPWorkloadIdentityConfig(161-223)GCPServiceAccountsEmails(227-267)GCPResourceLabel(23-50)
cmd/cluster/gcp/create_test.go (1)
cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
api/hypershift/v1beta1/gcp.go (4)
client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabel(29-31)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfig(31-33)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmails(29-31)
🪛 golangci-lint (2.5.0)
api/hypershift/v1beta1/gcp.go
[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn
(typecheck)
🔇 Additional comments (40)
go.mod (1)
293-295: Dependency pin fork8s.io/utilslooks intentional and consistentThe replace/pin with an explanatory comment matches other targeted overrides in this module and is a reasonable way to align with the Kubernetes 1.32.3 stack. No issues from a correctness or maintainability perspective.
client/applyconfiguration/utils.go (1)
176-183: New GCP WIF ForKind mappings are correct and idiomaticThe added cases for
GCPResourceLabel,GCPServiceAccountsEmails, andGCPWorkloadIdentityConfigfollow the existing pattern and return the expected apply configuration types; this should seamlessly enable client-side apply for the new GCP WIF APIs.api/hypershift/v1beta1/zz_generated.deepcopy.go (5)
1488-1495: Deep copy forGCPPlatformSpeccorrectly handles new fieldsThe updated
GCPPlatformSpec.DeepCopyIntonow deep-copies theResourceLabelsslice element‑by‑element and copiesWorkloadIdentityby value. Given the new GCP types are value-only (or have their own DeepCopy), this prevents shared mutable state while keeping the implementation minimal.
1614-1632:GCPResourceLabelDeepCopy correctly handles pointer fieldThe DeepCopy implementation allocates a new
Valuestring when non‑nil and otherwise relies on value copy for the rest, which matches the struct’s shape and avoids pointer aliasing.
1649-1662:GCPServiceAccountsEmailsDeepCopy is sufficient for its value-only fieldsUsing
*out = *inis appropriate here since the type has no pointer, map, or slice fields; no risk of shared mutable state.
1664-1678:GCPWorkloadIdentityConfigDeepCopy matches the new type’s structureThe implementation copies the struct by value, including
ServiceAccountsEmails, which itself is value-only. This is correct and keeps the DeepCopy minimal while preserving isolation.
3438-3442: DeepCopy forPlatformSpec.GCPis now correctly delegatedSwitching the
GCPbranch inPlatformSpec.DeepCopyIntoto allocate a newGCPPlatformSpecand callDeepCopyIntoensures the new nested slice (ResourceLabels) and WIF config are fully deep‑copied instead of shallowly assigned. This brings GCP in line with other complex platform specs.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (7)
4634-4650: GCP network name + immutability look good.Pattern and immutability rule match GCP constraints.
4655-4671: PSC subnet name + immutability look good.Matches GCP naming and locks the field post‑create.
4685-4685: Project ID regex is correct.Length and charset align with GCP rules; anchors prevent edge cases.
4693-4702: Region validation looks right.Single hyphen, trailing digits, lowercase; covers known regions.
4706-4755: Labels: solid constraints and map semantics.
- Correct key/value patterns (lowercase, hyphens), reserved “goog” blocked.
- List‑map keyed by “key” prevents dupes; SSA‑friendly.
4756-4884: WIF fields and immutability are well‑scoped.poolID/providerID patterns, reserved prefix blocks, projectNumber numeric, and per‑field immutability look correct.
4891-4900: Project consistency check is good.CEL endsWith() guards ensure SA project matches spec.platform.gcp.project.
api/go.mod (1)
90-92: LGTM! Correct k8s.io/utils version pinned.The replace directive correctly pins k8s.io/utils to v0.0.0-20241104100929-3ea5e8cea738, which aligns with the k8s.io/client-go v0.32.3 dependency as discussed in the previous review. The comment clearly documents the rationale.
test/e2e/v2/tests/api_ux_validation_test.go (2)
343-672: Comprehensive GCP WIF validation test coverage.The new test context thoroughly exercises GCP Workload Identity Federation validation rules with well-structured acceptance and rejection scenarios. Tests cover:
- Valid and invalid ProjectNumber, PoolID, ProviderID formats
- Reserved prefix validation ('gcp-' and 'goog')
- Service account email format validation
- Resource label constraints (key/value format, max 60 items)
The BeforeEach guard properly skips tests when GCP CRD fields are unavailable, and all tests follow consistent patterns with the rest of the file.
1949-1981: Well-designed helper functions for validation testing.The
testHostedClusterCreationandtestNodePoolCreationhelpers effectively reduce code duplication across validation tests. The double-deletion pattern (defer + explicit delete) is appropriate for validation test scenarios:
- The defer ensures cleanup in all code paths (panic, early return, normal completion)
- The explicit delete after
Createensures immediate cleanup when creation succeeds- Both deletions safely ignore errors, handling cases where the resource doesn't exist
This defensive approach is good practice for test isolation and resource cleanup.
docs/content/reference/api.md (2)
5062-5072: New GCP conditions look good.ValidGCPCredentials and ValidGCPWorkloadIdentity add useful observability. No issues found.
5977-5982: Region validation text LGTM.Examples and constraints read well and are accurate.
cmd/cluster/gcp/create_test.go (2)
25-43: ApplyPlatformSpecifics wiring is exercised end-to-end and looks correctThe test now builds a
RawCreateOptionswith all new network and Workload Identity fields and asserts each one is present inHostedCluster.Spec.Platform.GCP(including nestedNetworkConfigandWorkloadIdentity.ServiceAccountsEmails). This gives good coverage of the new ApplyPlatformSpecifics wiring; no issues spotted.Also applies to: 53-59
130-150: CLI flag plumbing for new GCP options is covered via render testExtending the “minimal flags necessary to render” scenario with the new network, PSC subnet, Workload Identity, and service account flags ensures they are accepted and flow through the generic
core.CreateClusterpath without breaking rendering. This is a good high-level integration check; no problems identified.cmd/cluster/gcp/create.go (2)
18-28: Flag constants, raw options, and bindings are consistent and aligned with API typesThe new flag names (
--network,--private-service-connect-subnet, WIF IDs, and service accounts) match the tests and are clearly documented, including references tohypershift infra create gcpfor sourcing values. The correspondingRawCreateOptionsfields andBindOptionswiring are straightforward and map 1:1 to the future API fields. No functional or maintainability issues here.Also applies to: 30-58, 60-71
175-198: ApplyPlatformSpecifics correctly populates new GCP network and Workload Identity fieldsThe new
NetworkConfigandWorkloadIdentityblocks are populated directly from the validated options and align with the corresponding API types (GCPNetworkConfig,GCPResourceReference,GCPWorkloadIdentityConfig,GCPServiceAccountsEmails). This should satisfy the API’s+requiredand immutability constraints from the outset. Wiring looks correct and cohesive.api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4742-4757: LGTM on GCP naming, region, and CEL cross-field checks.
- Network/subnet name patterns and immutability: good.
- Project ID pattern: matches GCP constraints.
- Region doc and regex: matches current GCP region format.
- CEL endsWith/contains for GSA domain binding: safe and correct.
Also applies to: 4764-4778, 4793-4793, 4801-4810, 5000-5008
api/hypershift/v1beta1/gcp.go (5)
7-18: LGTM! GCPResourceReference pattern updated correctly.The updated pattern
^[a-z]([-a-z0-9]*[a-z0-9])?$correctly implements GCP resource naming standards, allowing hyphens anywhere in the middle while enforcing lowercase letters/digits at boundaries.
20-50: LGTM! GCPResourceLabel validation is well-designed.The implementation correctly handles GCP Compute Engine label requirements:
- Key validation blocks the reserved 'goog' prefix via XValidation
- Value is properly optional (*string with omitempty) to allow empty values per GCP API
- Patterns enforce RFC1035-style constraints (no underscores, lowercase only)
- MaxItems=60 on the parent list (line 137) leaves headroom for HyperShift system labels
66-79: LGTM! Immutability constraints prevent breaking changes.The XValidation rules
self == oldSelfon Network and PrivateServiceConnectSubnet correctly prevent modifications after cluster creation, which is essential since these underpin the Private Service Connect networking model.
81-156: LGTM! Cross-field validation ensures consistency.The XValidation rules on lines 82-83 correctly enforce that service account emails belong to the cluster's project by validating they end with
@{project}.iam.gserviceaccount.com. The WorkloadIdentity field's immutability and required status are appropriate given the feature-gated nature of GCP support.
158-223: LGTM! WIF configuration fields have strong validation.The GCPWorkloadIdentityConfig type correctly validates:
- ProjectNumber as numeric-only string
- PoolID and ProviderID with reserved prefix checks ('gcp-' blocked)
- All WIF fields immutable to prevent breaking the authentication chain
The extensive documentation references (
hypershift infra create gcp, IAM role requirements) help users understand the prerequisites.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (4)
5372-5388: LGTM: GCP network and PSC subnet name validation + immutability.Patterns match GCP rules and object immutability is correctly enforced.
Also applies to: 5393-5408
5414-5427: LGTM: Project ID pattern.Bounds and charset align with GCP project-id constraints; immutable as expected.
5630-5638: LGTM: SA email belongs-to-project check.CEL endsWith guard is clear and resilient; contains('@') avoids false positives.
5507-5528: The "gcp-" prefix reservation is correct.Verified against Google Cloud IAM Workload Identity Federation documentation: the "gcp-" prefix is indeed reserved by Google for both Workload Identity Pool IDs and Provider IDs and cannot be used. The validation rule, character restrictions, and length constraints (4–32 characters, lowercase letters/digits/hyphens only, no leading/trailing hyphens) all align with official Google Cloud specifications.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (2)
5537-5548: Region regex rejects valid multi-hyphen regions (e.g., northamerica-northeast1).Your pattern only allows a single hyphen:
^[a-z]+-[a-z]+[0-9]+$. Permit additional hyphenated location segments.Apply:
- pattern: ^[a-z]+-[a-z]+[0-9]+$ + pattern: ^[a-z]+-[a-z]+(?:-[a-z]+)*[0-9]+$Likely an incorrect or invalid review comment.
5569-5583: GCP label key pattern must allow underscores to match GCP requirements.The current pattern forbids underscores, but Google Cloud Compute Engine allows label keys to contain lowercase letters, digits, underscores, and dashes. Keys must start with a lowercase letter and end with a letter or digit (1-63 characters total).
Apply:
- pattern: ^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^[a-z][a-z0-9_-]{0,61}[a-z0-9]$Keep the reserved prefix rule for "goog" as-is.
Likely an incorrect or invalid review comment.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (5)
5769-5785: Network and PSC subnet naming + immutability: LGTMPatterns match GCP rules and immutability guards are correct.
Also applies to: 5791-5805
5811-5824: Project ID validation: LGTMRegex and bounds align with GCP’s 6–30, lowercase/digits/hyphens, start letter, no trailing hyphen.
5826-5837: Region validation text and pattern: LGTMPattern allows known regions (e.g., us-central1, europe-west12, northamerica-northeast1). Docs clearly exclude zones.
5967-6007: Service account email regex and minLength: LGTMPattern is strict and minLength 38 matches the shortest possible address (6+1+6+1+24).
6026-6035: Cross-field SA→project ownership checks: LGTMEnds-with guard ties both GSAs to the specified project; simple and effective.
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (8)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4846-4847: GSA email minLength off by one (rejects valid 6‑char IDs).Minimal valid address length is 37 chars (6 + 1 + 6 + 24). Current minLength: 38 will reject valid addresses.
Apply this diff to both controlPlane and nodePool:
- minLength: 38 + minLength: 37Also applies to: 4866-4867
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4954-4976: Off-by-one: minLength for GSA emails should be 37 (not 38).Shortest valid: 6(local) + 1(@) + 6(project) + 24(".iam.gserviceaccount.com") = 37. Current 38 rejects valid addresses. Fix both controlPlane and nodePool.
Apply this diff:
- minLength: 38 + minLength: 37 @@ - minLength: 38 + minLength: 37
4814-4863: Update label value pattern to allow underscores as per GCP documentation.GCP Compute Engine label values allow lowercase letters, digits, underscores (_), and dashes (-). The current pattern
^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$excludes underscores and unnecessarily restricts the ending character. Update the description and regex to^$|^[a-z][a-z0-9_-]{0,62}$:- description: |- - value is the value part of the label. A label value can have a maximum of 63 characters. - Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + description: |- + value is the value part of the label. A label value can have a maximum of 63 characters. + Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, + and may contain only lowercase letters, digits, underscores (_), or hyphens (-). See https://cloud.google.com/compute/docs/labeling-resources for Compute Engine label requirements. @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z][a-z0-9_-]{0,62}$docs/content/reference/api.md (1)
6299-6304: Replace broken name regex; remove HTML anchor.The “Pattern” includes an HTML link and is not a valid regex. Use a copy/paste‑able pattern and wrap it in backticks in the source Go comment, then regenerate docs.
- Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars) ... + Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Tip: apply in api/hypershift/v1beta1/gcp.go comments and run
make api-docs.api/hypershift/v1beta1/gcp.go (1)
240-246: MinLength=38 creates an off-by-one inconsistency with the pattern.The regex pattern's minimum valid email is 37 characters:
- Service account name: 6 chars (1 + 4 + 1)
@: 1 char- Project ID: 6 chars (1 + 4 + 1)
- Domain
.iam.gserviceaccount.com: 24 chars- Total: 37 chars
A valid 37-character email like
aaaaaa@bbbbbb.iam.gserviceaccount.comwould be rejected byMinLength=38despite matching the pattern.-// +kubebuilder:validation:MinLength=38 +// +kubebuilder:validation:MinLength=37The same fix applies to
controlPlaneat line 263.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5553-5600: Label value regex too strict — allow leading digits and underscores per GCP.Current value pattern forbids leading digits and underscores, rejecting valid labels like "2025" or "ci_build". Update description and pattern to match GCP Compute label rules; keep keys as-is.
Apply this diff:
@@ - value: - description: |- - value is the value part of the label. A label value can have a maximum of 63 characters. - Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + value: + description: |- + value is the value part of the label. A label value can have a maximum of 63 characters. + Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter or digit, + may contain only lowercase letters, digits, underscores, or hyphens, and must end with a lowercase letter or digit. @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z0-9][a-z0-9_-]{0,62}$cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5734-5782: GCP label key/value regex too strict — underscores must be allowed.GCP Compute Engine labels permit underscores in keys and values; current patterns reject them, blocking valid configs.
Apply:
- pattern: ^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^[a-z]([a-z0-9_-]{0,61}[a-z0-9])?$- pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z]([a-z0-9_-]{0,61}[a-z0-9])?$Also consider avoiding list-map semantics here and enforce key uniqueness with a CEL rule at the array level to prevent SSA merge surprises. This was suggested earlier.
5919-5927: endsWith-based project check is vulnerable to suffix collisions — compare domain exactly.Use split('@',2)[1] equality for both controlPlane and nodePool to prevent false positives like sa@other-myproj.iam....
Apply:
- - message: controlPlane service account must belong to the same project - rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.contains('@') - && self.workloadIdentity.serviceAccountsEmails.controlPlane.endsWith('@' - + self.project + '.iam.gserviceaccount.com') - - message: nodePool service account must belong to the same project - rule: self.workloadIdentity.serviceAccountsEmails.nodePool.contains('@') - && self.workloadIdentity.serviceAccountsEmails.nodePool.endsWith('@' - + self.project + '.iam.gserviceaccount.com') + - message: controlPlane service account must belong to the same project + rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.split("@", 2)[1] == self.project + ".iam.gserviceaccount.com" + - message: nodePool service account must belong to the same project + rule: self.workloadIdentity.serviceAccountsEmails.nodePool.split("@", 2)[1] == self.project + ".iam.gserviceaccount.com"
🧹 Nitpick comments (7)
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4892-4900: Simplify CEL checks for SA project match.The contains('@') guard is redundant; endsWith alone suffices and reduces noise.
- rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.contains('@') - && self.workloadIdentity.serviceAccountsEmails.controlPlane.endsWith('@' + self.project + '.iam.gserviceaccount.com') + rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.endsWith('@' + self.project + '.iam.gserviceaccount.com')Do the same for nodePool.
docs/content/reference/api.md (1)
6333-6341: Clarify when Service Account User is needed for NodePool GSA.If the VM’s service account differs from the controller’s GSA, note that the controller principal needs roles/iam.serviceAccountUser on the VM SA to attach it to instances. If identical and assumed via WIF, this can be omitted.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5926-5936: Tighten projectNumber maxLength to 19 digitsGCP project numbers are int64; a numeric string over 19 digits isn’t valid. Recommend maxLength: 19 (pattern remains ^[0-9]+$).
Apply:
- maxLength: 25 + maxLength: 19api/hypershift/v1beta1/gcp.go (2)
33-38: Inconsistent+requiredmarker withomitemptyjson tag onKeyfield.The
Keyfield is marked+requiredbut hasjson:"key,omitempty". For required fields, usingomitemptycan lead to the field being silently omitted during serialization if it's an empty string, which contradicts the required semantics.Consider removing
omitemptyfrom the json tag:- Key string `json:"key,omitempty"` + Key string `json:"key"`
169-176: Inconsistent+requiredwithomitemptyon required string fields.Similar to the
Keyfield,projectNumber,poolID, andproviderIDare all marked+requiredbut useomitemptyjson tags. This creates an inconsistency where required fields could be silently omitted during serialization.Consider using
omitzero(Go 1.24+) or removingomitemptyfor consistency with required semantics:- ProjectNumber string `json:"projectNumber,omitempty"` + ProjectNumber string `json:"projectNumber"`The same applies to
poolID(line 195) andproviderID(line 214).cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (2)
5385-5387: Soften immutability to field-level to preserve forward-compat.Freezing the entire object (
self == oldSelf) blocks adding future non-identity fields. Prefer freezing only.name.Apply:
- x-kubernetes-validations: - - message: Network is immutable - rule: self == oldSelf + x-kubernetes-validations: + - message: Network name is immutable + rule: self.name == oldSelf.name
5406-5408: Limit subnet immutability to.name.Same rationale as network: keep
.nameimmutable but allow future extra fields without forcing object equality.- x-kubernetes-validations: - - message: Private Service Connect subnet is immutable - rule: self == oldSelf + x-kubernetes-validations: + - message: Private Service Connect subnet name is immutable + rule: self.name == oldSelf.name
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
⛔ Files ignored due to path filters (14)
api/go.sumis excluded by!**/*.sumapi/vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!**/vendor/**api/vendor/k8s.io/utils/lru/lru.gois excluded by!**/vendor/**api/vendor/modules.txtis excluded by!**/vendor/**go.sumis excluded by!**/*.sumvendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_conditions.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.gois excluded by!vendor/**,!**/vendor/**vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/buffer/ring_growing.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/clock/testing/fake_clock.gois excluded by!vendor/**,!**/vendor/**vendor/k8s.io/utils/lru/lru.gois excluded by!vendor/**,!**/vendor/**vendor/modules.txtis excluded by!vendor/**,!**/vendor/**
📒 Files selected for processing (22)
api/go.mod(1 hunks)api/hypershift/v1beta1/gcp.go(3 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(2 hunks)docs/content/reference/api.md(5 hunks)go.mod(1 hunks)test/e2e/v2/tests/api_ux_validation_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- api/go.mod
- api/hypershift/v1beta1/hostedcluster_types.go
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
- go.mod
- client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
cmd/cluster/gcp/create.goclient/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yamlapi/hypershift/v1beta1/hostedcluster_conditions.gotest/e2e/v2/tests/api_ux_validation_test.gocmd/cluster/gcp/create_test.goapi/hypershift/v1beta1/zz_generated.deepcopy.goapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlclient/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/gcp.godocs/content/reference/api.mdcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlclient/applyconfiguration/utils.go
🧬 Code graph analysis (6)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (2)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmailsApplyConfiguration(22-25)api/hypershift/v1beta1/gcp.go (1)
GCPWorkloadIdentityConfig(161-223)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
api/hypershift/v1beta1/hosted_controlplane.go (1)
ConditionType(294-294)
test/e2e/v2/tests/api_ux_validation_test.go (2)
test/e2e/util/crd.go (1)
HasFieldInCRDSchema(15-38)api/hypershift/v1beta1/gcp.go (6)
GCPPlatformSpec(84-156)GCPNetworkConfig(67-79)GCPResourceReference(6-18)GCPWorkloadIdentityConfig(161-223)GCPServiceAccountsEmails(227-267)GCPResourceLabel(23-50)
cmd/cluster/gcp/create_test.go (1)
cmd/cluster/gcp/create.go (2)
RawCreateOptions(31-58)CreateOptions(127-130)
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-50)
api/hypershift/v1beta1/gcp.go (5)
test/e2e/util/external_oidc.go (1)
Key(289-292)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabel(29-31)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfig(31-33)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmails(29-31)
🪛 golangci-lint (2.5.0)
api/hypershift/v1beta1/gcp.go
[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn
(typecheck)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Red Hat Konflux / hypershift-cli-mce-211-on-pull-request
🔇 Additional comments (43)
api/hypershift/v1beta1/hostedcluster_conditions.go (1)
154-163: LGTM! Well-structured condition definitions.Both new GCP condition types follow established naming conventions and documentation patterns. The placement among other platform-specific validation conditions is logical, and the comments clearly explain when these conditions would fail and the expected remediation approach.
cmd/cluster/gcp/create_test.go (3)
30-59: LGTM! Comprehensive test coverage for new GCP fields.The test properly initializes all new GCP-related fields and verifies their propagation through nested structures (NetworkConfig, WorkloadIdentity, ServiceAccountsEmails). Test data follows valid GCP naming conventions.
65-116: LGTM! Good refactoring and valuable new test case.The refactoring to use a
validOptsbase improves readability and maintainability by eliminating duplication across test cases. The new "missing network" test case (lines 92-96) properly validates that network is now a required field.
139-145: LGTM! CLI flags properly integrated.The new flags for GCP fields are correctly added to the minimal rendering test, ensuring the CLI can parse and use these fields. Flag values are consistent with test data used elsewhere.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (6)
4634-4649: Network name regex and immutability look solid.Pattern matches GCP resource naming and immutability is correctly enforced.
4655-4670: PSC subnet name validation is correct.Regex and immutability align with GCP requirements.
4676-4689: GCP project ID validation: LGTM.Length/pattern and immutability match GCP guidelines.
4691-4705: Region format check: good coverage.Regex blocks zones and enforces one hyphen + trailing digits; immutability set.
4706-4755: Labels: regexes and reserved prefix block are correct; list‑map avoids dup keys.This is SSA‑friendly and matches GCE label constraints.
4786-4790: WIF IDs and immutability: good constraints.Reserved prefix checks for pool/provider and top‑level immutability read well.
Also applies to: 4821-4825, 4882-4884
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (8)
4742-4758: LGTM: network name validation + immutability guard are correct.Pattern matches GCP resource naming and immutability is enforced.
4764-4778: LGTM: PSC subnet name validation + immutability guard are correct.Consistent with GCP naming rules; immutable as expected.
4793-4793: LGTM: project ID regex matches GCP constraints.Start letter, [a-z0-9-], 6–30 chars, no trailing hyphen.
4801-4809: LGTM: region validation.Regex and docs text accept current region formats like us-central1, europe-west12, northamerica-northeast1.
4877-4897: LGTM: poolID rules + reserved “gcp-” check and immutability.Regex bounds are sound; CEL guard blocks reserved prefix and mutations.
4926-4933: LGTM: providerID rules + reserved “gcp-” check and immutability.Symmetric to poolID; looks good.
4997-4997: LGTM: workloadIdentity required under GCP (feature-gated CRD).Acceptable since this CRD is gated; no upgrade risk for GA paths.
5000-5008: LGTM: CEL domain check for GSA emails.Using contains() + endsWith() avoids split()/indexing pitfalls and handles malformed input safely.
cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml (1)
42-53: LGTM! Test fixture correctly demonstrates the new WIF API.The workload identity configuration is properly structured with valid test data. Service account emails correctly reference the project ID, and all field formats align with GCP conventions.
client/applyconfiguration/utils.go (1)
176-183: LGTM! Generated code properly extends ForKind for new GCP WIF types.The three new cases for
GCPResourceLabel,GCPServiceAccountsEmails, andGCPWorkloadIdentityConfigfollow the existing pattern and are correctly placed within the hypershift v1beta1 group.client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
20-47: Generated apply-configuration for GCPResourceLabel looks correctStruct fields and fluent setters are consistent with the corresponding API type and applyconfiguration patterns; nothing to fix here.
cmd/cluster/gcp/create.go (1)
18-58: GCP create options and WIF wiring into HostedCluster look consistentThe new raw options, flag bindings, required-field validation, and
ApplyPlatformSpecificsmapping toGCPPlatformSpec.NetworkConfigandGCPWorkloadIdentityConfig(includingServiceAccountsEmails) align with the API definitions and the WIF‑only design for GCP. No issues from a correctness or maintainability standpoint.Also applies to: 60-71, 84-113, 175-201
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
20-65: Apply-configuration for GCPWorkloadIdentityConfig matches API shapeField set and fluent
With*builders correctly mirrorGCPWorkloadIdentityConfigand its nestedGCPServiceAccountsEmailsapplyconfig, enabling predictable declarative usage.api/hypershift/v1beta1/zz_generated.deepcopy.go (1)
1485-1496: New GCP deepcopy implementations correctly handle ResourceLabels and WorkloadIdentity
GCPResourceLabel.DeepCopyIntosafely duplicates the optionalValue *string.GCPPlatformSpec.DeepCopyIntonow deep-copies theResourceLabelsslice and includesWorkloadIdentity.PlatformSpec.DeepCopyIntodelegates toGCPPlatformSpec.DeepCopyIntofor the GCP branch.Given the current field shapes (all value types except the label value pointer), this avoids aliasing issues and matches how other platform structs are deep-copied.
Also applies to: 1614-1678, 3401-3442
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (3)
5841-5890: Labels map semantics look solidUsing x-kubernetes-list-type: map with x-kubernetes-list-map-keys: ["key"] prevents duplicate keys; regex/lengths align with your RFC1035 intent. No issues.
5968-6006: Service account email minLength is correctminLength: 38 matches the minimum possible: 6 (sa) + 1 ('@') + 6 (project) + 25 (".iam.gserviceaccount.com") = 38. Regex also enforces structure. LGTM.
6024-6024: Confirm gating of required workloadIdentity across CRDsSince workloadIdentity is required here by design, verify it's only required in the gated manifests and not in GA CRDs by checking all hostedclusters CRD variants (CustomNoUpgrade, CustomUpgrade, GA versions).
api/hypershift/v1beta1/gcp.go (4)
6-18: LGTM!The
GCPResourceReferencetype has well-documented naming constraints that align with GCP resource naming standards. The pattern and length validations are consistent.
66-79: LGTM!The immutability validations on
NetworkandPrivateServiceConnectSubnetare correctly implemented using CEL rules.
81-84: Good fix for the CEL validation rules.The XValidation rules now use
contains('@')andendsWith()instead of the previously flagged invalidsplit('@', 2)syntax. This approach is simpler and correctly validates that service account emails belong to the configured project.
127-156: Well-structured WIF configuration with comprehensive validation.The
resourceLabelsandworkloadIdentityadditions follow good practices:
resourceLabelsuses+listType=mapwith+listMapKey=keyfor proper map semanticsMaxItems=60leaves headroom for system labels (64 total GCP limit)omitzeroon struct types (workloadIdentity,serviceAccountsEmails) is the correct serialization choice- Immutability enforcement is consistent across all WIF-related fields
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (6)
5372-5381: GCP network name regex is correct.Matches GCE naming rules (lowercase, digits, hyphens; start with letter; end with letter/digit; ≤63 chars). LGTM.
5393-5402: GCP PSC subnet name regex is correct.Consistent with GCE naming requirements. LGTM.
5414-5427: Project ID validation looks good.Length (6–30), charset, start/end rules, and immutability are correct. LGTM.
5431-5440: Region validation is sane and matches current GCP regions.Pattern enforces two segments and digit suffix (e.g., us-central1, europe-west12, northamerica-northeast1). LGTM.
5445-5493: resourceLabels: solid schema, headroom preserved.
- list-map semantics keyed by
keyensure uniqueness.maxItems: 60leaves space for system labels.- Key/value patterns + reserved 'goog' prefix block are correct.
LGTM.
5494-5622: Top-level immutability may serve a purpose beyond field-level validation; verification needed.The review suggests removing object-level
self == oldSelfas redundant, but this overlooks a key distinction: field-level immutability protects only currently-defined fields. Removing the object-level rule would allow future optional fields to be added to an already-deployed configuration, potentially bypassing immutability for new fields. For a security-critical feature like Workload Identity Federation, the conservative dual-layer approach (both field-level and object-level immutability) may be intentional. Verify whether this design aligns with project conventions and whether parity exists across all CRD variants before removing the top-level constraint.cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (3)
5480-5496: LGTM on GCP naming and immutability rules.Network/subnet name patterns, project ID regex, and region validation look correct and align with GCP constraints.
Also applies to: 5501-5516, 5531-5535, 5539-5548
5738-5746: Cross-field project ownership check for SA emails — good.The endsWith('@{project}.iam.gserviceaccount.com') validations are a clear, low-cost guardrail.
5632-5635: The "gcp-" prefix restriction is correct and mandated by Google.The validation rule blocking pool IDs starting with "gcp-" aligns with official GCP requirements. Per Google's IAM API reference and gcloud documentation, the "gcp-" prefix is reserved by Google for both Workload Identity Federation pool IDs and provider IDs. This restriction is not a false negative; it prevents users from creating pools/providers that would fail in GCP due to official naming constraints.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (3)
5661-5670: LGTM on GCP network/subnet naming, immutability, and project ID pattern.Patterns align with GCP naming (start letter, lowercase/digits/hyphen, no trailing hyphen) and immutability is appropriate.
Also applies to: 5674-5676, 5682-5691, 5695-5697, 5712-5716
5805-5816: LGTM on poolID/providerID patterns (must start with a letter).Good fix to enforce leading letter and immutability.
Also applies to: 5841-5852
5721-5729: Region regex rejects valid GCP regions (e.g., northamerica-northeast1).Current pattern doesn’t allow hyphens inside the location segment. Allow hyphenated locations and still require trailing digits.
Apply:
- pattern: ^[a-z]+-[a-z]+[0-9]+$ + pattern: ^[a-z]+-[a-z]+(?:-[a-z]+)*[0-9]+$Optionally clarify the description that the location segment may include hyphens (e.g., “northamerica-northeast1”).
Likely an incorrect or invalid review comment.
Add comprehensive GCP Workload Identity Federation (WIF) support for secure, short-lived token-based authentication without storing long-term service account keys. API Changes: - GCPWorkloadIdentityConfig: Core WIF configuration with immutable fields - GCPServiceAccountsEmails: Service account mappings for different controllers - GCPResourceReference: GCP resource naming patterns with validation - GCPResourceLabel: GCP resource labeling with reserved prefix protection - Enhanced GCPPlatformSpec with workloadIdentity and resourceLabels fields Client Changes: - Apply configuration builders for all new WIF types - Fluent builder methods for programmatic resource creation - Server-side apply support for GCP platform resources CLI Changes: - WIF flags: --wif-pool-id, --wif-provider-id, --wif-project-number - Service account email flags for control plane and node pool - Integration with existing GCP cluster creation workflow - Updated test fixtures and validation coverage Features: - Immutable WIF configuration to prevent breaking auth chains - Comprehensive validation patterns for GCP naming conventions - Cross-validation ensuring service accounts belong to the same project - Support for resource labeling with GCP-specific constraints This enables secure cluster provisioning on GCP using modern identity federation instead of long-lived service account keys. Signed-off-by: Amador Pahim <apahim@redhat.com> Commit-Message-Assisted-by: Claude (via Claude Code) Signed-off-by: Amador Pahim <apahim@redhat.com>
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (14)
api/hypershift/v1beta1/gcp.go (2)
242-244: MinLength should be 37 to match the pattern's minimum.The regex pattern
^[a-z][a-z0-9-]{4,28}[a-z0-9]@[a-z][a-z0-9-]{4,28}[a-z0-9]\.iam\.gserviceaccount\.com$enforces a minimum length of:
- Service account name: 6 chars (1 + 4 + 1)
@: 1 char- Project ID: 6 chars (1 + 4 + 1)
- Domain suffix: 24 chars
- Total: 37 chars
Setting
MinLength=38creates an off-by-one gap where valid 37-character emails matching the pattern (e.g.,aaaaaa@bbbbbb.iam.gserviceaccount.com) would be rejected by the length constraint.Apply this diff to align the validation:
-// +kubebuilder:validation:MinLength=38 +// +kubebuilder:validation:MinLength=37
262-264: MinLength should be 37 to match the pattern's minimum.Same issue as the NodePool field: the pattern enforces a 37-character minimum, but
MinLength=38creates an off-by-one inconsistency.Apply this diff:
-// +kubebuilder:validation:MinLength=38 +// +kubebuilder:validation:MinLength=37api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (1)
4846-4854: Label value regex excludes underscores; GCP allows them.GCP label values may contain lowercase letters, digits, underscores, and dashes (max 63 characters, empty allowed). The current pattern
^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$and description omit underscores and enforce incorrect start/end constraints.Update the pattern to include underscores and correct the description to match GCP requirements.
Proposed diff:
- Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, + and may contain only lowercase letters, digits, underscores (_), or hyphens (-). @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z][a-z0-9_-]{0,62}$cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (1)
5552-5600: Allow label values that start with a digit (GCP permits it).GCP label values may be empty or start with a letter or digit. Current pattern forces a leading letter, rejecting valid values like “2025”. Relax the value regex and description accordingly.
Apply this diff:
- description: |- - value is the value part of the label. A label value can have a maximum of 63 characters. - Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter, - contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. + description: |- + value is the value part of the label. A label value can have a maximum of 63 characters. + Empty values are allowed by GCP. If non-empty, it must start with a lowercase letter or digit, + contain only lowercase letters, digits, or hyphens, and end with a lowercase letter or digit. @@ - pattern: ^$|^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$ + pattern: ^$|^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$docs/content/reference/api.md (5)
6335-6343: Document least‑privilege note for nodePool/controlPlane GSAs (Service Account User vs WIF).If the controller attaches a distinct VM SA, it needs
roles/iam.serviceAccountUseron that VM SA; if using WIF impersonation with the same SA, call that out to avoid confusion.This GSA requires the following IAM roles: - roles/compute.instanceAdmin.v1 (Compute Instance Admin v1) - roles/compute.networkAdmin (Compute Network Admin) + - If a distinct VM service account is attached to instances, also grant + roles/iam.serviceAccountUser on that VM service account to the controller GSA. + When the controller GSA directly impersonates the same VM SA via + roles/iam.workloadIdentityUser, Service Account User is not additionally required.Also applies to: 6355-6363
6299-6304: Broken regex/pattern for GCP resource names (HTML anchor inlined).Replace the invalid anchor with a copy/paste‑able regex and clarify start/end constraints.
- Pattern: “^<a href="[-a-z0-9]*[a-z0-9]">a-z</a>?$” (max 63 chars), per GCP naming requirements. + Pattern: `^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` (max 63 chars), per GCP naming requirements.Tip: wrap the regex in backticks in the Go doc comment and regenerate to prevent linkification. As per coding guidelines, ...
6439-6447: “serviceAccountsEmails,omitzero” leak indicates wrong struct tag; fix Go tags and regenerate.Same tag issue as above; the field name includes “,omitzero”.
- <code>serviceAccountsEmails,omitzero</code> + <code>serviceAccountsEmails</code>Action: fix the struct tag in the Go type and run
make api-docs. As per coding guidelines, ...
6033-6046: “workloadIdentity,omitzero” leak indicates wrong struct tag; fix Go tags and regenerate.The field name renders with “,omitzero”, implying a bad json tag option in the API type (should be “omitempty”). Fix the Go source tags and re-run docs gen.
- <code>workloadIdentity,omitzero</code> + <code>workloadIdentity</code>Action: in api/hypershift/v1beta1 (GCP types), replace
json:"...,omitzero,omitempty"withjson:"...,omitempty"andmake api-docs. As per coding guidelines, ...
5976-5982: Fix GCP region rule (“exactly one hyphen” is wrong).Regions can contain multiple hyphens (e.g., northamerica-northeast1). Update the sentence accordingly.
- Must be in the form of <geographic-area>-<location><number> (e.g., us-central1, europe-west12). - Must contain exactly one hyphen separating the geographic area from the location. - Must end with one or more digits. + Must be one or more lowercase segments separated by hyphens and end with one or more digits + (e.g., us-central1, europe-west12, northamerica-northeast1). + Must not include a zone suffix (e.g., “-a”, “-b”).test/e2e/v2/tests/api_ux_validation_test.go (1)
343-672: Past issue resolved; test coverage is comprehensive.The
GCPResourceLabel.Valueinitializations flagged in the previous review have all been corrected to useptr.To()(lines 550-551, 578, 632, 645). The nil-value test case (line 605) correctly omits theValuefield.Test coverage for GCP WIF validation is thorough, including:
- Valid WIF configuration with all required fields
- Format validation (project number, pool/provider IDs, service account emails)
- Reserved prefix checks (
gcp-,goog)- Length constraints (poolID minimum 4 chars)
- Resource label limits (max 60 items)
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5926-5939: Tighten projectNumber maxLength to 19 digits.maxLength: 25 is overly permissive. GCP project numbers are stored as int64 (automatically generated, read-only values), which limits them to a maximum value of 9,223,372,036,854,775,807—exactly 19 decimal digits. Reduce maxLength from 25 to 19 to align with the actual constraint.
- maxLength: 25 + maxLength: 19cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (1)
5584-5584: Fix off-by-one: service account email minLength should be 37 (not 38).Shortest valid GSA email (6+1+6+24) is 37 chars; 38 rejects valid inputs. Update both controlPlane and nodePool.
- minLength: 38 + minLength: 37 ... - minLength: 38 + minLength: 37Also applies to: 5604-5604
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (1)
4846-4847: GSA email minLength off by one (rejects valid 6‑char IDs).Minimal valid is 37 chars: 6 + 1 + 6 + 24. Current minLength 38 will reject edge‑valid emails.
Apply this diff in both places (controlPlane and nodePool):
- minLength: 38 + minLength: 37Also applies to: 4866-4867
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (1)
5919-5927: Make project-domain check exact; endsWith() is spoofable.endsWith('@' + project + '.iam.gserviceaccount.com') can pass for wrong projects via suffix collisions. Compare the domain part exactly after '@'.
Apply:
- rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.contains('@') - && self.workloadIdentity.serviceAccountsEmails.controlPlane.endsWith('@' - + self.project + '.iam.gserviceaccount.com') + rule: self.workloadIdentity.serviceAccountsEmails.controlPlane.split("@", 2)[1] + == self.project + ".iam.gserviceaccount.com" - rule: self.workloadIdentity.serviceAccountsEmails.nodePool.contains('@') - && self.workloadIdentity.serviceAccountsEmails.nodePool.endsWith('@' - + self.project + '.iam.gserviceaccount.com') + rule: self.workloadIdentity.serviceAccountsEmails.nodePool.split("@", 2)[1] + == self.project + ".iam.gserviceaccount.com"
🧹 Nitpick comments (3)
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (1)
5841-5890: Reserved label prefix: keep stricter rule, add doc note for clarity.You intentionally ban any key starting with “goog” (stricter than GCP’s documented “goog-”). Keep it if desired, but add a short note to the Key field docs that this is intentionally stricter than GCP to avoid collisions. List‑map semantics for uniqueness look good.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml (2)
5733-5782: Confirm intentional restriction of GCP label syntax (no underscores, last char must be alnum).Current patterns disallow “_” and trailing “-”, which is stricter than typical GCP label rules. If this is product intent, fine; if not, consider allowing underscores and dropping the final-char requirement.
5779-5781: Prefer array + CEL uniqueness over list-type=map (to avoid SSA merge semantics).If list-map semantics are discouraged, replace list-type=map with an array and add a CEL rule to enforce unique keys.
Example:
- x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map + x-kubernetes-validations: + - message: resourceLabels keys must be unique + rule: self == null || self.all(l1, self.exists_one(l2, l1.key == l2.key))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (20)
api/hypershift/v1beta1/gcp.go(3 hunks)api/hypershift/v1beta1/hostedcluster_conditions.go(1 hunks)api/hypershift/v1beta1/hostedcluster_types.go(1 hunks)api/hypershift/v1beta1/zz_generated.deepcopy.go(4 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go(2 hunks)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go(1 hunks)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go(1 hunks)client/applyconfiguration/utils.go(1 hunks)cmd/cluster/gcp/create.go(4 hunks)cmd/cluster/gcp/create_test.go(3 hunks)cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml(1 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yaml(2 hunks)cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml(2 hunks)docs/content/reference/api.md(5 hunks)test/e2e/v2/tests/api_ux_validation_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go
- cmd/cluster/gcp/create_test.go
- client/applyconfiguration/hypershift/v1beta1/gcpplatformspec.go
- client/applyconfiguration/utils.go
- api/hypershift/v1beta1/hostedcluster_conditions.go
- api/hypershift/v1beta1/zz_generated.deepcopy.go
- cmd/cluster/gcp/testdata/zz_fixture_TestCreateCluster_minimal_flags_necessary_to_render.yaml
🧰 Additional context used
📓 Path-based instructions (1)
**
⚙️ CodeRabbit configuration file
-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.
Files:
api/hypershift/v1beta1/hostedcluster_types.goclient/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.goclient/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yamlcmd/cluster/gcp/create.goapi/hypershift/v1beta1/gcp.gocmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yamlcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yamlapi/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yamldocs/content/reference/api.mdcmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-CustomNoUpgrade.crd.yamltest/e2e/v2/tests/api_ux_validation_test.go
🧬 Code graph analysis (3)
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
api/hypershift/v1beta1/gcp.go (1)
GCPResourceLabel(23-50)
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (2)
client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmailsApplyConfiguration(22-25)api/hypershift/v1beta1/gcp.go (1)
GCPWorkloadIdentityConfig(161-223)
api/hypershift/v1beta1/gcp.go (5)
test/e2e/util/external_oidc.go (1)
Key(289-292)client/applyconfiguration/hypershift/v1beta1/gcpresourcereference.go (1)
GCPResourceReference(28-30)client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
GCPResourceLabel(29-31)client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
GCPWorkloadIdentityConfig(31-33)client/applyconfiguration/hypershift/v1beta1/gcpserviceaccountsemails.go (1)
GCPServiceAccountsEmails(29-31)
🪛 golangci-lint (2.5.0)
api/hypershift/v1beta1/gcp.go
[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn
(typecheck)
🔇 Additional comments (44)
client/applyconfiguration/hypershift/v1beta1/gcpresourcelabel.go (1)
1-47: LGTM! Generated apply-configuration code is correct.The generated apply-configuration type correctly mirrors the GCPResourceLabel API type with appropriate builder methods for declarative configuration.
client/applyconfiguration/hypershift/v1beta1/gcpworkloadidentityconfig.go (1)
1-65: LGTM! Generated apply-configuration code is correct.The generated apply-configuration type correctly mirrors the GCPWorkloadIdentityConfig API type with appropriate builder methods and nested ServiceAccountsEmails configuration.
cmd/cluster/gcp/create.go (4)
18-28: LGTM! Flag constants are well-defined.The new flag constants follow the existing naming convention and cover all required GCP WIF and network configuration fields.
38-70: LGTM! Options and flag bindings are well-structured.The new fields are well-documented, and the help text appropriately references the
hypershift infra create gcpcommand as the source for WIF configuration values.
93-113: LGTM! Validation correctly enforces WIF requirements.All WorkloadIdentity and network fields are validated as required, which aligns with the design decision to support WIF-only authentication for the initial GCP implementation.
181-197: LGTM! Platform-specific configuration is correctly applied.The new GCP fields are properly populated into the HostedCluster spec, with correct mapping from CLI options to NetworkConfig and WorkloadIdentity API structures.
api/hypershift/v1beta1/gcp.go (5)
7-17: LGTM! GCP resource naming pattern is correct.The updated pattern correctly enforces GCP resource naming requirements: start with lowercase letter, end with lowercase letter or digit, max 63 characters.
20-50: LGTM! GCPResourceLabel validation is comprehensive.The type correctly implements GCP Compute Engine label requirements with proper RFC1035 validation, reserved prefix blocking, and support for optional empty values.
66-79: LGTM! Network immutability is properly enforced.The XValidation rules correctly prevent modification of network configuration after cluster creation, which is appropriate for these infrastructure fields.
81-156: LGTM! GCPPlatformSpec extensions are well-designed.The new ResourceLabels and WorkloadIdentity fields are properly validated with:
- Cross-field CEL validation ensuring service accounts belong to the correct project
- Appropriate list constraints and immutability rules
- Comprehensive documentation referencing GCP standards
158-223: LGTM! WorkloadIdentity configuration is comprehensive.The WIF configuration type includes:
- Proper validation of GCP-specific identifiers (project number, pool ID, provider ID)
- Reserved prefix blocking for 'gcp-' prefixes
- Immutability enforcement to prevent breaking auth chains
- Extensive documentation with prerequisites and references to infra commands
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml (2)
4801-4810: Region regex looks good.Pattern and description align with current GCP region naming (one hyphen; ends with digits), e.g., us-central1, europe-west12, northamerica-northeast1.
5000-5008: CEL split fix + domain check LGTM.Using contains('@') and endsWith(...) avoids split/TDZ pitfalls and guards malformed emails.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-TechPreviewNoUpgrade.crd.yaml (7)
5480-5489: GCP network name validation looks correct and immutable.Pattern matches GCE standards and immutability rule is appropriate.
Also applies to: 5493-5495
5501-5510: PSC subnet name validation and immutability look good.Matches GCE naming; immutability avoids day‑2 drift.
Also applies to: 5514-5516
5523-5535: Project ID validation: solid.Length, charset, and edge constraints align with GCP guidance; immutability is right.
5539-5548: Region format validation LGTM.The pattern accepts current GCP regions and blocks zones; immutability is appropriate.
Also applies to: 5550-5551
5680-5717: WIF SA email regex + immutability + project match checks look right.Patterns, min lengths, and cross‑field validations enforce correct tenancy and prevent day‑2 drift.
Also applies to: 5723-5730
5738-5746: Cross‑field validation for SA domain matches project is correct.EndsWith check enforces project consistency for both controlPlane and nodePool GSAs.
5629-5635: The validation rule correctly prevents IDs from using the 'gcp-' prefix. Google Cloud's official documentation explicitly reserves this prefix for Workload Identity Federation pool and provider IDs, making the check necessary and appropriate.api/hypershift/v1beta1/hostedcluster_types.go (1)
133-135: GCP CAPI provider image annotation is consistent with existing patternsThe new
ClusterAPIGCPProviderImageconstant follows the established naming, documentation, and annotation-key patterns used for other CAPI provider image overrides (AWS, Azure, KubeVirt, Agent, PowerVS, OpenStack). No issues from a maintainability or API-shape perspective.docs/content/reference/api.md (1)
5062-5072: LGTM on new GCP condition types.The additions for ValidGCPCredentials and ValidGCPWorkloadIdentity read clearly and match the feature intent.
test/e2e/v2/tests/api_ux_validation_test.go (1)
1949-1981: LGTM: Clean test helper pattern.The double-delete pattern (explicit + deferred) is appropriate for validation tests that only check API acceptance/rejection. The comment at line 1961 clearly explains the rationale.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-CustomNoUpgrade.crd.yaml (7)
5769-5785: LGTM: GCP network and PSC subnet naming + immutability are correct.Patterns match GCP constraints and day‑2 immutability is appropriate.
Also applies to: 5791-5805
5812-5824: LGTM: GCP project ID validation.Pattern prevents trailing hyphen and enforces 6–30 chars as intended; immutability OK.
5826-5840: LGTM: Region format validation.Pattern covers examples like us-central1, europe-west12, northamerica-northeast1; immutability OK.
5904-5960: LGTM: Pool/Provider IDs validation and reserved “gcp-” prefix.Patterns/lengths align with IAM WIF rules; reserved-prefix block is correct; immutability OK.
5967-6007: LGTM: Service account email regex and minLength.Regex is hardened; minLength: 38 matches the true minimum (6 + 1 + 6 + len(".iam.gserviceaccount.com")=25).
6027-6035: LGTM: Cross-field checks for SA emails vs project.CEL ensures both GSAs belong to the same project as spec.gcp.project.
6024-6024: Verify workloadIdentity gating in non-gated CRDs.The concern is valid: workloadIdentity should only be required in gated CRDs (CustomNoUpgrade/TechPreviewNoUpgrade). Confirm that non-gated hostedclusters CRDs do not enforce workloadIdentity in their required fields, as HyperShift's feature-gate mechanism should prevent new gated fields from appearing in base CRD schemas.
cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-TechPreviewNoUpgrade.crd.yaml (6)
5372-5388: LGTM: GCP network and PSC subnet name validation + immutability.Regex matches GCP Compute naming rules; immutability guard is appropriate.
Also applies to: 5393-5409
5414-5427: LGTM: GCP project ID constraints.Length, charset, and start/end constraints align with GCP rules.
5429-5443: LGTM: Region validation.Pattern accepts current regions (e.g., us-central1, europe-west12, northamerica-northeast1) and rejects zones. Immutability is correct.
5445-5493: LGTM: Resource labels schema.RFC1035-style key/value, reserved 'goog' prefix block, map semantics for uniqueness, and 60-item cap for headroom look good.
5494-5622: LGTM: Workload Identity Federation block.Reserved-prefix checks, per-field patterns, and immutability on pool/provider/projectNumber and emails are sound.
5630-5638: LGTM: Cross-field SA domain verification.CEL ensures GSAs belong to the configured project.
api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml (8)
4634-4643: GCP network name validation: LGTM.Pattern/length + immutability match GCE rules.
Also applies to: 4647-4649
4655-4663: GCP subnet name validation: LGTM.Consistent with GCE naming and made immutable.
Also applies to: 4668-4670
4676-4689: Project ID regex: LGTM.6–30 chars, starts with letter, no trailing hyphen; immutability set.
4693-4705: Region format validation: LGTM.Regex/description appropriately constrain regions (no zones), immutable.
4706-4755: Resource labels schema/regex: LGTM.
- Keys/values align with GCE label rules.
- Reserved 'goog' prefix blocked.
- list‑map by key avoids duplicates.
4756-4885: WIF field validations: LGTM (pool/provider/projectNumber immutability, reserved prefixes, SA patterns).Solid constraints and immutability. Fix the GSA minLength noted separately.
Please confirm there aren’t other CRD variants (non‑featuregated) where minLength still reads 38 to keep schemas consistent.
4886-4889: Making workloadIdentity required — verify backcompat.This can block spec updates for existing GCP clusters without WIF populated. If intentional, OK; otherwise consider making it optional with controller defaults/migration notes.
4891-4900: CEL cross‑field checks for SA project match: LGTM.Simple, effective guard against misconfigurations.
|
/lgtm |
|
/verified later @apahim |
|
@patjlm: This PR has been marked to be verified later by DetailsIn response to this:
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. |
|
/hold cancel |
|
/retest-required |
|
/retest |
|
/label acknowledge-critical-fixes-only |
|
/retest |
|
@apahim: all tests passed! Full PR test history. Your PR dashboard. DetailsInstructions 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. |
What this PR does / why we need it:
This PR introduces Workload Identity Federation (WIF) API types for the GCP platform in HyperShift. These changes lay the foundation for secure, keyless
authentication between hosted control planes and GCP services.
The PR adds:
GCP Workload Identity Federation API Types (
feat(api)):GCPWorkloadIdentityConfig: Core structure for WIF configuration including service account references and project metadataGCPResourceLabel: RFC1035-compliant labels for Compute Engine resourcesValidWorkloadIdentityConfigurationfor platform validationClient Apply Configurations (
feat(client)):GCPPlatformSpec,GCPResourceLabel,GCPServiceAccountsRef, andGCPWorkloadIdentityConfigAll changes include:
Which issue(s) this PR fixes:
Fixes GCP-231
Special notes for your reviewer:
GCPWorkloadIdentityConfigstructure is designed to support both user-provided and HyperShift-managed service accountsChecklist: