Skip to content

ROSAENG-64886: fix conversion-gen CRD detection to require TypeMeta/ObjectMeta embeds - #300

Merged
openshift-merge-bot[bot] merged 3 commits into
openshift-online:mainfrom
cdoan1:ROSAENG-64886-fix-conversion-gen-crd-detection
Aug 11, 2026
Merged

ROSAENG-64886: fix conversion-gen CRD detection to require TypeMeta/ObjectMeta embeds#300
openshift-merge-bot[bot] merged 3 commits into
openshift-online:mainfrom
cdoan1:ROSAENG-64886-fix-conversion-gen-crd-detection

Conversation

@cdoan1

@cdoan1 cdoan1 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

The naive Spec+Status heuristic incorrectly treated nested sub-types (e.g. ControlPlaneUpgradePolicy) as top-level CRD resources, generating conversion functions that referenced non-existent wrapper types. Now only types with a wrapper struct embedding metav1.TypeMeta and metav1.ObjectMeta are recognized as CRD resources.

Otherewise, we don't merge this, and top-level CRD need to define TypeMeta/ObjectMeta embeds

The CRD YAML change is small and entirely mechanical — it's a side-effect of regenerating the CRD manifests (make manifests) after updating the Go types.

Here's the causal chain:

  1. New types were added: ControlPlaneUpgradePolicySpec and ControlPlaneUpgradePolicyStatus were added as new files in api/v1alpha1/public/, and new enum types (ControlPlaneUpgradeType, ScheduleUpgradeType, UpgradeScopeType) were added to
    constants.go.
  2. Cluster CRD types were updated: ClusterSpec gained a ControlPlaneUpgradePolicy *ControlPlaneUpgradePolicySpec field, and ClusterStatus gained a matching ControlPlaneUpgradePolicy *ControlPlaneUpgradePolicyStatus field.
  3. CRD was regenerated: Running make manifests (controller-gen) re-derived the CRD YAML from the Go types. The only diff in the CRD YAML itself is the updateType enum values changing from ControlPlane/ControlPlaneCVE to
    UserInitiated/ServiceInitiated. The rest of the new controlPlaneUpgradePolicy block landed in the OpenAPI spec (openapi.yaml), not the CRD bases file, because these are the public API types — the CRD is generated from the internal types in the
    operator.

The two-line enum change (ControlPlane → UserInitiated, ControlPlaneCVE → ServiceInitiated) means the internal CRD types already had a ControlPlaneUpgradePolicySpec with an updateType field, but its enum values were renamed to be more
descriptive and consistent with the new public-facing naming convention. The old names described what was being upgraded; the new names describe who initiated the upgrade — which better matches the field's semantic purpose.

Description

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • CI/CD or tooling change

Testing

  • Unit tests pass (make test)
  • Integration tests pass (if applicable)
  • Manual verification completed

Checklist

  • My code follows the project's coding conventions
  • I have updated documentation as needed
  • I have added tests that prove my fix/feature works
  • All new and existing tests pass

Summary by CodeRabbit

  • New Features

    • Added configurable control-plane upgrade policies for clusters.
    • Supports manual or automatic scheduling, desired versions, upgrade scope, and next-run status.
    • Added validation for schedules and compatible policy settings.
    • Added clear options for user-initiated and service-initiated upgrades.
  • Bug Fixes

    • Improved detection of top-level API resources.
    • Prevented nested specification and status types from being exposed as standalone resources.
    • Enhanced recognition of custom resources by validating required metadata and matching specification/status types.

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

openshift-ci-robot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

@cdoan1: This pull request references ROSAENG-64886 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

The naive Spec+Status heuristic incorrectly treated nested sub-types (e.g. ControlPlaneUpgradePolicy) as top-level CRD resources, generating conversion functions that referenced non-existent wrapper types. Now only types with a wrapper struct embedding metav1.TypeMeta and metav1.ObjectMeta are recognized as CRD resources.

Otherewise, we don't merge this, and top-level CRD need to define TypeMeta/ObjectMeta embeds

Description

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • CI/CD or tooling change

Testing

  • Unit tests pass (make test)
  • Integration tests pass (if applicable)
  • Manual verification completed

Checklist

  • My code follows the project's coding conventions
  • I have updated documentation as needed
  • I have added tests that prove my fix/feature works
  • All new and existing tests pass

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

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

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

The generator now records embedded types and identifies top-level CRD resources through TypeMeta, ObjectMeta, Spec, and Status structure checks. The public API adds control-plane upgrade policy fields, types, validation, and schema definitions.

Changes

CRD discovery and upgrade policy API

Layer / File(s) Summary
Structural CRD resource discovery
hack/api-codegen/pkg/conversion/generator.go
Type parsing records embedded field expressions. REST and conversion discovery use structural validation for top-level CRD resources.
Control-plane upgrade policy API contract
api/v1alpha1/public/constants.go, api/v1alpha1/public/controlplaneupgradepolicyspec_types.go, api/v1alpha1/public/controlplaneupgradepolicystatus_types.go, api/v1alpha1/public/clusterspec_types.go, api/v1alpha1/public/clusterstatus_types.go
The public API adds policy fields, policy spec and status types, enum values, and conditional validation rules.
OpenAPI and CRD schema alignment
api/v1alpha1/public/openapi.yaml, hyperfleet-operator/config/crd/bases/hyperfleet.io_clusters.yaml
The OpenAPI schema adds policy fields and validation. The Cluster CRD updates the updateType enum values.

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

Possibly related PRs

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Ai-Attribution ⚠️ Warning Commits 525f2bd and 618a4da identify Claude Opus 4.6 with Co-Authored-By; no Assisted-by or Generated-by trailer is present. Remove the AI Co-Authored-By trailers and add the required Red Hat Assisted-by or Generated-by trailer.
✅ Passed checks (10 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No-Weak-Crypto ✅ Passed The aggregate PR diff adds no MD5, SHA1, DES, 3DES, RC4, Blowfish, ECB, custom crypto, or secret/token comparisons; existing SHA-256 uses are unchanged.
Container-Privileges ✅ Passed PR changes add API schemas and CRD enum values; no privileged, hostPID, hostIPC, SYS_ADMIN, root, or allowPrivilegeEscalation:true settings were added.
No-Sensitive-Data-In-Logs ✅ Passed The complete PR diff adds no logging or print calls and contains no passwords, tokens, API keys, PII, hostnames, or customer data in emitted output.
No-Hardcoded-Secrets ✅ Passed Topic diff scans found no hardcoded API keys, tokens, passwords, credentials, private keys, credential URLs, or base64 secrets over 32 characters.
No-Injection-Vectors ✅ Passed The PR changes CRD detection and API schemas only; structural and added-line scans found no eval/exec, pickle.loads, unsafe yaml.load, os.system, shell=True, SQL concatenation, or dangerouslySetInn...
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: requiring TypeMeta and ObjectMeta embeds for CRD detection in conversion generation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@hack/api-codegen/pkg/conversion/generator.go`:
- Around line 755-779: Update Generator.isCRDResource to inspect ti.Fields and
require Spec and Status fields whose GoType values match typeName+"Spec" and
typeName+"Status", respectively, in addition to the existing sibling-type and
embedded-metadata checks. Return true only when both matching fields are
present.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift-online/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 09fb3d83-bc13-4788-90dd-7d042213f07b

📥 Commits

Reviewing files that changed from the base of the PR and between 3678e70 and 43f93a2.

📒 Files selected for processing (1)
  • hack/api-codegen/pkg/conversion/generator.go

Comment thread hack/api-codegen/pkg/conversion/generator.go Outdated
statusName := typeName + "Status"
_, hasSpec := g.typeInfos[specName]
_, hasStatus := g.typeInfos[statusName]
if hasSpec && hasStatus {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This was required before and now isn't, is that expected?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes, the Spec+Status check is still required and still happens — it's inside isCRDResource(). The isCRDResource() function is a superset: it checks sibling types AND embeds AND (after our latest change) matching Spec/Status fields.

@cdoan1

cdoan1 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

/test ci/prow/unit

@cdoan1

cdoan1 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

/retest

@cdoan1

cdoan1 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator Author

/test on-demand-e2e

@cdoan1
cdoan1 force-pushed the ROSAENG-64886-fix-conversion-gen-crd-detection branch from a2a35df to 63c3f21 Compare August 11, 2026 14:20
@openshift-ci

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

@cdoan1: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/on-demand-e2e a2a35df link true /test on-demand-e2e

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.

cdoan1 and others added 2 commits August 11, 2026 10:43
…bjectMeta embeds

The naive Spec+Status heuristic incorrectly treated nested sub-types
(e.g. ControlPlaneUpgradePolicy) as top-level CRD resources, generating
conversion functions that referenced non-existent wrapper types. Now
only types with a wrapper struct embedding metav1.TypeMeta and
metav1.ObjectMeta are recognized as CRD resources.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address review feedback: in addition to checking for sibling FooSpec/FooStatus
type definitions and TypeMeta/ObjectMeta embeds, also verify the wrapper struct
declares Spec and Status fields whose GoType matches the sibling types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cdoan1
cdoan1 force-pushed the ROSAENG-64886-fix-conversion-gen-crd-detection branch from 63c3f21 to 618a4da Compare August 11, 2026 17:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In `@api/v1alpha1/public/controlplaneupgradepolicyspec_types.go`:
- Line 35: Update the cron validation Pattern on the control plane upgrade
policy spec to reject zero step values in every \*/... alternative across all
five fields. Replace each step subpattern with an allow-list of valid nonzero
values while preserving the existing accepted cron syntax and ranges.

In `@api/v1alpha1/public/openapi.yaml`:
- Around line 2265-2330: Add a controlPlaneUpgradePolicy status object to the
ClusterStatusInfo schema, including the nextRun date-time field exposed by the
CRD. Match the CRD’s property name, type, and format so OpenAPI-generated
clients can represent the policy status.

In `@hyperfleet-operator/config/crd/bases/hyperfleet.io_clusters.yaml`:
- Around line 112-113: Update the enum in the cluster CRD schema to retain the
deprecated ControlPlane and ControlPlaneCVE values alongside UserInitiated and
ServiceInitiated. Do not remove the legacy values until stored Cluster resources
have been migrated in a later release.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift-online/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9bf02e13-399b-4807-abb9-0776ce999358

📥 Commits

Reviewing files that changed from the base of the PR and between a2a35df and d857fc0.

⛔ Files ignored due to path filters (1)
  • api/v1alpha1/public/zz_generated.deepcopy.go is excluded by !**/zz_generated*
📒 Files selected for processing (7)
  • api/v1alpha1/public/clusterspec_types.go
  • api/v1alpha1/public/clusterstatus_types.go
  • api/v1alpha1/public/constants.go
  • api/v1alpha1/public/controlplaneupgradepolicyspec_types.go
  • api/v1alpha1/public/controlplaneupgradepolicystatus_types.go
  • api/v1alpha1/public/openapi.yaml
  • hyperfleet-operator/config/crd/bases/hyperfleet.io_clusters.yaml

Comment thread api/v1alpha1/public/controlplaneupgradepolicyspec_types.go
Comment on lines +2265 to +2330
controlPlaneUpgradePolicy:
description: ControlPlaneUpgradePolicy is the control plane upgrade policy defined by the user.
properties:
nextRun:
description: NextRun is the time the upgrade should run for "manual" upgrade policies
format: date-time
type: string
schedule:
description: |-
Schedule defines a cron expression that calculates the next automatic upgrade scheduling.
The cron expression must follow the standard 5-field format:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
* * * * *
maxLength: 256
pattern: ^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])-([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])(,([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]))*) (\*|([0-9]|1[0-9]|2[0-3])|([0-9]|1[0-9]|2[0-3])-([0-9]|1[0-9]|2[0-3])|\*/([0-9]|1[0-9]|2[0-3])|([0-9]|1[0-9]|2[0-3])(,([0-9]|1[0-9]|2[0-3]))*) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|([1-9]|1[0-9]|2[0-9]|3[0-1])-([1-9]|1[0-9]|2[0-9]|3[0-1])|\*/([1-9]|1[0-9]|2[0-9]|3[0-1])|([1-9]|1[0-9]|2[0-9]|3[0-1])(,([1-9]|1[0-9]|2[0-9]|3[0-1]))*) (\*|([1-9]|1[0-2])|([1-9]|1[0-2])-([1-9]|1[0-2])|\*/([1-9]|1[0-2])|([1-9]|1[0-2])(,([1-9]|1[0-2]))*) (\*|[0-6]|[0-6]-[0-6]|\*/[0-6]|[0-6](,[0-6])*)$
type: string
scheduleType:
description: |-
ScheduleType indicates if the control plane upgrade policy is "manual" and it's executed only one time or
whether it is "automatic" where an expression will calculate recurrent upgrades.
enum:
- Manual
- Automatic
type: string
updateType:
description: |-
UpdateType indicates if it is a control plane upgrade policy defined by the user or
triggered by Red Hat for addressing critical CVEs.
enum:
- UserInitiated
- ServiceInitiated
type: string
upgradeScope:
description: |-
UpgradeScope indicates if minor version upgrades are allowed for automatic upgrades.
Manual upgrades always allow it.
enum:
- PatchOnly
- PatchAndMinor
type: string
version:
description: Version is the desired upgrade version on "manual" upgrade policies.
maxLength: 64
type: string
required:
- scheduleType
- updateType
type: object
x-kubernetes-validations:
- message: version and nextRun are required when scheduleType is Manual
rule: self.scheduleType != 'Manual' || (has(self.version) && has(self.nextRun))
- message: schedule must not be set when scheduleType is Manual
rule: self.scheduleType != 'Manual' || !has(self.schedule)
- message: schedule is required when scheduleType is Automatic
rule: self.scheduleType != 'Automatic' || has(self.schedule)
- message: version and nextRun must not be set when scheduleType is Automatic
rule: self.scheduleType != 'Automatic' || (!has(self.version) && !has(self.nextRun))
- message: upgradeScope must not be set when scheduleType is Manual
rule: self.scheduleType != 'Manual' || !has(self.upgradeScope)
- message: upgradeScope is required when scheduleType is Automatic
rule: self.scheduleType != 'Automatic' || has(self.upgradeScope)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Add the policy status to the OpenAPI response schema.

The CRD exposes status.controlPlaneUpgradePolicy.nextRun, but ClusterStatusInfo does not declare this field. OpenAPI-generated clients cannot model the new policy status. Add the matching status object to ClusterStatusInfo.

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

In `@api/v1alpha1/public/openapi.yaml` around lines 2265 - 2330, Add a
controlPlaneUpgradePolicy status object to the ClusterStatusInfo schema,
including the nextRun date-time field exposed by the CRD. Match the CRD’s
property name, type, and format so OpenAPI-generated clients can represent the
policy status.

Comment thread hyperfleet-operator/config/crd/bases/hyperfleet.io_clusters.yaml
@gdbranco

Copy link
Copy Markdown
Contributor

/lgtm

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

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cdoan1, gdbranco

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-merge-bot
openshift-merge-bot Bot merged commit 1225902 into openshift-online:main Aug 11, 2026
13 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. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants