Skip to content

feat: Migrate HCO automation from v1beta1 to v1 API - #5958

Open
hmeir wants to merge 9 commits into
RedHatQE:mainfrom
hmeir:hco-v1-api-migration
Open

feat: Migrate HCO automation from v1beta1 to v1 API#5958
hmeir wants to merge 9 commits into
RedHatQE:mainfrom
hmeir:hco-v1-api-migration

Conversation

@hmeir

@hmeir hmeir commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
What this PR does / why we need it:

Migrates all HCO automation from v1beta1 to v1 API. The upstream
openshift-python-wrapper PR #2777 regenerated the HyperConverged class
from the v1 CRD schema. This PR updates all test code to match.

Key changes:

  • Add HCOv1Spec class with callable spec group builders and FG helpers
  • Add parse_hco_fg_phases() to read FG phase defaults from the CRD at runtime
  • Remove v1beta1 API version override in get_hyperconverged_resource()
  • Convert all FG patches from dict to v1 list format
  • Convert all spec patches/reads from flat paths to v1 grouped structure
  • Add 15 unit tests for the new tooling
  • Add v1 enforcement rules to AGENTS.md

50 files changed across 9 commits, organized by domain (utilities, IUO,
storage, virt, network, infrastructure).

Which issue(s) this PR fixes:

CNV-87694

Special notes for reviewer:
  • spec.workloads is renamed to workload (singular) in v1
  • Feature gates stay at spec.featureGates (NOT under a group), only format changes
  • Deprecated FGs (enableMultiArchBootImageImport, disableMDevConfiguration,
    persistentReservation) should be read from their dedicated spec fields
  • changedBlockTrackingLabelSelectors moved under spec.virtualization
jira-ticket:

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

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added support for constructing and validating HyperConverged v1 configuration, including grouped settings, feature gates, node placement, storage, virtualization, and security options.
    • Added feature-gate phase parsing and default-aware enablement checks.
  • Bug Fixes
    • Updated configuration handling for nested deployment, workload, networking, and security settings.
    • Improved handling of missing workload-source configuration.
  • Tests
    • Expanded coverage for v1 schemas, feature-gate behavior, nested configuration, and validation errors.
  • Chores
    • Updated the minimum supported wrapper version.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@hmeir, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 41 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cd803b8f-e5b6-44a2-a003-ff1b7f8cc060

📥 Commits

Reviewing files that changed from the base of the PR and between b130a55 and d9ad4da.

📒 Files selected for processing (10)
  • tests/conftest.py
  • tests/install_upgrade_operators/crypto_policy/test_hco_crypto_policy_propagation.py
  • tests/install_upgrade_operators/hco_enablement_golden_image_updates/test_enable_common_boot_image_import.py
  • tests/install_upgrade_operators/node_component/conftest.py
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_default_cpu_model.py
  • tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py
  • tests/storage/test_cdi_certificate.py
  • tests/virt/node/workload_density/test_free_page_reporting.py
  • utilities/constants/hco.py
  • utilities/hco.py
📝 Walkthrough

Walkthrough

The PR adds HCOv1Spec builders and CRD-based feature-gate parsing. It migrates shared utilities, fixtures, and tests from legacy HCO paths and mappings to the grouped HCO v1 schema.

Changes

HCO v1 migration

Layer / File(s) Summary
HCO v1 builders and feature-gate parsing
AGENTS.md, pyproject.toml, utilities/constants/hco.py, utilities/hco.py, utilities/infra.py, utilities/unittests/test_hco.py
Adds grouped HCO v1 patch builders, list-form feature-gate handling, CRD phase parsing, and unit coverage.
Shared utilities and workload configuration
tests/conftest.py, tests/infrastructure/..., tests/install_upgrade_operators/hco_enablement_golden_image_updates/..., utilities/hco.py, utilities/unittests/test_hco.py
Updates node placement, workload source, boot-image, and AAQ handling to nested v1 paths.
Install and upgrade test migration
tests/install_upgrade_operators/...
Migrates security, virtualization, deployment, node-placement, feature-gate, API-version, and uninstall tests to HCO v1 paths and builders.
Strict reconciliation and storage migration
tests/install_upgrade_operators/strict_reconciliation/..., tests/network/..., tests/storage/..., tests/utils.py
Updates strict-reconciliation, networking, storage, certificate, live-migration, and feature-gate test payloads and assertions.
Virtualization and GPU test migration
tests/virt/...
Uses HCO v1 virtualization and feature-gate builders across virtualization, GPU, workload-density, upgrade, and vGPU tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: new-tests

Suggested reviewers: vsibirsk, rnetser

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title is under 120 characters and clearly describes the migration from the HCO v1beta1 API to the v1 API.
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.
Pr Template Sections ✅ Passed The PR body includes all four required headings, and the first section contains meaningful migration details and rationale.
Stp Link Required ✅ Passed The PR diff adds no test files or test_* functions under tests; the added test functions are only in utilities/unittests/, which this check skips.
Stp Scenario Coverage ✅ Passed The PR modifies test_*.py files, but none contain an STP:, Jira:, or RFE: reference; the STP coverage check is not applicable.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.50746% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.89%. Comparing base (f18201a) to head (d9ad4da).
⚠️ Report is 30 commits behind head on main.

Files with missing lines Patch % Lines
utilities/constants/hco.py 97.56% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5958      +/-   ##
==========================================
- Coverage   98.89%   98.89%   -0.01%     
==========================================
  Files          42       42              
  Lines        2631     2704      +73     
==========================================
+ Hits         2602     2674      +72     
- Misses         29       30       +1     
Flag Coverage Δ
utilities 98.89% <98.50%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@openshift-virtualization-qe-bot-4

Copy link
Copy Markdown

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the OWNERS file in the repository root
  • Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
  • Issue Creation: A tracking issue is created for this PR and will be closed when the PR is merged or closed
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified
  • Labels: Enabled categories: branch, can-be-merged, cherry-pick, has-conflicts, hold, needs-rebase, size, verified, wip

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (PR author or approvers)
  • /hold cancel - Unblock PR merging (PR author or approvers)
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)
  • /regenerate-welcome - Regenerate this welcome message
  • /security-override - Set security check runs to pass (maintainers only)
  • /security-override cancel - Re-run security checks

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest verify-bugs-are-open - verify-bugs-are-open
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3
  • /cherry-pick-retry <branch> - Retry a failed cherry-pick (merged PRs only)

Branch Management

  • /rebase - Rebase this PR branch onto its base branch

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. LGTM Count: Minimum 2 /lgtm from reviewers
  3. Status Checks: All required status checks must pass
  4. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  5. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • EdDev
  • dshchedr
  • jpeimer
  • myakove
  • rnetser
  • vsibirsk

Reviewers:

  • Acedus
  • Ahmad-Hafe
  • Anatw
  • Dsanatar
  • EdDev
  • OhadRevah
  • RoniKishner
  • SamAlber
  • acinko-rh
  • akalenyu
  • akri3i
  • albarker-rh
  • awels
  • azhivovk
  • dalia-frank
  • dshchedr
  • ema-aka-young
  • frenzyfriday
  • geetikakay
  • hmeir
  • josemacassan
  • jpeimer
  • kgoldbla
  • kshvaika
  • mijankow
  • nirdothan
  • orelmisan
  • rlobillo
  • rnetser
  • servolkov
  • vsibirsk
  • yossisegev
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
AI Features
  • Cherry-Pick Conflict Resolution: Enabled (claude/claude-opus-4-6-1m)
Security Checks
  • Suspicious Path Detection: Monitors paths: .claude/, .vscode/, .cursor/, .devcontainer/, .pi/, .github/workflows/, .github/actions/
  • Committer Identity Check: Verifies last committer matches PR author
  • Mandatory: Security checks block merge (use /security-override to bypass — maintainers only)

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is removed on new commits unless the push is detected as a clean rebase
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

📌 Additional Information

Custom Commands:

  • /test-plan — Triggers CodeRabbit to analyze the PR's changed files and post a test execution plan
  • /rerun-smoke — Adds retest-smoke label on the PR to trigger smoke tests execution

For more information, please refer to the project documentation or contact the maintainers.

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

🤖 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 `@AGENTS.md`:
- Around line 238-240: Update the HCO patch guidance to require v1 builders for
each field group while allowing their generated payloads to be composed into a
single spec patch when an update spans multiple groups. Preserve the prohibition
on manually constructing grouped nested dictionaries, v1beta1 flat paths, and
dict-format feature gates; clarify that merging outputs such as
HCOv1Spec.feature_gates() and HCOv1Spec.virtualization() is valid.
- Around line 244-255: Add blank lines between each bold heading and its
following fenced code block in the documented Before and After sections,
ensuring both opening fences satisfy markdownlint MD031.

In `@tests/install_upgrade_operators/csv/test_hco_api_version.py`:
- Around line 8-12: Update test_hyperconverged_cr_api_version to provide an
assertion failure message containing the observed
hyperconverged_resource_scope_function.instance.apiVersion and the expected
/{Resource.ApiVersion.V1} suffix, while preserving the existing assertion
condition.

In
`@tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py`:
- Around line 23-52: Replace raw nested HCO patch dictionaries with the existing
HCOv1Spec builders: in
tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py#L23-L52,
use HCOv1Spec.virtualization(...) for all four reset patches; in
tests/install_upgrade_operators/launcher_updates/constants.py#L48-L48, construct
the customization with HCOv1Spec.virtualization(...); and in
tests/install_upgrade_operators/product_uninstall/test_remove_hco.py#L142-L144,
use HCOv1Spec.deployment(...) for the uninstall strategy patch. Preserve the
existing values and test behavior while using the v1 grouped API consistently.

In `@tests/install_upgrade_operators/product_uninstall/test_remove_kubevirt.py`:
- Around line 20-22: Replace the inline deployment payload in the patches
argument with HCOv1Spec.deployment(uninstallStrategy="RemoveWorkloads"), and add
the HCOv1Spec import if needed. Keep the existing
hyperconverged_resource_scope_function key unchanged and ensure this HCO spec
patch uses the v1 grouped API.

In `@tests/install_upgrade_operators/strict_reconciliation/conftest.py`:
- Around line 127-132: Update the loop adding feature gates in the fixture so
existing_names is updated immediately after appending a new feature-gate object,
ensuring duplicate entries in new_fgs are not emitted.

In `@tests/install_upgrade_operators/strict_reconciliation/constants.py`:
- Line 255: Rename the constant NP_WORKLOADS_KEY_HCO_CR to
NP_WORKLOAD_KEY_HCO_CR in constants.py and update every reference to use the
singular identifier, while preserving its "workload" value.

In
`@tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py`:
- Around line 68-69: Centralize HCO spec patch construction through the grouped
HCOv1Spec builders instead of duplicating schema paths: in
tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py,
update ranges 68-69, 89-98, 118-126, 147-155, and 176-185 to use
HCOv1Spec.security(...), and ranges 202, 225-232, 255-261, 282, and 305-311 to
use HCOv1Spec.virtualization(...); in
tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py
ranges 23-26 and 31-35 also use HCOv1Spec.virtualization(...); in
tests/storage/cdi_config/test_cdi_config.py range 107-113 use
HCOv1Spec.storage(...) for both fragments. Ensure all HCO spec patches and reads
use the v1 grouped API.

In
`@tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py`:
- Line 51: Update the assertion failure message associated with the HCO live
migration configuration lookup in the test to report the actual
HCO.spec.virtualization.liveMigrationConfig path, while preserving the existing
lookup and assertion behavior.

In `@tests/storage/cbt/conftest.py`:
- Around line 50-56: The CBT fixture setup must preserve existing
spec.featureGates entries instead of replacing them with only incrementalBackup.
Update the merged_spec construction around HCOv1Spec.feature_gates and
ResourceEditorValidateHCOReconcile to derive the target feature-gate list from
the current resource, then add or update incrementalBackup while retaining all
existing gates.

In `@utilities/hco.py`:
- Around line 98-106: Update the v1 schema traversal that computes
fg_description to catch missing-key failures, including an absent
spec.featureGates path, and re-raise ValueError with the HCO schema path and
original exception context. Preserve the existing ValueError for unparseable
phases, and add a unit test covering a v1 schema without spec.featureGates.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8b2a21b8-032b-47f8-8c7c-2c93dd44d1b1

📥 Commits

Reviewing files that changed from the base of the PR and between 58f19a3 and b130a55.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (49)
  • AGENTS.md
  • pyproject.toml
  • tests/conftest.py
  • tests/infrastructure/golden_images/update_boot_source/conftest.py
  • tests/infrastructure/vhostmd/test_downwardmetrics_virtio.py
  • tests/infrastructure/vhostmd/test_vhostmd.py
  • tests/install_upgrade_operators/conftest.py
  • tests/install_upgrade_operators/constants.py
  • tests/install_upgrade_operators/crypto_policy/test_crypto_policy_default.py
  • tests/install_upgrade_operators/crypto_policy/test_hco_crypto_policy_propagation.py
  • tests/install_upgrade_operators/crypto_policy/test_hco_custom_profile_negative.py
  • tests/install_upgrade_operators/crypto_policy/utils.py
  • tests/install_upgrade_operators/csv/test_hco_api_version.py
  • tests/install_upgrade_operators/feature_gates/test_update_featuregate_hco.py
  • tests/install_upgrade_operators/hco_enablement_golden_image_updates/test_enable_common_boot_image_import.py
  • tests/install_upgrade_operators/launcher_updates/constants.py
  • tests/install_upgrade_operators/launcher_updates/test_negative_kubevirt_update.py
  • tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py
  • tests/install_upgrade_operators/must_gather/conftest.py
  • tests/install_upgrade_operators/node_component/conftest.py
  • tests/install_upgrade_operators/node_component/test_deploy_cnv_on_subset_of_nodes_sanity.py
  • tests/install_upgrade_operators/product_uninstall/test_remove_hco.py
  • tests/install_upgrade_operators/product_uninstall/test_remove_kubevirt.py
  • tests/install_upgrade_operators/strict_reconciliation/conftest.py
  • tests/install_upgrade_operators/strict_reconciliation/constants.py
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_nondefault_fields.py
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_default_cpu_model.py
  • tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py
  • tests/network/kubemacpool/explicit_range/conftest.py
  • tests/storage/cbt/conftest.py
  • tests/storage/cdi_config/test_cdi_config.py
  • tests/storage/cross_cluster_live_migration/utils.py
  • tests/storage/test_cdi_certificate.py
  • tests/storage/test_hotplug.py
  • tests/storage/upgrade/conftest.py
  • tests/utils.py
  • tests/virt/cluster/migration_and_maintenance/test_evictionstrategy.py
  • tests/virt/node/gpu/gpu_pci_passthrough/conftest.py
  • tests/virt/node/gpu/vgpu/conftest.py
  • tests/virt/node/workload_density/test_free_page_reporting.py
  • tests/virt/node/workload_density/test_kernel_samepage_merging.py
  • tests/virt/upgrade/conftest.py
  • tests/virt/upgrade_custom/vgpu/conftest.py
  • tests/virt/utils.py
  • utilities/constants/hco.py
  • utilities/hco.py
  • utilities/infra.py
  • utilities/unittests/test_hco.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • RedHatQE/openshift-virtualization-tests-design-docs (manual)
💤 Files with no reviewable changes (3)
  • tests/install_upgrade_operators/constants.py
  • tests/install_upgrade_operators/conftest.py
  • utilities/infra.py

Comment thread AGENTS.md
Comment on lines +238 to +240
1. **HCO spec patches MUST use v1 grouped structure** — use `HCOv1Spec` builders, NEVER construct raw nested dicts manually
2. **Feature gates MUST use v1 list format** — use `HCOv1Spec.feature_gates(name=True/False)`, NEVER dict format `{"featureGates": {"name": true}}`
3. **NEVER use v1beta1 flat spec paths** — `spec.liveMigrationConfig` is wrong, `spec.virtualization.liveMigrationConfig` is correct. See `HCOv1Spec` group builders in `utilities/constants/hco.py` for the complete mapping

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.

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

MEDIUM: Allow composition of builder-generated patches.

The absolute prohibition conflicts with multi-group patches. For example, tests/storage/cbt/conftest.py combines HCOv1Spec.feature_gates() and HCOv1Spec.virtualization() results before passing one spec patch.

Require builders for each field group. Permit merging builder-generated payloads when one update changes multiple groups. Do not require developers to hand-write grouped paths.

🤖 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 `@AGENTS.md` around lines 238 - 240, Update the HCO patch guidance to require
v1 builders for each field group while allowing their generated payloads to be
composed into a single spec patch when an update spans multiple groups. Preserve
the prohibition on manually constructing grouped nested dictionaries, v1beta1
flat paths, and dict-format feature gates; clarify that merging outputs such as
HCOv1Spec.feature_gates() and HCOv1Spec.virtualization() is valid.

Comment thread AGENTS.md
Comment on lines +244 to +255
**Before (v1beta1 -- WRONG):**
```python
# Flat spec path -- WRONG
patch = {"spec": {"liveMigrationConfig": {"parallelOutboundMigrationsPerNode": 5}}}
hco_resource.update(resource_dict=patch)

# Dict feature gate -- WRONG
fg_patch = {"spec": {"featureGates": {"withHostPassthroughCPU": True}}}
```

**After (v1 -- CORRECT):**
```python

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.

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

MEDIUM: Add blank lines around both fenced code blocks.

markdownlint reports MD031 at Lines 245 and 255. Add a blank line after each bold heading before the opening fence.

🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 245-245: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 255-255: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 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 `@AGENTS.md` around lines 244 - 255, Add blank lines between each bold heading
and its following fenced code block in the documented Before and After sections,
ensuring both opening fences satisfy markdownlint MD031.

Source: Linters/SAST tools

Comment on lines 8 to +12
def test_hyperconverged_cr_api_version(hyperconverged_resource_scope_function):
"""
This test will check the Hyperconverged CR's api_version for v1beta1
This test will check the Hyperconverged CR's api_version for v1
"""
assert Resource.ApiVersion.V1BETA1 in hyperconverged_resource_scope_function.instance.apiVersion
assert hyperconverged_resource_scope_function.instance.apiVersion.endswith(f"/{Resource.ApiVersion.V1}")

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

LOW: Add an assertion failure message.

If the API version is not v1, this assertion does not show the observed value. Add a message with the actual apiVersion and expected suffix.

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

In `@tests/install_upgrade_operators/csv/test_hco_api_version.py` around lines 8 -
12, Update test_hyperconverged_cr_api_version to provide an assertion failure
message containing the observed
hyperconverged_resource_scope_function.instance.apiVersion and the expected
/{Resource.ApiVersion.V1} suffix, while preserving the existing assertion
condition.

Source: Learnings

Comment on lines +23 to +52
"patch": {"spec": {"virtualization": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: None}}},
},
DEFAULT_WORKLOAD_UPDATE_STRATEGY,
marks=(pytest.mark.polarion("CNV-6928"),),
),
pytest.param(
{
"patch": {"spec": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: {"batchEvictionInterval": None}}},
"patch": {
"spec": {"virtualization": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: {"batchEvictionInterval": None}}}
},
},
MOD_CUST_DEFAULT_BATCH_EVICTION_INTERVAL,
marks=pytest.mark.polarion("CNV-6929"),
id="test_hyperconverged_reset_workload_update_strategy_batch_eviction_size",
),
pytest.param(
{
"patch": {"spec": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: {"batchEvictionSize": None}}},
"patch": {
"spec": {"virtualization": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: {"batchEvictionSize": None}}}
},
},
MOD_CUST_DEFAULT_BATCH_EVICTION_SIZE,
marks=pytest.mark.polarion("CNV-6930"),
id="test_hyperconverged_reset_workload_update_strategy_workload_update_methods",
),
pytest.param(
{
"patch": {"spec": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: {WORKLOADUPDATEMETHODS: None}}},
"patch": {
"spec": {"virtualization": {WORKLOAD_UPDATE_STRATEGY_KEY_NAME: {WORKLOADUPDATEMETHODS: None}}}
},

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

HIGH: Centralize HCO patch construction with HCOv1Spec.

These changed sites construct HCO patch payloads with raw nested dictionaries. The repository requires HCO spec patches to use HCOv1Spec builders.

  • tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py#L23-L52: use HCOv1Spec.virtualization(...) for all four reset patches.
  • tests/install_upgrade_operators/launcher_updates/constants.py#L48-L48: use HCOv1Spec.virtualization(**CUSTOM_STRATEGY).
  • tests/install_upgrade_operators/product_uninstall/test_remove_hco.py#L142-L144: use HCOv1Spec.deployment(uninstallStrategy=REMOVE_STRATEGY).

As per coding guidelines: all HCO spec patches and reads must use the v1 grouped API and HCOv1Spec builders.
Based on learnings: reuse existing implementations instead of duplicating schema construction.

📍 Affects 3 files
  • tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py#L23-L52 (this comment)
  • tests/install_upgrade_operators/launcher_updates/constants.py#L48-L48
  • tests/install_upgrade_operators/product_uninstall/test_remove_hco.py#L142-L144
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py`
around lines 23 - 52, Replace raw nested HCO patch dictionaries with the
existing HCOv1Spec builders: in
tests/install_upgrade_operators/launcher_updates/test_reset_custom_values.py#L23-L52,
use HCOv1Spec.virtualization(...) for all four reset patches; in
tests/install_upgrade_operators/launcher_updates/constants.py#L48-L48, construct
the customization with HCOv1Spec.virtualization(...); and in
tests/install_upgrade_operators/product_uninstall/test_remove_hco.py#L142-L144,
use HCOv1Spec.deployment(...) for the uninstall strategy patch. Preserve the
existing values and test behavior while using the v1 grouped API consistently.

Sources: Coding guidelines, Learnings

Comment on lines +20 to +22
patches={
hyperconverged_resource_scope_function: {"spec": {"deployment": {"uninstallStrategy": "RemoveWorkloads"}}}
},

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

HIGH: Use HCOv1Spec.deployment(...) for the uninstall-strategy patch.

The nested payload is correct for HCO v1, but this code bypasses the shared builder. Replace it with HCOv1Spec.deployment(uninstallStrategy="RemoveWorkloads"). Add the HCOv1Spec import if this file does not already have it.

Proposed fix
-            hyperconverged_resource_scope_function: {"spec": {"deployment": {"uninstallStrategy": "RemoveWorkloads"}}}
+            hyperconverged_resource_scope_function: HCOv1Spec.deployment(
+                uninstallStrategy="RemoveWorkloads"
+            )

As per path instructions, “All HCO spec patches and reads must use the v1 grouped API and HCOv1Spec builders.”

📝 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
patches={
hyperconverged_resource_scope_function: {"spec": {"deployment": {"uninstallStrategy": "RemoveWorkloads"}}}
},
patches={
hyperconverged_resource_scope_function: HCOv1Spec.deployment(
uninstallStrategy="RemoveWorkloads"
)
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/install_upgrade_operators/product_uninstall/test_remove_kubevirt.py`
around lines 20 - 22, Replace the inline deployment payload in the patches
argument with HCOv1Spec.deployment(uninstallStrategy="RemoveWorkloads"), and add
the HCOv1Spec import if needed. Keep the existing
hyperconverged_resource_scope_function key unchanged and ensure this HCO spec
patch uses the v1 grouped API.

Source: Path instructions

"nodePlacement": NP_INFRA_VALUE_CDI_CR,
}
NP_WORKLOADS_KEY_HCO_CR = "workloads"
NP_WORKLOADS_KEY_HCO_CR = "workload"

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.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

MEDIUM: Rename the constant to match the singular HCO v1 field.

The value is now "workload", but the identifier remains NP_WORKLOADS_KEY_HCO_CR. Rename it to NP_WORKLOAD_KEY_HCO_CR and update its references. The current name misstates the v1 schema and can cause future code to use the obsolete plural field.

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

In `@tests/install_upgrade_operators/strict_reconciliation/constants.py` at line
255, Rename the constant NP_WORKLOADS_KEY_HCO_CR to NP_WORKLOAD_KEY_HCO_CR in
constants.py and update every reference to use the singular identifier, while
preserving its "workload" value.

Comment on lines +68 to 69
"patch": {"spec": {"security": {HCO_CR_CERT_CONFIG_KEY: EXPCT_CERTC_DEFAULTS}}},
},

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

HIGH: Centralize HCO patch construction in HCOv1Spec.

These changed inputs duplicate the v1 schema. Use the shared builder that owns each grouped path.

  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L68-L69: use HCOv1Spec.security(...).
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L89-L98: use HCOv1Spec.security(...) for the CA duration patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L118-L126: use HCOv1Spec.security(...) for the CA renewal patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L147-L155: use HCOv1Spec.security(...) for the server duration patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L176-L185: use HCOv1Spec.security(...) for the server renewal patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L202-L202: use HCOv1Spec.virtualization(...) for the live-migration defaults patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L225-L232: use HCOv1Spec.virtualization(...) for the completion-timeout patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L255-L261: use HCOv1Spec.virtualization(...) for the parallel-migrations patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L282-L282: use HCOv1Spec.virtualization(...) for the outbound-migrations patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L305-L311: use HCOv1Spec.virtualization(...) for the progress-timeout patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py#L23-L26: use HCOv1Spec.virtualization(...) for the auto-converge patch.
  • tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py#L31-L35: use HCOv1Spec.virtualization(...) for the post-copy patch.
  • tests/storage/cdi_config/test_cdi_config.py#L107-L113: use HCOv1Spec.storage(...) for both storage fragments.

As per coding guidelines, all HCO spec patches and reads must use the v1 grouped API and HCOv1Spec builders.

📍 Affects 3 files
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L68-L69 (this comment)
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L89-L98
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L118-L126
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L147-L155
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L176-L185
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L202-L202
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L225-L232
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L255-L261
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L282-L282
  • tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py#L305-L311
  • tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py#L23-L26
  • tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py#L31-L35
  • tests/storage/cdi_config/test_cdi_config.py#L107-L113
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py`
around lines 68 - 69, Centralize HCO spec patch construction through the grouped
HCOv1Spec builders instead of duplicating schema paths: in
tests/install_upgrade_operators/strict_reconciliation/test_hco_cr_modify_defaults.py,
update ranges 68-69, 89-98, 118-126, 147-155, and 176-185 to use
HCOv1Spec.security(...), and ranges 202, 225-232, 255-261, 282, and 305-311 to
use HCOv1Spec.virtualization(...); in
tests/install_upgrade_operators/strict_reconciliation/test_livemigration_config_update.py
ranges 23-26 and 31-35 also use HCOv1Spec.virtualization(...); in
tests/storage/cdi_config/test_cdi_config.py range 107-113 use
HCOv1Spec.storage(...) for both fragments. Ensure all HCO spec patches and reads
use the v1 grouped API.

Source: Coding guidelines

Comment on lines +50 to +56
fg_patch = HCOv1Spec.feature_gates(incrementalBackup=True)
cbt_patch = HCOv1Spec.virtualization(
changedBlockTrackingLabelSelectors={"virtualMachineLabelSelector": {"matchLabels": CBT_ENABLED_LABEL}},
)
merged_spec = {**fg_patch["spec"], **cbt_patch["spec"]}
with ResourceEditorValidateHCOReconcile(
patches={
hyperconverged_resource_scope_module: {
"spec": {
"featureGates": {"incrementalBackup": True},
"changedBlockTrackingLabelSelectors": {
"virtualMachineLabelSelector": {"matchLabels": CBT_ENABLED_LABEL},
},
},
},
},
patches={hyperconverged_resource_scope_module: {"spec": merged_spec}},

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

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 12 'class ResourceEditor|def update\(|PatchType|merge-patch|server-side' utilities libs tests || true
rg -n -C 8 'HCOv1Spec\.feature_gates|incrementalBackup|featureGates' utilities tests || true

Repository: RedHatQE/openshift-virtualization-tests

Length of output: 50395


🏁 Script executed (no clone):

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import urllib.request
import json
import re
import tempfile
import zipfile

# Fetch KubeVirt HCO CRD from the upstream GitHub API.
url = "https://api.github.com/repos/kubevirt/hyperconverged-cluster-operator/contents/config/crd/bases/hco.kubevirt.io_hyperconvergeds.yaml"
with urllib.request.urlopen(url, timeout=30) as r:
    crd_yaml = r.read().decode("utf-8")
PY

Length of output: 2411


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the base ResourceEditor implementation and installed dependency versions that define patch semantics.
rg -n -C 20 'class ResourceEditor|def update\(|patches|PatchType|patch_type|patched|server.apply|server.side|json\.patch|merge_patch' utilities pyproject.toml uv.lock poetry.lock setup.cfg setup.py 2>/dev/null || true

# Print exact source around ResourceEditor and ResourceEditorValidateHCOReconcile.
sed -n '1,130p' utilities/hco.py

# Print relevant project dependency declarations and lock versions.
for f in pyproject.toml uv.lock poetry.lock poetry.lock.cpan; do
  if [ -f "$f" ]; then
    echo "---- $f ----"
    rg -n 'openshift-client|kubectl|kubernetes-client|openshift|resource|operator-sdk|kubernetes' "$f" || true
  fi
done

Repository: RedHatQE/openshift-virtualization-tests

Length of output: 50395


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- dependency files ----"
for f in pyproject.toml requirements.txt pipenv.lock constraints.txt setup.cfg setup.py pdm.lock; do
  if [ -f "$f" ]; then
    echo "==== $f ===="
    rg -n 'openshift-client|kubernetes|kubernetes-client|pyopenssl|sslp|openshift' "$f" || true
  fi
done

echo "---- ResourceEditor definition locations ----"
rg -n 'class ResourceEditor|def update\(' . --glob '*.py' || true

echo "---- installed package metadata if available ----"
python3 - <<'PY'
import importlib.util, site, os
mods = ['ovirt-engine-sdk-python', 'ovirt-engine-sdk-python3', 'ovirt_engine_sdk', 'vapi-runtime', 'vapi-bindings']
for mod in mods:
    spec = importlib.util.find_spec(mod)
    print(f"{mod}: {spec.origin if spec else 'not found'}")
import pkg_resources
try:
    for name in ['ovirt-engine-sdk-python', 'ovirt-engine-sdk-python3']:
        try:
            dist = pkg_resources.get_distribution(name)
            print(f"dist={dist.project_name} {dist.version} location={dist.location}")
        except pkg_resources.DistributionNotFound:
            pass
except Exception as e:
    print("pkg_resources failed:", e)
PY

echo "---- source around ResourceEditor from installed/vendored or path ----"
python3 - <<'PY'
import importlib.util, sys
for mod in ['ovirt_engine_sdk','ovirt-engine-sdk-python']:
    spec = importlib.util.find_spec(mod)
    print("spec", mod, spec)
PY

Repository: RedHatQE/openshift-virtualization-tests

Length of output: 970


🏁 Script executed on all repositories:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import urllib3, json
http = urllib3.PoolManager()
url = "https://api.github.com/repos/kubevirt/hyperconverged-cluster-operator/contents/config/crd/bases/hco.kubevirt.io_hyperconvergeds.yaml"
res = http.request("GET", url)
print("status", res.status)
if res.status == 200:
    data = json.loads(res.data)
    print("sha", data.get("sha"))
    print("content len", len(data.get("content","")))
    print("\nfeatureGates keys (first 20 lines of decoded content)")
    import base64
    txt = "\n".join(base64.b64decode(data["content"] + "===\n" * (3-len(data["content"]>%3))).decode().split("\n")[:40])
    print(txt)
PY

Length of output: 1030


🏁 Script executed (no clone):

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import urllib3, json, base64
http = urllib3.PoolManager()
url = "https://api.github.com/repos/kubevirt/hyperconverged-cluster-operator/contents/config/crd/bases/hco.kubevirt.io_hyperconvergeds.yaml"
res = http.request("GET", url)
print("status", res.status)
print("content type", res.headers.get("content-type"))
if res.status == 200:
    data = json.loads(res.data)
    lines_resolved = base64.b64decode(data["content"] + "==").decode().splitlines()
    feature_lines = [
        i for i, l in enumerate(lines_resolved, start=1)
        if "featureGates" in l
    ]
    begin = max(0, feature_lines[0]-10) if feature_lines else 0
    end = min(len(lines_resolved), feature_lines[-1]+25) if feature_lines else min(60, len(lines_resolved))
    for i in range(begin, end):
        print(f"{i+1:4}: {lines_resolved[i]}")
PY

echo "---- pypi openshift-python-utilities ResourceEditor docs/source ----"
python3 - <<'PY'
import urllib.request
url = "https://pypi.org/pypi/openshift-python-utilities/json"
print("getting pypi openshift-python-utilities", url)
try:
    with urllib.request.urlopen(url, timeout=30, context=urllib.request.create_default_context(cafile="/etc/ssl/certs/ca-certificates.crt")) as r:
        data = r.read().decode()
        print(data[:4000])
except Exception as e:
    print("pypi failed:", repr(e))
PY

Length of output: 245


🌐 Web query:

openshift-python-utilities ResourceEditor class update patches kubernetes client patch_type

💡 Result:

The ResourceEditor class in the openshift-python-wrapper (often associated with RedHatQE utilities) is used to perform bulk or complex updates on Kubernetes/OpenShift resources by applying patches [1]. When updating resources, the library leverages the underlying Kubernetes client (typically the DynamicClient) to execute these patches. In contexts like the mcp_server's update_resource function, the patch_type parameter supports three primary Kubernetes patch strategies [2][3][4]: 1. merge: The default patch type, which performs a JSON Merge Patch (RFC 7396) [2][3]. 2. strategic: Supports Strategic Merge Patch, which is particularly useful for resources with specific merge keys defined in the Kubernetes API [2][3]. 3. json: Supports JSON Patch (RFC 6902) [2][3]. While ResourceEditor simplifies the process of aggregating patches across multiple resources or fields before applying them [1], the underlying patch execution adheres to these standard Kubernetes client conventions [2][3]. When using the Resource class directly for updates, the update method often takes a resource dictionary representing the desired state or partial changes to be merged [5][6][7].

Citations:


🌐 Web query:

site:github.com/RedHatQE/openshift-python-wrapper class ResourceEditor update patches patch_type

💡 Result:

There is no standard class named ResourceEditor that uses the specific signature update patches patch_type in public documentation. However, in the context of the RedHatQE openshift-python-wrapper library, there is a function called update_resource that manages resource updates using patch operations and a patch_type parameter [1]. The update_resource function supports the following patch_type options for updating Kubernetes or OpenShift resources [1]: merge (default) strategic json When calling this function, the patch_type parameter determines how the provided patch data is applied to the target resource [1]. Example usage: update_resource( resource_type="deployment", name="my-app", namespace="default", patch={"spec": {"replicas": 3}}, patch_type="merge") [1]

Citations:


🌐 Web query:

"openpatch" "ResourceEditor" "openshift-python-wrapper"

💡 Result:

There is no known tool, class, or method named openpatch or ResourceEditor within the openshift-python-wrapper library [1][2][3]. In the openshift-python-wrapper, resource updates are handled via the Resource class using the update method, which performs a partial update (patch) [4][5]. To perform a partial update, you pass a dictionary containing the fields to be updated to the update method [4][5]. For example: deployment.update(resource_dict={"spec": {"replicas": 10}}) [4] For situations where a full replacement is required, such as removing existing fields, the library provides the update_replace method [5]. If you were referring to a different tool, openpatch and ResourceEditor do not appear in the official documentation or the codebase of the RedHatQE/openshift-python-wrapper project [1][3][5].

Citations:


🌐 Web query:

"openshift-python-wrapper" "ResourceEditor" "resource.py"

💡 Result:

The openshift-python-wrapper library does not appear to contain a class or component named ResourceEditor. The foundational base class for all Kubernetes and OpenShift resources in the library is named Resource, which is located in the ocp_resources/resource.py module [1][2][3]. The Resource class provides the standard interface for CRUD (Create, Read, Update, and Delete) operations, resource management, and schema validation across the library [1][2][3]. All specific resource implementations, such as Pod or Deployment, inherit from either Resource or its subclass, NamespacedResource [2][3]. The library documentation and codebase focus on the Resource class for managing cluster objects and utilize a class generator tool to automatically create resource classes from Kubernetes API schemas, rather than a ResourceEditor [4][5][6].

Citations:


🌐 Web query:

site:github.com/RedHatQE/openshift-python-wrapper "class ResourceEditor"

💡 Result:

There is no widely recognized or standardized class named ResourceEditor in mainstream software development or the queried RedHatQE/openshift-python-wrapper library [1][2][3][4]. The openshift-python-wrapper library provides various classes for interacting with Kubernetes and OpenShift resources (such as Pod, Namespace, and VirtualMachine), but it does not include a class specifically identified as ResourceEditor [1][2][4]. The term may refer to a custom, project-specific, or obscure class name not present in the searched authoritative technical documentation [1][3][4].

Citations:


🌐 Web query:

site:github.com/RedHatQE/openshift-python-utilities "class ResourceEditor" "ResourceEditor"

💡 Result:

The term ResourceEditor refers to several different classes and tools depending on the programming environment and context: 1. Spring Framework (Java): The org.springframework.core.io.ResourceEditor is a PropertyEditor implementation used to convert String-based resource locations (such as file paths, URLs, or classpath locations) into Spring Resource objects [1][2]. It is widely used within the Spring Framework to handle resource injection and configuration [3][4]. 2. Apache Sling: The Apache Sling Resource Editor is a web-based tool designed to visualize and edit content stored in the Apache Sling repository [5]. 3. Visual Studio (.NET/C#): Historically, Visual Studio included a ResourceEditor component within its project system to manage application resources (like bitmaps, strings, or files) [6][7]. Microsoft has been moving away from some of these legacy editors in favor of more modern project system implementations [6]. 4. Other Contexts: - LWUIT (Java ME): The ResourceEditor was a GUI tool used to design user interfaces and manage localization resources for Java ME applications [8][9]. - ResForge: The ResourceEditor protocol or class is used in tools like ResForge to handle specific Macintosh resource types [10]. Because ResourceEditor is a generic name, its specific function depends entirely on the framework or library being used [1][5][10][7].

Citations:


🌐 Web query:

"ResourceEditor" "OcpResources" "kubernetes"

💡 Result:

The terms "ResourceEditor" and "ocpResources" do not refer to standard, built-in features of the Kubernetes or OpenShift core APIs, but rather to components found in specific ecosystem tools and development frameworks. 1. ResourceEditor: This name generally refers to custom user interface components used for modifying Kubernetes resources. For example, it is used in: - The Headlamp Kubernetes UI (a plugin-based web interface) as a component for editing resource manifests [1]. - The OpenShift Console, which includes a YAMLEditorPage component used to view and edit resource YAML [2]. - Various external platforms or plugins that provide a browser-based YAML editor for Kubernetes objects [3]. 2. OcpResources: This term typically appears in two contexts related to the Red Hat OpenShift ecosystem: - OpenShift Python Wrapper: In this testing framework, OcpResources refers to a collection of Python classes that provide a structured way to interact with Kubernetes and OpenShift resources [4][5][6]. The library defines a base Resource class and subclasses (such as NamespacedResource) that handle CRUD operations, schema validation, and lifecycle management for various API objects [4][5][7]. - OpenShift/Hypershift Internal Logic: In the context of the Hypershift project (an OpenShift component), ocpResources is an internal list or registry used to track or test GroupVersionKinds (GVKs) present on a management cluster [8]. In summary, there is no single Kubernetes "ResourceEditor" or "OcpResources" core feature. If you are developing with OpenShift or testing against it, OcpResources likely refers to the Python wrapper library [4][5]. If you are working on a dashboard or UI, ResourceEditor likely refers to a specific component within your interface framework [2][1].

Citations:


🌐 Web query:

"ResourceEditor" "ocp_resources" "update" "patches"

💡 Result:

The term ResourceEditor in the context of ocp_resources generally refers to a utility component within OpenShift testing frameworks, specifically seen in repositories like RedHatQE's openshift-virtualization-tests [1][2]. In these contexts, ResourceEditor is a Python class or utility used to programmatically manage, modify, and update OpenShift Custom Resources (CRs) during test execution [1][2]. There is no standard, standalone OpenShift administrative command named ocp_resources update patches. If you are working with automated testing frameworks, the ResourceEditor utility typically provides methods to patch or update resource definitions (e.g., using the patch or update methods) to modify configurations [1][2]. If you are instead referring to patching or updating OpenShift resources in a general operational context: 1. Standard Patching: To update OpenShift resources via the CLI, you typically use oc patch <resource_type>/<resource_name> --patch '<patch_data>' --type=merge (or strategic). 2. Resource Editors: Various integrated development environments (IDEs) and tools (like the Kubernetes by Red Hat extension for IntelliJ) include their own GUI-based resource editors that allow you to modify YAML configurations directly within the cluster [3][4][5]. If your goal is to perform a specific update or patch via a framework, you should consult the documentation of the specific repository or toolset where you encountered the ResourceEditor class to understand its specific API and methods for applying updates [1][2].

Citations:


🌐 Web query:

"from ocp_resources import ResourceEditor"

💡 Result:

The ResourceEditor class is a component of the ocp_resources Python library (commonly referred to as the OpenShift Python Wrapper) [1]. This library is an open-source tool developed to provide a standardized, intuitive interface for interacting with Kubernetes and OpenShift cluster resources [2][3]. While specific documentation for ResourceEditor is less prominent than the core Resource base class [4][5], it is frequently used within the testing frameworks maintained by Red Hat QE (Quality Engineering) to facilitate the modification or management of cluster resources during test execution [1]. In the broader context of the ocp_resources library: - Purpose: The library simplifies CRUD (Create, Read, Update, Delete) operations, resource management, and cluster interaction [4][3]. - Core Concept: All resource types (e.g., Pod, Deployment, Namespace) inherit from a common Resource base class [6][5]. - Usage: Users typically interact with the library by first acquiring a client via get_client() [4][7]. - Ecosystem: It is designed to be highly compatible with testing workflows, offering support for context managers for automatic resource cleanup and resource-specific functionality like log streaming and command execution [2][3]. If you are working with a codebase containing from ocp_resources import ResourceEditor, it is likely part of an automated testing or cluster management suite designed to handle resource lifecycles or complex state modifications [1]. You can explore the library's official documentation for comprehensive details on standard resource operations [3][8].

Citations:


🌐 Web query:

"ocp_resources" "ResourceEditor" "patch_type" "merge"

💡 Result:

The term merge in the context of patch_type refers to the JSON Merge Patch strategy (defined in RFC 7396) used for updating Kubernetes or OpenShift resources [1][2][3]. In Kubernetes and OpenShift ecosystems—including kubectl/oc CLI tools, Python wrappers, and various operators—the patch_type parameter determines how a patch payload is applied to an existing object [4][5][2][6]. The merge patch strategy is one of three primary types [3]: 1. Merge Patch (patch_type: merge): Uses JSON Merge Patch [1][3]. It is a simple, intuitive way to merge JSON objects [2]. It is particularly useful for updates where you simply want to overwrite or add fields in a JSON structure [1][2]. However, it cannot be used to remove fields (setting a field to null effectively removes it) and it lacks the list-merging capabilities found in strategic merge patches [2][7]. 2. Strategic Merge Patch (patch_type: strategic): The default behavior for most native Kubernetes resources [2][6]. It is "Kubernetes-aware," meaning it uses metadata (such as patchMergeKey) defined in the API schema to intelligently merge lists rather than replacing them entirely [7][8]. Note that this type is generally not supported for Custom Resource Definitions (CRDs) [4][6]. 3. JSON Patch (patch_type: json): Uses RFC 6902 JSON Patch [1][2]. This provides precise, granular control over operations like add, remove, replace, move, and copy [1][2]. When using tools like oc patch, kubectl patch, or various library wrappers, you specify --type merge (or patch_type="merge") to explicitly invoke the JSON Merge Patch strategy [4][5][6]. This is often the required approach when working with CRDs or when specific field handling behavior that differs from the default strategic merge is needed [9].

Citations:


🌐 Web query:

"ocp_resources" "ResourceEditor" "oc patch"

💡 Result:

The terms in your query refer to two distinct contexts within the OpenShift ecosystem: command-line operations using the OpenShift CLI (oc) and internal components of the OpenShift Python automation framework. oc patch The command oc patch is a standard OpenShift CLI utility used to apply partial updates (patches) to existing resources on a cluster [1][2]. It allows you to modify specific fields without needing to replace the entire resource definition [3][4]. Common usage patterns include: - Strategic Merge Patch (default): Ideal for updating fields in existing objects [1][2]. oc patch <resource_type> <resource_name> -p '{"spec":{"key":"value"}}' - JSON Patch: Useful for precise operations like replacing or adding items in an array [1][2]. oc patch <resource_type> <resource_name> --type='json' -p='[{"op": "replace", "path": "/path/to/field", "value":"new_value"}]' ResourceEditor The term ResourceEditor (or ResourceYAMLEditor) typically refers to internal components used within the OpenShift Console web interface (often related to React components for editing resource YAML) [5] or class structures within the OpenShift Python Wrapper (a test/automation library) [6][7][8]. In the context of the OpenShift Python Wrapper (frequently used by Red Hat QE), resources are managed via Python classes (e.g., Pod, Deployment) that inherit from a base Resource class [6][8]. In this library, patching or updating a resource is handled through methods like.update, which accepts a dictionary representing the desired changes [7][8][9]. It does not involve the oc patch command directly, but rather performs API calls to achieve the same result programmatically [7][9]. If you are encountering these terms together in an error message or log, you may be using an automation tool that wraps oc commands or interacts with the OpenShift API; checking the documentation for the specific framework or library you are using is recommended [6][8].

Citations:


🌐 Web query:

"ocp_resources" "ResourceEditor" "Resource" "backup_resources"

💡 Result:

The query terms provided do not correspond to a single integrated feature or official OpenShift/Kubernetes command. Instead, they appear to be a mix of separate concepts and third-party projects related to OpenShift resource management and backups [1][2][3]. 1. OADP (OpenShift API for Data Protection): This is the official Red Hat solution for backing up and restoring OpenShift applications [1][2]. It uses custom resources (CRs) such as Backup, Restore, and Schedule to manage data protection [1][2]. It does not utilize a specific tool called "ResourceEditor" for this purpose [1][2]. 2. ResourceEditor: This term is associated with KubeStash and the Appscode ecosystem (kmodules), which provides tools for managing Kubernetes resources and backup configurations [4]. It is not a standard component of OpenShift's native backup solution (OADP) [1][2]. 3. ocp_resources: This appears to be a reference to a Python utility library used in OpenShift QE and testing environments (e.g., ocp-resources or openshift-python-wrapper) for interacting with the Kubernetes API programmatically [3]. If you are attempting to perform backups in OpenShift, the authoritative method is using OADP [1][2]. You create a Backup custom resource to define which resources to include or exclude [1][5]. You can preview resources by running dry-run operations or using Velero commands before committing to a full backup [6][7]. For more granular resource discovery to assist in backup planning, tools like the oc get-resources plugin exist in the broader Kubernetes/OpenShift community to audit namespace and cluster-scoped resources [8].

Citations:


Preserve existing spec.featureGates entries.

ResourceEditor applies these patches as resource updates, and HCOv1Spec.feature_gates(incrementalBackup=True) produces only {"featureGates": [{"name": "incrementalBackup"}]}. A merge update on spec.featureGates will replace the existing list, which can remove other configured gates. Build the target list from the existing feature gates and add/modify incrementalBackup, or include both the existing entries and the new selector in one preserved patch payload.

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

In `@tests/storage/cbt/conftest.py` around lines 50 - 56, The CBT fixture setup
must preserve existing spec.featureGates entries instead of replacing them with
only incrementalBackup. Update the merged_spec construction around
HCOv1Spec.feature_gates and ResourceEditorValidateHCOReconcile to derive the
target feature-gate list from the current resource, then add or update
incrementalBackup while retaining all existing gates.

Comment thread utilities/hco.py
Comment on lines +98 to +106
fg_description = v1_version["schema"]["openAPIV3Schema"]["properties"]["spec"]["properties"]["featureGates"].get(
"description", ""
)
phases = dict(_FG_PHASE_RE.findall(fg_description))
if not phases:
raise ValueError(
f"Failed to parse FG phases from HCO CRD — format may have changed. "
f"Description starts with: {fg_description[:200]!r}"
)

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

HIGH: Normalize missing schema keys to the documented ValueError.

If the CRD moves or removes spec.featureGates.description, Line 98 raises KeyError. The session fixture then fails with no schema context. This contradicts the function contract that changed or unavailable v1 schema produces ValueError.

Catch the missing-key case and re-raise ValueError with the HCO schema path and exception context. Add a unit test for a v1 version that lacks spec.featureGates.

Proposed fix
-        fg_description = v1_version["schema"]["openAPIV3Schema"]["properties"]["spec"]["properties"]["featureGates"].get(
-            "description", ""
-        )
+        try:
+            fg_description = v1_version["schema"]["openAPIV3Schema"]["properties"]["spec"]["properties"][
+                "featureGates"
+            ].get("description", "")
+        except KeyError as exception:
+            raise ValueError("HCO v1 schema does not contain spec.featureGates.description") from exception
+
+        if not isinstance(fg_description, str):
+            raise ValueError("HCO v1 schema has a non-string spec.featureGates.description")
📝 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
fg_description = v1_version["schema"]["openAPIV3Schema"]["properties"]["spec"]["properties"]["featureGates"].get(
"description", ""
)
phases = dict(_FG_PHASE_RE.findall(fg_description))
if not phases:
raise ValueError(
f"Failed to parse FG phases from HCO CRD — format may have changed. "
f"Description starts with: {fg_description[:200]!r}"
)
try:
fg_description = v1_version["schema"]["openAPIV3Schema"]["properties"]["spec"]["properties"][
"featureGates"
].get("description", "")
except KeyError as exception:
raise ValueError("HCO v1 schema does not contain spec.featureGates.description") from exception
if not isinstance(fg_description, str):
raise ValueError("HCO v1 schema has a non-string spec.featureGates.description")
phases = dict(_FG_PHASE_RE.findall(fg_description))
if not phases:
raise ValueError(
f"Failed to parse FG phases from HCO CRD — format may have changed. "
f"Description starts with: {fg_description[:200]!r}"
)
🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 100-100: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: _FG_PHASE_RE.findall(fg_description)
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)

🪛 Ruff (0.16.1)

[warning] 103-106: Avoid specifying long messages outside the exception class

(TRY003)

🤖 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 `@utilities/hco.py` around lines 98 - 106, Update the v1 schema traversal that
computes fg_description to catch missing-key failures, including an absent
spec.featureGates path, and re-raise ValueError with the HCO schema path and
original exception context. Preserve the existing ValueError for unparseable
phases, and add a unit test covering a v1 schema without spec.featureGates.

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5952.

Overlapping files

uv.lock

hmeir and others added 9 commits August 10, 2026 18:47
Introduce HCOv1Spec callable spec group builders and FG helpers in
utilities/constants/hco.py. Add parse_hco_fg_phases() to read FG phase
defaults from the CRD at runtime. Remove the v1beta1 API version override
in get_hyperconverged_resource(). Bump openshift-python-wrapper to 11.0.139
which includes the v1-regenerated HyperConverged class. Update all central
HCO utility functions to use v1 grouped spec paths.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert all HCO spec patches and reads in install_upgrade_operators
to use v1 grouped structure via HCOv1Spec builders. Migrate feature
gate patches from dict to list format. Remove dead FG constants and
the unused multiarch block in expected_value fixture.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert HCO spec patches in storage tests to use HCOv1Spec builders
for storage, virtualization, and security groups. Migrate feature gate
patches from dict to list format.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert HCO spec patches in virt tests to use HCOv1Spec builders
for virtualization group (permittedHostDevices, virtualMachineOptions,
ksmConfiguration, evictionStrategy). Migrate feature gate patches
from dict to list format.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert kubeMacPoolConfiguration patches and reads to use
HCOv1Spec.networking() and v1 grouped spec paths.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert featureGates patches in vhostmd tests and dataImportCronTemplates
patches in golden_images tests to use HCOv1Spec builders.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert vmStateStorageClass patch to use HCOv1Spec.storage().

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 15 new tests covering HCOv1Spec spec group builders,
feature_gates() (enable/disable/multiple), is_fg_enabled() (explicit,
default beta/alpha, unknown FG), and CRD-based FG phase parsing.
Update existing test mocks from v1beta1 flat format to v1 grouped
structure.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add HCO v1 API Usage (MANDATORY) section requiring HCOv1Spec builders
for all HCO spec patches, v1 list format for feature gates, and
is_fg_enabled() for FG state reads.

Signed-off-by: Harel Meir <hmeir@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5922.

Overlapping files

tests/conftest.py

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5877.

Overlapping files

pyproject.toml
uv.lock

@vsibirsk vsibirsk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

pr link in the description points to wrong repo (tests instead on python wrapper :) )

with ResourceEditorValidateHCOReconcile(
admin_client=admin_client,
patches={hyperconverged_resource_scope_function: {"spec": {EVICTIONSTRATEGY: "None"}}},
patches={hyperconverged_resource_scope_function: HCOv1Spec.virtualization(**{EVICTIONSTRATEGY: "None"})},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why not evictionStrategy=None?

Z_STREAM = "z-stream"


class _SpecGroup:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

return current


class HCOv1Spec:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ditto

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5672.

Overlapping files

tests/conftest.py

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5975.

Overlapping files

tests/install_upgrade_operators/conftest.py

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5708.

Overlapping files

tests/storage/test_hotplug.py

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #5674.

Overlapping files

tests/conftest.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants