Skip to content

feat: add JSON Schema for .providers.json - #561

Merged
myakove merged 3 commits into
mainfrom
feat/issue-560-providers-json-schema
Jun 18, 2026
Merged

myakove merged 3 commits into
mainfrom
feat/issue-560-providers-json-schema

Conversation

@myakove

@myakove myakove commented Jun 18, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Add a JSON Schema file (providers_schema.json) for .providers.json to enable IDE autocomplete/validation and provide AI code reviewers with authoritative required vs optional field definitions.

Changes

  1. providers_schema.json — Full schema with discriminated union on type field:

    • vsphere (incl. copyoffload with vendor-conditional fields)
    • ovirt, openstack, openshift, ova
    • Required/optional field definitions matching codebase access patterns
  2. .providers.json.example — Added $schema pointer to raw GitHub URL

  3. AGENTS.md — Two new MUST rules:

    • Provider Config Key Access: check schema for required vs optional
    • Schema and Example Maintenance: update both files when adding new properties
  4. CLAUDE.md — Replaced symlink with @AGENTS.md reference (Claude Code native feature)

  5. README.md — Added schema documentation

Closes #560

Summary by CodeRabbit

  • New Features

    • Introduced JSON Schema for provider configuration validation, enabling IDE autocomplete and validation for .providers.json files
  • Documentation

    • Updated .providers.json documentation with schema and IDE support guidance
    • Consolidated and expanded project guidelines documentation

@redhat-qe-bot

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: Disabled for this repository
  • 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: All label categories are enabled (default configuration)

📋 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 (approvers only)
  • /hold cancel - Unblock PR merging
  • /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)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and 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 conventional-title - Validate commit message format
  • /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. Status Checks: All required status checks must pass
  3. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  4. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • krcmarik
  • myakove
  • solenoci

Reviewers:

  • krcmarik
  • myakove
  • solenoci
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge
AI Features
  • Conventional Title: Mode: fix (claude/claude-opus-4-6[1m])
  • Cherry-Pick Conflict Resolution: Enabled (claude/claude-opus-4-6[1m])
  • Test Oracle: Triggers: approved (cursor/gpt-5.4-xhigh-fast); /test-oracle can be used anytime
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

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

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add JSON Schema for .providers.json with docs and agent guidance
✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

Description

• Add providers_schema.json to validate .providers.json and enable IDE autocomplete.
• Point .providers.json.example to the published schema URL for editor integration.
• Document schema usage and maintenance rules in README.md and agent guidelines.
Diagram

graph TD
  A["Developer / IDE"] --> B[".providers.json"] --> C["providers_schema.json"]
  D[".providers.json.example"] --> C --> E["README.md"]
  F["CLAUDE.md"] --> G["AGENTS.md"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use oneOf per provider type (discriminated union)
  • ➕ Often yields better editor autocomplete than if/then chains for variant objects
  • ➕ Clearer separation of required fields per provider type
  • ➖ More verbose schema (duplicates base fields or requires careful allOf factoring)
  • ➖ May require reworking current conditional requirements for copy-offload/vendor fields
2. Provide a local schema reference option (repo-relative)
  • ➕ Works offline and on forks without relying on raw GitHub URLs
  • ➕ Avoids schema drift if main changes while users pin older configs
  • ➖ Editors vary in support for relative $schema resolution
  • ➖ Still need a canonical hosted URL for wider tooling support
3. Version the schema URL by release/tag
  • ➕ Stable schema for consumers; avoids breaking validation when schema evolves
  • ➕ Clearer upgrade path across schema changes
  • ➖ Requires a publishing/versioning process and documentation
  • ➖ Users may not update schema version promptly

Recommendation: The PR’s approach (shipping a canonical Draft 2020-12 schema, referencing it from the example, and documenting maintenance rules) is solid and immediately useful. If editor autocomplete fidelity becomes an issue, consider refactoring providerDefinition into oneOf branches keyed by type, and/or adding a versioned schema URL for stability; otherwise the current design is an effective baseline.

Files changed (5) +1393 / -961

Enhancement (1) +398 / -0
providers_schema.jsonAdd Draft 2020-12 JSON Schema for provider configuration +398/-0

Add Draft 2020-12 JSON Schema for provider configuration

• Introduces a JSON Schema for '.providers.json' with common required provider fields plus conditional/provider-specific properties for 'vsphere', 'ovirt', 'openstack', 'openshift', and 'ova'. Includes nested 'copyoffload' configuration with vendor- and method-conditional required fields to match expected access patterns and reduce config drift.

providers_schema.json

Documentation (3) +994 / -961
AGENTS.mdIntroduce centralized agent/contributor rules including schema maintenance +985/-0

Introduce centralized agent/contributor rules including schema maintenance

• Adds a comprehensive project instruction document, including new MUST rules for '.providers.json' key access patterns based on schema required/optional status and a requirement to update both schema and example when adding provider fields. Serves as the single source of truth for AI workflow and codebase standards.

AGENTS.md

CLAUDE.mdReplace duplicated instructions with reference to AGENTS.md +2/-961

Replace duplicated instructions with reference to AGENTS.md

• Replaces the previous large instruction content with a short entry-point that references 'AGENTS.md' using Claude’s native '@AGENTS.md' include mechanism. This reduces duplication and keeps guidance centralized.

CLAUDE.md

README.mdDocument providers schema usage for IDE support +7/-0

Document providers schema usage for IDE support

• Adds a short README section explaining that 'providers_schema.json' defines required vs optional fields and shows how to add '$schema' to '.providers.json' for autocomplete/validation. Improves discoverability for contributors configuring providers.

README.md

Other (1) +1 / -0
.providers.json.exampleAdd $schema pointer to hosted providers schema +1/-0

Add $schema pointer to hosted providers schema

• Adds a top-level '$schema' field pointing to the raw GitHub URL for 'providers_schema.json'. This enables editor validation/autocomplete when users copy the example to '.providers.json'.

.providers.json.example

@coderabbitai

coderabbitai Bot commented Jun 18, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@myakove, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 29 minutes and 35 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

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 credits.

🚦 How do rate limits work?

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

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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a1c2a9df-071b-4da2-a6c5-b3ee8bf0ade5

📥 Commits

Reviewing files that changed from the base of the PR and between 6da69d5 and 97d0259.

📒 Files selected for processing (7)
  • .providers.json.example
  • AGENTS.md
  • AGENTS.md
  • CLAUDE.md
  • README.md
  • cli/mtv_api_tests/run.py
  • providers_schema.json

Walkthrough

Adds providers_schema.json as a JSON Schema for .providers.json with type-discriminated conditional validation for vsphere, ovirt, openstack, openshift, and ova providers. Updates .providers.json.example with a $schema pointer and adds schema documentation to README.md. Consolidates all AI coding guidelines from CLAUDE.md into a new AGENTS.md, and reduces CLAUDE.md to a two-line @AGENTS.md reference stub.

Changes

providers_schema.json, example file, README, and AI instructions consolidation

Layer / File(s) Summary
providers_schema.json: root, guestCredentials, copyoffloadConfig
providers_schema.json
Root schema maps provider names to providerDefinition. guestCredentials defines optional Linux/Windows VM credential fields. copyoffloadConfig enforces a required base property set plus allOf/if/then branches for vendor-specific fields and esxi_clone_method=ssh host connection requirements.
providers_schema.json: providerDefinition with type-conditional branches
providers_schema.json
providerDefinition enforces six common required fields (type, version, fqdn, api_url, username, password) and applies conditional allOf branches: expanded vsphere endpoint/clone/copyoffload/encryption properties, guest-credential boolean enforcement for ovirt/openstack/ova, and a no-extra-properties branch for openshift.
Schema reference in example file and README
.providers.json.example, README.md
.providers.json.example gains a $schema pointer to the raw GitHub URL. README.md gains a "Schema & IDE support" section with the $schema entry example and the published schema URL.
AGENTS.md: full AI workflow and coding rules
AGENTS.md
New 985-line file specifying AI workflow (branching, agent routing, mandatory post-change review, pre-commit), code standards (type annotations, uv, logging format, import constraints), OpenShift/K8s interaction rules, exception-handling requirements, determinism/fail-fast rules, schema maintenance requirements, test architecture patterns (5-step class-based flow with copy-offload/shared-disk variants), fixture/conftest organization, cleanup fixture behavior, pytest marker requirements, and pytest-xdist parallel execution rules.
CLAUDE.md reduced to @AGENTS.md reference
CLAUDE.md
961 lines of prior instruction content removed; file now contains only a # Project Guidelines header and an @AGENTS.md delegation line.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change—adding a JSON Schema for .providers.json to enable IDE support and validation.
Linked Issues check ✅ Passed All requirements from issue #560 are met: schema file created with discriminated union, $schema reference added, AGENTS.md rules documented, symlink replaced, and README updated.
Out of Scope Changes check ✅ Passed All changes directly support the schema feature: providers_schema.json, .providers.json.example update, AGENTS.md rules, CLAUDE.md refactor, and README documentation are all in-scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-560-providers-json-schema

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 and usage tips.

@qodo-code-review

qodo-code-review Bot commented Jun 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 49 rules

Grey Divider


Action required

1. $schema breaks CLI run ✓ Resolved 🐞 Bug ≡ Correctness
Description
Adding a top-level "$schema" string entry to .providers.json (as shown in the updated example)
causes mtv-api-tests run to exit because it currently requires every top-level value to be a JSON
object (dict). Users following the new example/README guidance will be unable to run tests via the
CLI.
Code

.providers.json.example[2]

+  "$schema": "https://raw.githubusercontent.com/RedHatQE/mtv-api-tests/main/providers_schema.json",
Evidence
The PR adds a top-level $schema key whose value is a string, but the CLI explicitly errors if any
top-level value is not a dict and also uses v.get(...) assuming dict values.

.providers.json.example[1-5]
cli/mtv_api_tests/run.py[301-328]
cli/mtv_api_tests/run.py[26-64]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The CLI `mtv-api-tests run` rejects any `.providers.json` top-level entry whose value is not a JSON object. With the PR’s new recommended top-level `"$schema"` key (string), the CLI fails early with "entries must be JSON objects".

## Issue Context
The PR adds `"$schema"` to `.providers.json.example` for IDE validation. The CLI should treat `"$schema"` as metadata and ignore it during provider validation/selection.

## Fix Focus Areas
- cli/mtv_api_tests/run.py[26-108]
- cli/mtv_api_tests/run.py[301-345]

### Implementation notes
- Before validating/iterating providers, strip metadata keys (at least `"$schema"`) or filter to dict values.
- Update comprehensions like `{k: v for k, v in providers.items() if v.get("type") == ...}` to safely handle non-dict values (or use the filtered dict).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. OpenShift schema mismatch ✓ Resolved 🐞 Bug ≡ Correctness
Description
providers_schema.json requires fqdn for all provider types and defines OpenShift as having no
additional properties, but the CLI generate/run logic uses OpenShift provider entries with host
and storage_class (and optional verify_ssl/ca_bundle). This makes schema
validation/autocomplete incorrect for the generated/consumed OpenShift provider config.
Code

providers_schema.json[R367-376]

+        {
+          "if": {
+            "properties": {
+              "type": { "const": "openshift" }
+            },
+            "required": ["type"]
+          },
+          "then": {
+            "description": "OpenShift provider requires only the common base fields; no additional properties."
+          }
Evidence
The schema requires fqdn universally and says OpenShift has no extra properties, but the
CLI-generated OpenShift provider config includes host and storage_class, and the CLI runtime
reads those fields.

providers_schema.json[230-240]
providers_schema.json[367-376]
cli/mtv_api_tests/common.py[726-765]
cli/mtv_api_tests/run.py[110-142]
cli/mtv_api_tests/run.py[336-344]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The OpenShift provider schema does not match the actual `.providers.json` contract used by the CLI.
- Schema requires `fqdn` for all providers.
- OpenShift branch states there are no additional properties.
But the CLI constructs/consumes OpenShift providers with `host` and `storage_class` (and optional `verify_ssl`/`ca_bundle`).

## Issue Context
`build_ocp_provider()` writes OpenShift provider entries that omit `fqdn` and include `host`/`storage_class`. `run.py` reads `host` for cluster auth and `storage_class` for defaulting.

## Fix Focus Areas
- providers_schema.json[230-376]
- cli/mtv_api_tests/common.py[726-765]
- cli/mtv_api_tests/run.py[110-146]
- cli/mtv_api_tests/run.py[336-344]

### Implementation notes
- Update the OpenShift schema branch to include `host`, `storage_class`, and optionally `verify_ssl`/`ca_bundle`.
- Make `fqdn` conditional (required for other provider types, not required for OpenShift) or restructure the base required list accordingly.
- Consider explicitly documenting which fields are used for OpenShift destination vs OpenShift source (if both are supported).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. providerDefinition lacks oneOf union 📎 Requirement gap ⚙ Maintainability
Description
providers_schema.json models provider variants using allOf + if/then blocks instead of a
type-keyed discriminated union (e.g., oneOf/anyOf with per-variant schemas). This may prevent
tooling from treating vsphere/ovirt/openstack/openshift/ova as distinct variants and
violates the checklist requirement.
Code

providers_schema.json[R230-395]

+    "providerDefinition": {
+      "type": "object",
+      "description": "A source provider configuration defining connection, authentication, and provider-specific settings.",
+      "required": [
+        "type",
+        "version",
+        "fqdn",
+        "api_url",
+        "username",
+        "password"
+      ],
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": ["vsphere", "ovirt", "openstack", "openshift", "ova"],
+          "description": "Provider type determining the virtualization platform."
+        },
+        "version": {
+          "type": "string",
+          "description": "Provider platform version (e.g. '8.0.3' for vSphere, '4.4.9' for oVirt, 'psi' for OpenStack)."
+        },
+        "fqdn": {
+          "type": "string",
+          "description": "Fully qualified domain name or IP address of the provider endpoint."
+        },
+        "api_url": {
+          "type": "string",
+          "description": "Full API URL for provider communication (e.g. 'https://vcenter.example.com/sdk' for vSphere, NFS path for OVA)."
+        },
+        "username": {
+          "type": "string",
+          "description": "Username for authenticating with the provider API."
+        },
+        "password": {
+          "type": "string",
+          "description": "Password for authenticating with the provider API."
+        }
+      },
+      "allOf": [
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "vsphere" }
+            },
+            "required": ["type"]
+          },
+          "then": {
+            "$ref": "#/$defs/guestCredentials",
+            "properties": {
+              "endpoint_type": {
+                "type": "string",
+                "enum": ["vcenter", "esxi"],
+                "description": "vSphere endpoint type: 'vcenter' for vCenter Server, 'esxi' for direct ESXi host connection."
+              },
+              "vddk_init_image": {
+                "type": "string",
+                "description": "Container image reference for the VDDK init container used during vSphere migrations (e.g. 'quay.io/rh-openshift-mtv/vddk-init-image:8.0.1')."
+              },
+              "clone_provider": {
+                "type": "string",
+                "description": "Name of a vCenter provider entry (key in this config) used for ESXi cloning when endpoint_type is 'esxi'."
+              },
+              "luks_passphrase": {
+                "type": "string",
+                "description": "LUKS encryption passphrase for decrypting encrypted VM disks during migration."
+              },
+              "copyoffload": {
+                "$ref": "#/$defs/copyoffloadConfig"
+              },
+              "guest_vm_linux_user": true,
+              "guest_vm_linux_password": true,
+              "guest_vm_win_user": true,
+              "guest_vm_win_password": true
+            }
+          }
+        },
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "ovirt" }
+            },
+            "required": ["type"]
+          },
+          "then": {
+            "$ref": "#/$defs/guestCredentials",
+            "properties": {
+              "guest_vm_linux_user": true,
+              "guest_vm_linux_password": true,
+              "guest_vm_win_user": true,
+              "guest_vm_win_password": true
+            }
+          }
+        },
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "openstack" }
+            },
+            "required": ["type"]
+          },
+          "then": {
+            "$ref": "#/$defs/guestCredentials",
+            "required": [
+              "user_domain_name",
+              "region_name",
+              "project_name",
+              "user_domain_id",
+              "project_domain_id"
+            ],
+            "properties": {
+              "user_domain_name": {
+                "type": "string",
+                "description": "OpenStack Keystone user domain name (e.g. 'redhat.com')."
+              },
+              "region_name": {
+                "type": "string",
+                "description": "OpenStack region name (e.g. 'regionOne')."
+              },
+              "project_name": {
+                "type": "string",
+                "description": "OpenStack project/tenant name for scoping API requests."
+              },
+              "user_domain_id": {
+                "type": "string",
+                "description": "OpenStack Keystone user domain UUID."
+              },
+              "project_domain_id": {
+                "type": "string",
+                "description": "OpenStack Keystone project domain UUID."
+              },
+              "guest_vm_linux_user": true,
+              "guest_vm_linux_password": true,
+              "guest_vm_win_user": true,
+              "guest_vm_win_password": true
+            }
+          }
+        },
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "openshift" }
+            },
+            "required": ["type"]
+          },
+          "then": {
+            "description": "OpenShift provider requires only the common base fields; no additional properties."
+          }
+        },
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "ova" }
+            },
+            "required": ["type"]
+          },
+          "then": {
+            "$ref": "#/$defs/guestCredentials",
+            "properties": {
+              "guest_vm_linux_user": true,
+              "guest_vm_linux_password": true,
+              "guest_vm_win_user": true,
+              "guest_vm_win_password": true
+            }
+          }
+        }
+      ]
Evidence
PR Compliance ID 178450 requires a discriminated union on the provider type field with explicit
variants for all provider types. The added schema instead defines providerDefinition with an
allOf list of if/then clauses for each type value, without a oneOf/anyOf union
construct.

Schema uses discriminated union on provider 'type' field for all provider types
providers_schema.json[230-395]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`providers_schema.json` is required to use a `type`-keyed discriminated union for provider variants, but the current schema uses `allOf` with multiple `if/then` blocks.

## Issue Context
The compliance checklist explicitly expects a discriminated union (e.g., `oneOf`/`anyOf`) with explicit variants for `vsphere`, `ovirt`, `openstack`, `openshift`, and `ova` so IDEs/validators can infer variant-specific required/optional fields.

## Fix Focus Areas
- providers_schema.json[230-395]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Copyoffload required keys wrong 🐞 Bug ≡ Correctness
Description
providers_schema.json marks copy-offload credentials and default_vm_name as always required, but the
harness accepts credentials from environment variables and only uses default_vm_name when present.
This makes the schema reject configurations that the code accepts, undermining the schema’s
“authoritative required vs optional” purpose.
Code

providers_schema.json[R40-50]

+    "copyoffloadConfig": {
+      "type": "object",
+      "description": "Copy-offload (XCOPY) configuration for hardware-accelerated migration via storage array APIs.",
+      "required": [
+        "storage_vendor_product",
+        "datastore_id",
+        "default_vm_name",
+        "storage_hostname",
+        "storage_username",
+        "storage_password"
+      ],
Evidence
The schema requires fields that the code explicitly allows to be absent: storage credentials can be
supplied via env vars and default_vm_name is accessed with .get() and used only if non-empty.

providers_schema.json[40-50]
tests/copyoffload/conftest.py[72-90]
utilities/copyoffload_migration.py[33-58]
conftest.py[1024-1032]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`providers_schema.json` currently requires `default_vm_name`, `storage_hostname`, `storage_username`, and `storage_password` inside `copyoffload`, but the runtime code treats `default_vm_name` as optional and allows storage credentials to come from environment variables.

## Issue Context
- Storage credentials are resolved via `get_copyoffload_credential()` (env var wins), so the JSON file can legitimately omit these keys.
- `default_vm_name` is only applied when present.

## Fix Focus Areas
- providers_schema.json[40-50]
- providers_schema.json[71-86]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Schema snippet unclear 🐞 Bug ⚙ Maintainability
Description
README.md shows the $schema line inside a ```json block, but the snippet is only a fragment (not a
complete JSON object), which can mislead users into copying it incorrectly. Clarifying with a full
minimal example (or explicitly labeling it as a fragment to insert) avoids configuration mistakes.
Code

README.md[R195-200]

+> **Schema & IDE support:** `providers_schema.json` documents which fields are required vs optional
+> per provider type. Add `"$schema"` to your `.providers.json` for IDE autocomplete:
+>
+> ```json
+> "$schema": "https://raw.githubusercontent.com/RedHatQE/mtv-api-tests/main/providers_schema.json"
+> ```
Evidence
The current README block contains only a single key/value line presented as JSON, without showing
where it goes in the actual .providers.json object structure.

README.md[195-200]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The README presents a `$schema` example as `json`, but it’s a fragment without surrounding braces/context. This is easy to miscopy into `.providers.json`.

## Issue Context
Users commonly paste code blocks verbatim; a complete minimal object (or an explicit “insert this field at the top of your existing object” note) reduces confusion.

## Fix Focus Areas
- README.md[195-200]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread providers_schema.json Resolved
Comment thread providers_schema.json Resolved
Comment thread README.md Resolved
…eference

- Add providers_schema.json with full provider type definitions (vsphere, ovirt,
  openstack, openshift, ova) including copyoffload vendor-conditional fields
- Update .providers.json.example with $schema reference
- Add AGENTS.md rules for provider config key access and schema maintenance
- Replace CLAUDE.md ↔ AGENTS.md symlink with @AGENTS.md reference
- Update README.md with schema documentation

Closes #560
@myakove
myakove force-pushed the feat/issue-560-providers-json-schema branch from 6da69d5 to 58e9e96 Compare June 18, 2026 10:52

@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 `@providers_schema.json`:
- Around line 43-50: The schema's required array incorrectly marks credentials
as mandatory even though the copyoffload_migration.py utility allows these to be
provided via environment variables (COPYOFFLOAD_STORAGE_HOSTNAME,
COPYOFFLOAD_ESXI_HOST, etc.), causing false validation failures for users
relying on env vars. Remove the env-overridable credential fields
(storage_hostname, storage_username, storage_password) from the required arrays
at lines 43-50 and line 225 since schema validation should not enforce
runtime-resolved values. Additionally, the OpenShift provider constraint's then
block at line 375 lacks schema enforcement for its stated "no additional
properties" restriction. Add "additionalProperties": false to the then block at
line 375 to properly enforce this constraint.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c6f6c892-fd64-4ea2-a769-eaa924cf6ed4

📥 Commits

Reviewing files that changed from the base of the PR and between 21e5dbc and 6da69d5.

📒 Files selected for processing (6)
  • .providers.json.example
  • AGENTS.md
  • AGENTS.md
  • CLAUDE.md
  • README.md
  • providers_schema.json

Comment thread providers_schema.json Resolved
Comment thread .providers.json.example Resolved
Comment thread providers_schema.json Resolved
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 58e9e96

- Restructure providerDefinition to use oneOf discriminated union
- Remove env-overridable credentials from copyoffload required list
- Fix README schema snippet to show full JSON object example
- Add additionalProperties: false to OpenShift provider variant
@myakove

myakove commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

@qodo-code-review[bot]

The following review comments were reviewed and a decision was made:

providers_schema.json:230 (qodo requirement gap) — providerDefinition lacks oneOf union

Addressed: Restructured providerDefinition to use oneOf discriminated union with 5 self-contained variant schemas (vsphere, ovirt, openstack, openshift, ova), each with const type value.

providers_schema.json:40 (qodo bug) — Copyoffload required keys wrong

Addressed: Removed default_vm_name, storage_hostname, storage_username, storage_password from copyoffloadConfig required list. Only storage_vendor_product and datastore_id remain required — credentials can come from environment variables.

README.md:195 (qodo bug) — Schema snippet unclear

Addressed: Replaced bare JSON fragment with a full minimal .providers.json object example showing $schema as the first key alongside provider entries.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
@qodo-code-review

Copy link
Copy Markdown

code-review[bot]

The following review comments were reviewed and a decision was made:

providers_schema.json:230 (qodo requirement gap) — providerDefinition lacks oneOf union

Addressed: Restructured providerDefinition to use oneOf discriminated union with 5 self-contained variant schemas (vsphere, ovirt, openstack, openshift, ova), each with const type value.

providers_schema.json:40 (qodo bug) — Copyoffload required keys wrong

Addressed: Removed default_vm_name, storage_hostname, storage_username, storage_password from copyoffloadConfig required list. Only storage_vendor_product and datastore_id remain required — credentials can come from environment variables.

README.md:195 (qodo bug) — Schema snippet unclear

Addressed: Replaced bare JSON fragment with a full minimal .providers.json object example showing $schema as the first key alongside provider entries.

Thanks — the review decisions line up with the diff:

  • finding 3 is addressed by the new oneOf discriminated union in providers_schema.json.
  • finding 4 is addressed by trimming copyoffloadConfig.required down to just storage_vendor_product and datastore_id.
  • finding 5 is addressed by the clearer minimal .providers.json example in README.md.

Two items still look active in the index:

  • finding 1: adding "$schema" to .providers.json.example may affect CLI parsing if the loader treats it as a provider entry.
  • finding 2: the OpenShift branch in providers_schema.json may still need a schema-structure adjustment.

If you want, I can also help verify whether finding 1 and finding 2 are now safe to close or still need a follow-up.

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 9b6c573

- Skip $schema key during .providers.json validation in CLI run command
- Add isinstance(v, dict) guards to provider comprehensions
- Fix OpenShift schema: use host instead of fqdn, add storage_class/verify_ssl/ca_bundle
- Update .providers.json.example OpenShift section to match
@qodo-code-review

Copy link
Copy Markdown

Looking for bugs?

Check back in a few minutes. Qodo's review agents are on it.

@myakove

myakove commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

@qodo-code-review[bot]

The following review comments were reviewed and a decision was made:

.providers.json.example:2 (qodo bug) — $schema breaks CLI run

Addressed: Fixed — added _METADATA_KEYS set to skip $schema during validation, and added isinstance(v, dict) guards to provider comprehensions in run.py.

providers_schema.json:367 (qodo bug) — OpenShift schema mismatch

Addressed: Fixed — OpenShift variant now uses host (not fqdn), includes storage_class (required), verify_ssl and ca_bundle (optional). Updated .providers.json.example to match.

providers_schema.json:230 (qodo requirement gap) — providerDefinition lacks oneOf union

Addressed: Already fixed in previous commit — schema uses oneOf discriminated union with 5 self-contained variant schemas.

providers_schema.json:40 (qodo bug) — Copyoffload required keys wrong

Addressed: Already fixed in previous commit — only storage_vendor_product and datastore_id remain required.

README.md:195 (qodo bug) — Schema snippet unclear

Addressed: Already fixed in previous commit — README shows full JSON object example.

@qodo-code-review

Copy link
Copy Markdown

code-review[bot]

The following review comments were reviewed and a decision was made:

.providers.json.example:2 (qodo bug) — $schema breaks CLI run

Addressed: Fixed — added _METADATA_KEYS set to skip $schema during validation, and added isinstance(v, dict) guards to provider comprehensions in run.py.

providers_schema.json:367 (qodo bug) — OpenShift schema mismatch

Addressed: Fixed — OpenShift variant now uses host (not fqdn), includes storage_class (required), verify_ssl and ca_bundle (optional). Updated .providers.json.example to match.

providers_schema.json:230 (qodo requirement gap) — providerDefinition lacks oneOf union

Addressed: Already fixed in previous commit — schema uses oneOf discriminated union with 5 self-contained variant schemas.

providers_schema.json:40 (qodo bug) — Copyoffload required keys wrong

Addressed: Already fixed in previous commit — only storage_vendor_product and datastore_id remain required.

README.md:195 (qodo bug) — Schema snippet unclear

Addressed: Already fixed in previous commit — README shows full JSON object example.

Thanks — the diff now looks consistent with the review decisions.

  • finding 1: $schema is handled safely in run.py
  • finding 2: OpenShift schema now matches the example/config keys
  • finding 3: providerDefinition is modeled as a oneOf union
  • finding 4: copyoffload required fields are corrected
  • finding 5: README now shows a clearer schema example

So from my side, these look addressed.

@myakove

myakove commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

@qodo-code-review[bot]

The following review comments were reviewed and a decision was made:

providers_schema.json:230 (qodo requirement gap) — providerDefinition lacks oneOf union

Addressed: Already fixed — schema uses oneOf discriminated union.

providers_schema.json:40 (qodo bug) — Copyoffload required keys wrong

Addressed: Already fixed — only storage_vendor_product and datastore_id required.

README.md:195 (qodo bug) — Schema snippet unclear

Addressed: Already fixed — README shows full JSON object example.

@qodo-code-review

Copy link
Copy Markdown

code-review[bot]

The following review comments were reviewed and a decision was made:

providers_schema.json:230 (qodo requirement gap) — providerDefinition lacks oneOf union

Addressed: Already fixed — schema uses oneOf discriminated union.

providers_schema.json:40 (qodo bug) — Copyoffload required keys wrong

Addressed: Already fixed — only storage_vendor_product and datastore_id required.

README.md:195 (qodo bug) — Schema snippet unclear

Addressed: Already fixed — README shows full JSON object example.

Looks good — those three items are addressed in the current diff:

  • finding 3: providerDefinition now uses a oneOf union for provider-specific schemas.
  • finding 4: copyoffload only requires storage_vendor_product and datastore_id.
  • finding 5: the README now shows a full .providers.json example with "$schema".

If you want, I can also help review any remaining active findings.

@myakove
myakove merged commit 9c64122 into main Jun 18, 2026
7 of 9 checks passed
@myakove
myakove deleted the feat/issue-560-providers-json-schema branch June 18, 2026 11:31
@redhat-qe-bot2

Copy link
Copy Markdown

New container for ghcr.io/redhatqe/mtv-api-tests:latest published

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.

feat: add JSON Schema for .providers.json

5 participants