Skip to content

OCPSTRAT-2336: Adjust karpenter API to OpenShift conventions#7952

Merged
enxebre merged 3 commits intoopenshift:mainfrom
enxebre:adjust-karpenter-api-to-ocp-convention
Mar 18, 2026
Merged

OCPSTRAT-2336: Adjust karpenter API to OpenShift conventions#7952
enxebre merged 3 commits intoopenshift:mainfrom
enxebre:adjust-karpenter-api-to-ocp-convention

Conversation

@enxebre
Copy link
Member

@enxebre enxebre commented Mar 13, 2026

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Introduced explicit enum-style options for public IP assignment, detailed monitoring, encryption, delete-on-termination and root-volume designation; reworked block device/volume config and strengthened validations (lengths, enums, min/max items/properties) for EC2 node classes, subnets and security group selectors; adjusted NodeClass spec/status/metadata presence and omission semantics.
  • Tests
    • Updated test fixtures and assertions to use new enum values and revised field shapes.

@openshift-ci-robot
Copy link

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

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

openshift-ci-robot commented Mar 13, 2026

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Review skipped — only excluded labels are configured. (1)
  • do-not-merge/work-in-progress

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: bd498955-c29f-4cdc-bad1-6de4efd05a12

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds five enum-like public types (PublicIPAddressAssignment, DetailedMonitoringState, RootVolumeDesignation, DeleteOnTerminationPolicy, EncryptionState), replaces several pointer/bool fields with these enums, tightens validations (MinProperties/MinItems/MinLength/MaxLength/Enum) across Subnet, SecurityGroup, BlockDeviceMapping, selector terms, and OpenshiftEC2NodeClass APIs, and updates conversions and spec accessors (deleteOnTerminationToBool, encryptionStateToBool, ptrIfNonEmpty, KarpenterAssociatePublicIPAddress, KarpenterDetailedMonitoring, KarpenterBlockDeviceMapping). Controllers now call the new accessors when reconciling Karpenter EC2NodeClass resources.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant OS as OpenshiftEC2NodeClass
participant C as Controller
participant U as util (conversion helpers)
participant K as Karpenter EC2NodeClass
OS->>C: CR created/updated (enum fields, selectors, block devices)
C->>U: call KarpenterAssociatePublicIPAddress(), KarpenterDetailedMonitoring(), KarpenterBlockDeviceMapping()
U-->>C: return converted pointers/values (ptrIfNonEmpty, deleteOnTerminationToBool, encryptionStateToBool)
C->>K: reconcile/create EC2NodeClass with converted spec
K-->>C: status/update confirmation


Important

Pre-merge checks failed

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

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ⚠️ Warning Out of 17 assertions in the test file, only 1 includes a meaningful failure message, violating the explicit requirement that all assertions must have diagnostic messages. Add descriptive failure messages to all 16 assertions lacking them, such as changing g.Expect(err).ToNot(HaveOccurred()) to include context about what operation failed.
Stable And Deterministic Test Names ❓ Inconclusive Test file karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go mentioned in PR summary could not be located in repository despite comprehensive file searches. Verify test file location or confirm whether this PR contains Ginkgo test modifications requiring stability assessment.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main objective: adjusting the Karpenter API to conform to OpenShift conventions, which aligns with the significant refactoring of pointer/bool fields to enum types across multiple files.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

@openshift-ci openshift-ci bot requested review from devguyio and sjenning March 13, 2026 09:27
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 13, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: enxebre

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

The pull request process is described here

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

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

@openshift-ci openshift-ci bot added area/api Indicates the PR includes changes for the API approved Indicates a PR has been approved by an approver from all required OWNERS files. area/karpenter-operator Indicates the PR includes changes related to the Karpenter operator and removed do-not-merge/needs-area labels Mar 13, 2026
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
  • Redesigned AWS node configuration to use explicit enum types (public IP assignment, detailed monitoring, encryption, termination policies, root volume designation) instead of boolean flags.
  • Strengthened validation constraints on node configuration fields and OpenShift EC2 NodeClass specifications for improved type safety and consistency.

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

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

  • Replaced several boolean fields with explicit enum-style types (public IP assignment, detailed monitoring, encryption, delete-on-termination, root volume).

  • Reworked block device and volume fields and strengthened validations (lengths, enums, min/max items/properties) across EC2 node class and selectors.

  • Spec/Status metadata semantics updated for OpenShift EC2 NodeClass.

  • Tests

  • Updated tests to use new enum values and revised field shapes.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
api/karpenter/v1beta1/karpenter_types.go (3)

428-430: Inconsistency: +required Spec field with omitzero tag.

The Spec field is marked +required but uses omitzero, which will omit zero-value structs during serialization. This could cause the field to be absent in serialized output even though it's required. Since OpenshiftEC2NodeClassSpec has MinProperties=1, validation will fail on empty specs anyway, but the serialization behavior may not match the required semantics.

Consider using just json:"spec" without omitzero for required fields.

♻️ Proposed fix
 	// spec defines the desired state of the OpenshiftEC2NodeClass.
 	// +required
-	Spec OpenshiftEC2NodeClassSpec `json:"spec,omitzero"`
+	Spec OpenshiftEC2NodeClassSpec `json:"spec"`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 428 - 430, The Spec
field on the OpenshiftEC2NodeClass struct is marked +required but uses
json:"spec,omitzero", which can omit a zero-value Spec during serialization;
update the struct tag for Spec (the Spec OpenshiftEC2NodeClassSpec field) to
remove omitzero (use json:"spec") so the required semantics match serialization
while keeping the +required marker and existing OpenshiftEC2NodeClassSpec
type/validation.

135-139: Same inconsistency: +required with omitempty on ID field.

Same issue as Subnet - consider removing omitempty for the required ID field to maintain consistency with the +required marker.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 135 - 139, The ID
field has a +required marker but is declared with json:"id,omitempty", causing
inconsistency; update the struct tag for the ID field in karpenter_types.go (the
ID string `json` tag) to remove "omitempty" so it matches the +required
validation, i.e., change `json:"id,omitempty"` to `json:"id"` to enforce
presence in marshaled output.

116-125: Inconsistency between +required marker and omitempty JSON tag.

Fields ID (line 120) and Zone (line 125) are marked +required but have omitempty in their JSON tags. While MinLength=1 provides runtime validation, the omitempty tag will omit these fields during serialization when empty, which contradicts the +required semantics. Consider removing omitempty for required fields to ensure proper OpenAPI schema generation.

♻️ Proposed fix
 type Subnet struct {
 	// id is the ID of the subnet.
 	// +required
 	// +kubebuilder:validation:MinLength=1
 	// +kubebuilder:validation:MaxLength=256
-	ID string `json:"id,omitempty"`
+	ID string `json:"id"`
 	// zone is the associated availability zone.
 	// +required
 	// +kubebuilder:validation:MinLength=1
 	// +kubebuilder:validation:MaxLength=256
-	Zone string `json:"zone,omitempty"`
+	Zone string `json:"zone"`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 116 - 125, The struct
fields ID and Zone are annotated with +required and MinLength validations but
their JSON tags use `omitempty`, which contradicts required semantics; update
the JSON tags for the ID and Zone fields in karpenter_types.go to remove
`omitempty` so the fields are always serialized (ensuring OpenAPI/kubebuilder
generates them as required) while keeping the existing `+required` and
`+kubebuilder:validation:MinLength=1`/MaxLength attributes intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/karpenter/v1beta1/karpenter_types.go`:
- Around line 428-430: The Spec field on the OpenshiftEC2NodeClass struct is
marked +required but uses json:"spec,omitzero", which can omit a zero-value Spec
during serialization; update the struct tag for Spec (the Spec
OpenshiftEC2NodeClassSpec field) to remove omitzero (use json:"spec") so the
required semantics match serialization while keeping the +required marker and
existing OpenshiftEC2NodeClassSpec type/validation.
- Around line 135-139: The ID field has a +required marker but is declared with
json:"id,omitempty", causing inconsistency; update the struct tag for the ID
field in karpenter_types.go (the ID string `json` tag) to remove "omitempty" so
it matches the +required validation, i.e., change `json:"id,omitempty"` to
`json:"id"` to enforce presence in marshaled output.
- Around line 116-125: The struct fields ID and Zone are annotated with
+required and MinLength validations but their JSON tags use `omitempty`, which
contradicts required semantics; update the JSON tags for the ID and Zone fields
in karpenter_types.go to remove `omitempty` so the fields are always serialized
(ensuring OpenAPI/kubebuilder generates them as required) while keeping the
existing `+required` and `+kubebuilder:validation:MinLength=1`/MaxLength
attributes intact.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: 4e9b9bd5-9c5d-4e48-b6aa-4d1e2fc9bfc0

📥 Commits

Reviewing files that changed from the base of the PR and between ede14af and 556b8fa.

⛔ Files ignored due to path filters (1)
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/karpenter_types.go is excluded by !vendor/**, !**/vendor/**
📒 Files selected for processing (1)
  • api/karpenter/v1beta1/karpenter_types.go

@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch from 8a769c2 to f457c9e Compare March 13, 2026 10:36
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

  • Replaced several boolean fields with explicit enum-style options for public IP, detailed monitoring, encryption, delete-on-termination and root volume.

  • Reworked block device/volume configuration and strengthened validations (lengths, enums, min/max items/properties) for EC2 node class and selectors.

  • Adjusted NodeClass spec/status metadata semantics for clearer presence/omission behavior.

  • Tests

  • Updated tests to use new enum values and revised field shapes.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
api/karpenter/v1beta1/karpenter_types.go (1)

354-356: ⚠️ Potential issue | 🟠 Major

The volumeSize regex now accepts bare Ti and T.

The doubled || in the Ti and T branches creates an empty alternative, so unit-only values match this pattern.

Suggested change
-	// +kubebuilder:validation:Pattern:="^((?:[1-9][0-9]{0,3}|[1-4][0-9]{4}|[5][0-8][0-9]{3}|59000)Gi|(?:[1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-3][0-9]{3}|64000)G|([1-9]||[1-5][0-7]|58)Ti|([1-9]||[1-5][0-9]|6[0-3]|64)T)$"
+	// +kubebuilder:validation:Pattern:="^((?:[1-9][0-9]{0,3}|[1-4][0-9]{4}|[5][0-8][0-9]{3}|59000)Gi|(?:[1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-3][0-9]{3}|64000)G|([1-9]|[1-5][0-7]|58)Ti|([1-9]|[1-5][0-9]|6[0-3]|64)T)$"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 354 - 356, The
kubebuilder validation regex for the volumeSize field contains accidental empty
alternatives ("||") in the Ti and T branches which allows unit-only values; fix
the pattern in the kubebuilder:validation:Pattern string by removing the stray
empty alternatives so those groups read e.g. ([1-9]|[1-5][0-7]|58)Ti and
([1-9]|[1-5][0-9]|6[0-3]|64)T (update the existing
kubebuilder:validation:Pattern line that defines the volumeSize regex).
🧹 Nitpick comments (1)
karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go (1)

91-122: Use a schema-valid fixture in this test.

This case now builds a subnet term with both tags and id, a security-group term with both tags and name, and a subnet ID ("testID") that no longer matches the new subnet-... pattern. Because the unit test bypasses admission, it can still pass on an object the API server would reject. Split those into separate OR terms if you want to keep covering both selection modes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go`
around lines 91 - 122, The fixture is invalid because SubnetSelectorTerm and
SecurityGroupSelectorTerm are populated with both tags and an ID/Name and the
subnet ID "testID" doesn't match the expected "subnet-..." pattern; update the
OpenshiftEC2NodeClassSpec fixture so each selector term is schema-valid by
splitting selection modes into separate OR terms: for SubnetSelectorTerms create
one term with ID only using a valid ID like "subnet-abc123" and another term
with Tags only, and for SecurityGroupSelectorTerms create one term with Name
only ("testName") and another with Tags only; modify the SubnetSelectorTerm and
SecurityGroupSelectorTerm entries in the test fixture accordingly so no term
contains both tags and id/name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/karpenter/v1beta1/karpenter_types.go`:
- Around line 161-162: The MinProperties=1 validation on
OpenshiftEC2NodeClassSpec makes an empty spec object invalid even though the
controller function reconcileEC2NodeClass() expects and handles spec: {} by
applying defaults; remove the kubebuilder:validation:MinProperties=1 marker (or
replace it with a comment explaining defaults) from the
OpenshiftEC2NodeClassSpec type so OpenshiftEC2NodeClass.Spec can be empty and
reconcilers can populate defaults at runtime.
- Around line 164-166: The CEL for subnetSelectorTerms currently uses
"!self.all(x, has(x.id) && has(x.tags))" which still allows a list where one
term sets both id and tags; update the mutual-exclusion rule for
subnetSelectorTerms to assert every term does not contain both fields, e.g.
replace that rule with one that uses either "self.all(x, !(has(x.id) &&
has(x.tags)))" or "!self.any(x, has(x.id) && has(x.tags))" so no single term may
set both id and tags (update the kubebuilder XValidation rule associated with
subnetSelectorTerms accordingly).
- Around line 174-177: The XValidation exclusivity rules on
securityGroupSelectorTerms currently use "!self.all(...)" which only rejects
when every term is invalid; change both rules so they reject if any term
contains the forbidden combination. Replace the rule expressions in the two
lines that reference "!self.all(x, has(x.id) && (has(x.tags) || has(x.name)))"
and "!self.all(x, has(x.name) && (has(x.tags) || has(x.id)))" with either
"not(self.any(x, has(x.id) && (has(x.tags) || has(x.name))))" and
"not(self.any(x, has(x.name) && (has(x.tags) || has(x.id))))" or equivalently
"self.all(x, !(has(x.id) && (has(x.tags) || has(x.name))))" and "self.all(x,
!(has(x.name) && (has(x.tags) || has(x.id))))" so any single invalid term causes
validation to fail.

---

Outside diff comments:
In `@api/karpenter/v1beta1/karpenter_types.go`:
- Around line 354-356: The kubebuilder validation regex for the volumeSize field
contains accidental empty alternatives ("||") in the Ti and T branches which
allows unit-only values; fix the pattern in the kubebuilder:validation:Pattern
string by removing the stray empty alternatives so those groups read e.g.
([1-9]|[1-5][0-7]|58)Ti and ([1-9]|[1-5][0-9]|6[0-3]|64)T (update the existing
kubebuilder:validation:Pattern line that defines the volumeSize regex).

---

Nitpick comments:
In `@karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go`:
- Around line 91-122: The fixture is invalid because SubnetSelectorTerm and
SecurityGroupSelectorTerm are populated with both tags and an ID/Name and the
subnet ID "testID" doesn't match the expected "subnet-..." pattern; update the
OpenshiftEC2NodeClassSpec fixture so each selector term is schema-valid by
splitting selection modes into separate OR terms: for SubnetSelectorTerms create
one term with ID only using a valid ID like "subnet-abc123" and another term
with Tags only, and for SecurityGroupSelectorTerms create one term with Name
only ("testName") and another with Tags only; modify the SubnetSelectorTerm and
SecurityGroupSelectorTerm entries in the test fixture accordingly so no term
contains both tags and id/name.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: 2e7a8836-d367-4e39-83fc-abf73fd6c359

📥 Commits

Reviewing files that changed from the base of the PR and between 556b8fa and f457c9e.

⛔ Files ignored due to path filters (9)
  • api/karpenter/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • client/applyconfiguration/karpenter/v1beta1/blockdevice.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/blockdevicemapping.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/openshiftec2nodeclassspec.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/openshiftec2nodeclassstatus.go is excluded by !client/**
  • karpenter-operator/controllers/karpenter/assets/karpenter.hypershift.openshift.io_openshiftec2nodeclasses.yaml is excluded by !karpenter-operator/controllers/karpenter/assets/*.yaml
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/karpenter_types.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/util.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (4)
  • api/karpenter/v1beta1/karpenter_types.go
  • karpenter-operator/controllers/karpenter/karpenter_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • karpenter-operator/controllers/karpenter/karpenter_controller.go

Comment on lines +161 to 162
// +kubebuilder:validation:MinProperties=1
type OpenshiftEC2NodeClassSpec struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't turn the default-only spec into an invalid object.

OpenshiftEC2NodeClass.Spec is already required on the root type. Adding MinProperties=1 goes further and rejects spec: {}, even though reconcileEC2NodeClass() still supports that shape by filling in default selectors and the default root volume when fields are unset.

Suggested change
-// +kubebuilder:validation:MinProperties=1
 type OpenshiftEC2NodeClassSpec struct {
📝 Committable suggestion

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

Suggested change
// +kubebuilder:validation:MinProperties=1
type OpenshiftEC2NodeClassSpec struct {
type OpenshiftEC2NodeClassSpec struct {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 161 - 162, The
MinProperties=1 validation on OpenshiftEC2NodeClassSpec makes an empty spec
object invalid even though the controller function reconcileEC2NodeClass()
expects and handles spec: {} by applying defaults; remove the
kubebuilder:validation:MinProperties=1 marker (or replace it with a comment
explaining defaults) from the OpenshiftEC2NodeClassSpec type so
OpenshiftEC2NodeClass.Spec can be empty and reconcilers can populate defaults at
runtime.

Comment on lines 164 to 166
// +kubebuilder:validation:XValidation:message="subnetSelectorTerms cannot be empty",rule="self.size() != 0"
// +kubebuilder:validation:XValidation:message="expected at least one, got none, ['tags', 'id']",rule="self.all(x, has(x.tags) || has(x.id))"
// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in subnetSelectorTerms",rule="!self.all(x, has(x.id) && has(x.tags))"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This subnet-selector CEL only fails when every term is invalid.

!self.all(x, has(x.id) && has(x.tags)) lets a list through as soon as one other item is valid, so a single term can still set both id and tags and pass schema validation.

Suggested change
-// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in subnetSelectorTerms",rule="!self.all(x, has(x.id) && has(x.tags))"
+// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in subnetSelectorTerms",rule="self.all(x, !(has(x.id) && has(x.tags)))"
📝 Committable suggestion

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

Suggested change
// +kubebuilder:validation:XValidation:message="subnetSelectorTerms cannot be empty",rule="self.size() != 0"
// +kubebuilder:validation:XValidation:message="expected at least one, got none, ['tags', 'id']",rule="self.all(x, has(x.tags) || has(x.id))"
// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in subnetSelectorTerms",rule="!self.all(x, has(x.id) && has(x.tags))"
// +kubebuilder:validation:XValidation:message="subnetSelectorTerms cannot be empty",rule="self.size() != 0"
// +kubebuilder:validation:XValidation:message="expected at least one, got none, ['tags', 'id']",rule="self.all(x, has(x.tags) || has(x.id))"
// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in subnetSelectorTerms",rule="self.all(x, !(has(x.id) && has(x.tags)))"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 164 - 166, The CEL for
subnetSelectorTerms currently uses "!self.all(x, has(x.id) && has(x.tags))"
which still allows a list where one term sets both id and tags; update the
mutual-exclusion rule for subnetSelectorTerms to assert every term does not
contain both fields, e.g. replace that rule with one that uses either
"self.all(x, !(has(x.id) && has(x.tags)))" or "!self.any(x, has(x.id) &&
has(x.tags))" so no single term may set both id and tags (update the kubebuilder
XValidation rule associated with subnetSelectorTerms accordingly).

Comment on lines 174 to 177
// +kubebuilder:validation:XValidation:message="securityGroupSelectorTerms cannot be empty",rule="self.size() != 0"
// +kubebuilder:validation:XValidation:message="expected at least one, got none, ['tags', 'id', 'name']",rule="self.all(x, has(x.tags) || has(x.id) || has(x.name))"
// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",rule="!self.all(x, has(x.id) && (has(x.tags) || has(x.name)))"
// +kubebuilder:validation:XValidation:message="'name' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",rule="!self.all(x, has(x.name) && (has(x.tags) || has(x.id)))"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

These security-group exclusivity rules have the same !self.all(...) bug.

Both rules only reject the list when all entries are invalid. A mixed list can still include one term with id+tags or name+tags and pass validation.

Suggested change
-// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",rule="!self.all(x, has(x.id) && (has(x.tags) || has(x.name)))"
-// +kubebuilder:validation:XValidation:message="'name' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",rule="!self.all(x, has(x.name) && (has(x.tags) || has(x.id)))"
+// +kubebuilder:validation:XValidation:message="'id' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",rule="self.all(x, !(has(x.id) && (has(x.tags) || has(x.name))))"
+// +kubebuilder:validation:XValidation:message="'name' is mutually exclusive, cannot be set with a combination of other fields in securityGroupSelectorTerms",rule="self.all(x, !(has(x.name) && (has(x.tags) || has(x.id))))"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 174 - 177, The
XValidation exclusivity rules on securityGroupSelectorTerms currently use
"!self.all(...)" which only rejects when every term is invalid; change both
rules so they reject if any term contains the forbidden combination. Replace the
rule expressions in the two lines that reference "!self.all(x, has(x.id) &&
(has(x.tags) || has(x.name)))" and "!self.all(x, has(x.name) && (has(x.tags) ||
has(x.id)))" with either "not(self.any(x, has(x.id) && (has(x.tags) ||
has(x.name))))" and "not(self.any(x, has(x.name) && (has(x.tags) ||
has(x.id))))" or equivalently "self.all(x, !(has(x.id) && (has(x.tags) ||
has(x.name))))" and "self.all(x, !(has(x.name) && (has(x.tags) || has(x.id))))"
so any single invalid term causes validation to fail.

@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch from f457c9e to b72eff1 Compare March 13, 2026 11:00
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

  • Replaced several boolean fields with explicit enum-style options for public IP assignment, detailed monitoring, encryption, delete-on-termination and root-volume designation.

  • Reworked block device/volume configuration and strengthened validations (lengths, enums, min/max items/properties) for EC2 node class, subnets and security group selectors.

  • Adjusted NodeClass spec/status presence/omission semantics.

  • Tests

  • Updated tests to use new enum values and revised field shapes.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
api/karpenter/v1beta1/karpenter_types.go (1)

114-145: Minor inconsistency: +required markers with omitempty tags.

The id and zone fields are marked +required but use omitempty JSON tags. While this works because these structs appear in status fields that are always populated by the controller, the mixed semantics could cause confusion. Consider documenting that these are "required when present" rather than schema-required.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 114 - 145, The
+required kubebuilder markers on Subnet.ID and Subnet.Zone (and the +optional
markers on ZoneID and SecurityGroup.Name) conflict with their
json:"...,omitempty" tags and can be confusing; update the declarations for the
Subnet and SecurityGroup structs (symbols: Subnet, SecurityGroup, fields ID,
Zone, ZoneID, Name) by either removing the +required annotations or changing the
field comments to explicitly state "required when present / set by controller in
status" (i.e., document that these are not schema-required but are populated by
the controller), and ensure the kubebuilder markers and json tags are consistent
with that choice.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/karpenter/v1beta1/karpenter_types.go`:
- Around line 114-145: The +required kubebuilder markers on Subnet.ID and
Subnet.Zone (and the +optional markers on ZoneID and SecurityGroup.Name)
conflict with their json:"...,omitempty" tags and can be confusing; update the
declarations for the Subnet and SecurityGroup structs (symbols: Subnet,
SecurityGroup, fields ID, Zone, ZoneID, Name) by either removing the +required
annotations or changing the field comments to explicitly state "required when
present / set by controller in status" (i.e., document that these are not
schema-required but are populated by the controller), and ensure the kubebuilder
markers and json tags are consistent with that choice.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: b96520f4-7b34-4c96-ba0f-66a499d67e1a

📥 Commits

Reviewing files that changed from the base of the PR and between f457c9e and b72eff1.

⛔ Files ignored due to path filters (9)
  • api/karpenter/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • client/applyconfiguration/karpenter/v1beta1/blockdevice.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/blockdevicemapping.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/openshiftec2nodeclassspec.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/openshiftec2nodeclassstatus.go is excluded by !client/**
  • karpenter-operator/controllers/karpenter/assets/karpenter.hypershift.openshift.io_openshiftec2nodeclasses.yaml is excluded by !karpenter-operator/controllers/karpenter/assets/*.yaml
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/karpenter_types.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/util.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (5)
  • api/karpenter/v1beta1/karpenter_types.go
  • api/karpenter/v1beta1/util.go
  • karpenter-operator/controllers/karpenter/karpenter_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • api/karpenter/v1beta1/util.go
  • karpenter-operator/controllers/karpenter/karpenter_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go

@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch from b72eff1 to d5b46ab Compare March 13, 2026 11:26
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
  • Introduced explicit enum-style options for public IP assignment, detailed monitoring, encryption, delete-on-termination and root-volume designation; reworked block device/volume config and strengthened validations (lengths, enums, min/max items/properties) for EC2 node classes, subnets and security group selectors; adjusted NodeClass spec/status/metadata presence and omission semantics.
  • Tests
  • Updated test fixtures and assertions to use new enum values and revised field shapes.

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/karpenter/v1beta1/karpenter_types.go`:
- Around line 373-383: The kubebuilder marker `MinProperties=1` on the
OpenshiftEC2NodeClassStatus struct can reject valid initial/partial status
updates; remove (or comment out) the `//
+kubebuilder:validation:MinProperties=1` marker from the
OpenshiftEC2NodeClassStatus definition so the controller can create an
initially-empty status and later populate the Conditions field (which already
enforces MinItems=1); ensure only the Conditions slice retains its validation
and that status remains controller-managed.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: 3eb72468-2686-45ce-837b-95168dc793f1

📥 Commits

Reviewing files that changed from the base of the PR and between b72eff1 and d5b46ab.

⛔ Files ignored due to path filters (9)
  • api/karpenter/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • client/applyconfiguration/karpenter/v1beta1/blockdevice.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/blockdevicemapping.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/openshiftec2nodeclassspec.go is excluded by !client/**
  • client/applyconfiguration/karpenter/v1beta1/openshiftec2nodeclassstatus.go is excluded by !client/**
  • karpenter-operator/controllers/karpenter/assets/karpenter.hypershift.openshift.io_openshiftec2nodeclasses.yaml is excluded by !karpenter-operator/controllers/karpenter/assets/*.yaml
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/karpenter_types.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/util.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/karpenter/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (5)
  • api/karpenter/v1beta1/karpenter_types.go
  • api/karpenter/v1beta1/util.go
  • karpenter-operator/controllers/karpenter/karpenter_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller.go
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • karpenter-operator/controllers/nodeclass/ec2_nodeclass_controller.go
  • karpenter-operator/controllers/karpenter/karpenter_controller.go

Comment on lines +373 to +383
// +kubebuilder:validation:MinProperties=1
type OpenshiftEC2NodeClassStatus struct {
// Subnets contains the current Subnet values that are available to the
// conditions contain signals for health and readiness.
// +optional
// +listType=map
// +listMapKey=type
// +patchMergeKey=type
// +patchStrategy=merge
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=100
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

MinProperties=1 on status may reject valid intermediate states.

When an OpenshiftEC2NodeClass is first created, its status will be empty until the controller reconciles it. The MinProperties=1 constraint could reject valid status updates if the controller tries to set status with only conditions (which itself has MinItems=1), potentially causing issues during the initial reconciliation cycle.

Consider whether this constraint is necessary given that status is always controller-managed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/karpenter/v1beta1/karpenter_types.go` around lines 373 - 383, The
kubebuilder marker `MinProperties=1` on the OpenshiftEC2NodeClassStatus struct
can reject valid initial/partial status updates; remove (or comment out) the `//
+kubebuilder:validation:MinProperties=1` marker from the
OpenshiftEC2NodeClassStatus definition so the controller can create an
initially-empty status and later populate the Conditions field (which already
enforces MinItems=1); ensure only the Conditions slice retains its validation
and that status remains controller-managed.

// associatePublicIPAddress controls if public IP addresses are assigned to instances that are launched with the nodeclass.
// +optional
AssociatePublicIPAddress *bool `json:"associatePublicIPAddress,omitempty"`
AssociatePublicIPAddress PublicIPAddressAssignment `json:"associatePublicIPAddress,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we change the field name? What if it were ipAddressAssociation: Private | Public or maybe Public should be PublicAndPrivate?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we should actually only allow Public here. If omitted default to the subnet behaviour

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd probably allow an explicit Private option here to be honest. It makes it predictable for users who want to set this explicitly in case for some reason we wanted to change what omitted behaviour in the future

Copy link
Member Author

@enxebre enxebre Mar 13, 2026

Choose a reason for hiding this comment

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

actually I'm not sure now, we can guarantee Public because is a cloud provider knob, but when not Public, the visibility is dictated by the subnet setup which is a service consumer infra choice not owned/controlled by us

Copy link
Member Author

@enxebre enxebre Mar 13, 2026

Choose a reason for hiding this comment

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

What happens If we allowed Private here or Basic in monitoring and then the cloud provider change their bool negative value behaviour? they technically shouldn't and it's unlikely, but their bool semantic leave room for ambiguity https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_LaunchTemplatesMonitoringRequest.html#API_LaunchTemplatesMonitoringRequest_Contents

Copy link
Contributor

Choose a reason for hiding this comment

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

actually I'm not sure now, we can guarantee Public because is a cloud provider knob, but when not Public, the visibility is dictated by the subnet setup which is a service consumer infra choice not owned/controlled by us

Good point

So the behaviour is Public or SubnetDefault? And then you'd need to just document that behaviour as

When set to SubnetDefault, the instance IP addresses will match the configuration of the instance subnet

On the monitoring front, I suspect Basic is fine and we will have bigger issues if Amazon changed their API around this (if it were enabled/disabled you'd still get the same breaking change)

// associatePublicIPAddress controls if public IP addresses are assigned to instances that are launched with the nodeclass.
// +optional
AssociatePublicIPAddress *bool `json:"associatePublicIPAddress,omitempty"`
AssociatePublicIPAddress PublicIPAddressAssignment `json:"associatePublicIPAddress,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically this is a breaking change, any existing client/object will have serialization issues if you change this away from a bool. Who is this going to impact?

Copy link
Member Author

Choose a reason for hiding this comment

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

this is still not published. There's no real use case for an out of band client to serialize this today. If the do, they must bump the deps.

Comment on lines +379 to +380
// +patchMergeKey=type
// +patchStrategy=merge
Copy link
Contributor

Choose a reason for hiding this comment

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

PatchStrategy doesn't do anything for CRDs so you can drop these

@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch from d5b46ab to 3be64ff Compare March 13, 2026 12:06
InstanceStorePolicy InstanceStorePolicy `json:"instanceStorePolicy,omitempty"`

// DetailedMonitoring controls if detailed monitoring is enabled for instances that are launched
// detailedMonitoring controls if detailed monitoring is enabled for instances that are launched.
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this wants to be monitoring: Basic | Detailed?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we can only take detailed and default to the provider behaviour

SecurityGroupSelectorTerms []SecurityGroupSelectorTerm `json:"securityGroupSelectorTerms,omitempty"`

// AssociatePublicIPAddress controls if public IP addresses are assigned to instances that are launched with the nodeclass.
// ipAddressAssociation controls the IP address assignment for instances launched with the nodeclass.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should document valid values from the enum and what each valid value means


// ID is the subnet id in EC2
// +kubebuilder:validation:Pattern="subnet-[0-9a-z]+"
// id is the subnet id in EC2.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should document in the godoc the expected format


// ID is the security group id in EC2
// +kubebuilder:validation:Pattern:="sg-[0-9a-z]+"
// id is the security group id in EC2.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should document in the godoc the expected format

Throughput *int64 `json:"throughput,omitempty"`

// VolumeSize in `Gi`, `G`, `Ti`, or `T`. You must specify either a snapshot ID or
// volumeSize in `Gi`, `G`, `Ti`, or `T`. You must specify either a snapshot ID or
Copy link
Contributor

Choose a reason for hiding this comment

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

Using resource.Quantity is generally not advised in most cases.

It can cause parsing issues for non-go clients

Best to make this something like VolumeSizeGiB and make it an integer value

// volumeType is the type of the block device.
// For more information, see Amazon EBS volume types (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html)
// in the Amazon Elastic Compute Cloud User Guide.
// +kubebuilder:validation:Enum:={standard,io1,io2,gp2,sc1,st1,gp3}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit, should use PascalCase for enum values

Suggested change
// +kubebuilder:validation:Enum:={standard,io1,io2,gp2,sc1,st1,gp3}
// +kubebuilder:validation:Enum:={Standard,IO1,IO2,GP2,SC1,ST1,GP3}

@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch 3 times, most recently from 83366ce to 88c0211 Compare March 13, 2026 13:01
@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch 3 times, most recently from bddce3d to de6bf17 Compare March 16, 2026 10:12
// +kubebuilder:validation:Schemaless
// +kubebuilder:validation:Type:=string
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=64000
Copy link
Contributor

Choose a reason for hiding this comment

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

This is 64TiB? Are we working as binary sizes here? If so wouldn't this be 65536?

@enxebre enxebre closed this Mar 16, 2026
@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch from de6bf17 to 70afd8f Compare March 16, 2026 14:35
@enxebre enxebre reopened this Mar 16, 2026
@openshift-ci-robot
Copy link

@enxebre: This pull request references OCPSTRAT-2336 which is a valid jira issue.

Details

In response to this:

Summary

  • Replace *bool and pointer fields in karpenter API types with string enum types (PublicIPAddressAssignment, DetailedMonitoringState, EncryptionState, DeleteOnTerminationPolicy, RootVolumeDesignation) to comply with OpenShift API conventions and kube-api-linter rules
  • Add conversion helpers to translate enum types back to *bool for upstream Karpenter compatibility
  • Update controllers and tests to use the new enum types and conversion helpers

Test plan

  • make build passes
  • make verify passes (excluding unrelated gitlint commit body warning)
  • CI e2e tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
  • Introduced explicit enum-style options for public IP assignment, detailed monitoring, encryption, delete-on-termination and root-volume designation; reworked block device/volume config and strengthened validations (lengths, enums, min/max items/properties) for EC2 node classes, subnets and security group selectors; adjusted NodeClass spec/status/metadata presence and omission semantics.
  • Tests
  • Updated test fixtures and assertions to use new enum values and revised field shapes.

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.

Copy link
Contributor

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

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

LGTM from an API perspective

@enxebre
Copy link
Member Author

enxebre commented Mar 16, 2026

/test e2e-aws-autonode
/test e2e-aws-techpreview

enxebre and others added 3 commits March 17, 2026 11:59
- Replace *bool fields with string enum types to comply with OpenShift
  API conventions
- Rename associatePublicIPAddress to ipAddressAssociation with
  Public/SubnetDefault values
- Rename detailedMonitoring to monitoring with Detailed/Basic values
- Replace volumeType string with VolumeType enum using PascalCase values
- Replace volumeSize *resource.Quantity with volumeSizeGiB int64
  (max 65536 = 64 TiB)
- Change BlockDeviceMappings from []*BlockDeviceMapping to []BlockDeviceMapping
- Make OpenshiftEC2NodeClass spec field required
- Add conversion helpers to translate enum types back to *bool and
  lowercase values for upstream Karpenter compatibility
- Document expected formats for tags and id fields in selector terms
- Fix CEL rule referencing renamed volumeSizeGiB field

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The karpenter API types changed from *bool/pointer fields to string enum
types (IPAddressAssociation, MonitoringState, VolumeType, etc.). Update
controller code and tests to use conversion helpers and enum constants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerated deepcopy, apply configurations, CRDs, and vendor copies
to reflect the karpenter API enum type and required spec changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@enxebre enxebre force-pushed the adjust-karpenter-api-to-ocp-convention branch from 70afd8f to b3e2a10 Compare March 17, 2026 10:59
@enxebre
Copy link
Member Author

enxebre commented Mar 17, 2026

/test e2e-aws-autonode
/test e2e-aws-techpreview

@enxebre
Copy link
Member Author

enxebre commented Mar 17, 2026

/label tide/merge-method-squash

@openshift-ci openshift-ci bot added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Mar 17, 2026
@enxebre
Copy link
Member Author

enxebre commented Mar 17, 2026

/test e2e-aws-autonode
/test e2e-aws-techpreview

@enxebre
Copy link
Member Author

enxebre commented Mar 17, 2026

/test e2e-aws-techpreview

1 similar comment
@jkyros
Copy link
Member

jkyros commented Mar 18, 2026

/test e2e-aws-techpreview

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 18, 2026

@enxebre: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@enxebre enxebre merged commit c720fb7 into openshift:main Mar 18, 2026
17 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/api Indicates the PR includes changes for the API area/karpenter-operator Indicates the PR includes changes related to the Karpenter operator jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants