Skip to content

Commit 7fcbcae

Browse files
authored
feat: Add --update-schema-for CLI option for single resource updates (#2642)
* feat: Add --update-schema-for CLI option for single resource updates Add new CLI option to update schema for individual resources without reprocessing all schema data. Includes: - README documentation for --update-schema-for option with examples - Refactored duplicate code into helper functions: - _fetch_openapi_v3_index: Fetches OpenAPI v3 paths index - _build_schema_data: Constructs schema data structure from API spec - _merge_schema_into_mapping: Merges schema into resource mapping - Improved code maintainability and reduced duplication * fix: Address CodeRabbit review comments in test files - Fix ResourceNotFoundError instantiation to use kind keyword argument - Rename unused mock parameters to follow Python conventions (_mock_*)
1 parent 342947a commit 7fcbcae

7 files changed

Lines changed: 603 additions & 69 deletions

File tree

class_generator/README.md

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,18 +155,55 @@ class-generator --kind Pod --add-tests
155155

156156
## Update schema files
157157

158-
- Dependencies
159-
- Kubernetes/Openshift cluster
160-
- [oc](https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/stable/) or [kubectl](https://kubernetes.io/docs/tasks/tools/) (latest version)
161-
- [uv](https://github.com/astral-sh/uv)
158+
Schema files contain resource definitions used by the class generator. You can update these from a connected Kubernetes/OpenShift cluster.
162159

163-
- Clone this repository
160+
### Dependencies
161+
162+
- Kubernetes/OpenShift cluster
163+
- [oc](https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/stable/) or [kubectl](https://kubernetes.io/docs/tasks/tools/) (latest version)
164+
- [uv](https://github.com/astral-sh/uv)
165+
166+
### Setup
167+
168+
Clone this repository:
164169

165170
```bash
166171
git clone https://github.com/RedHatQE/openshift-python-wrapper.git
167172
cd openshift-python-wrapper
168173
```
169174

170-
- Login to the cluster use admin user and password.
175+
Login to the cluster using admin user and password.
176+
177+
### Full schema update
178+
179+
Update the entire schema from the connected cluster:
180+
181+
```bash
182+
class-generator --update-schema
183+
```
184+
185+
This fetches all resource schemas from the cluster and updates the local cache.
186+
187+
**Note:** If connected to an older cluster, existing schemas are preserved and only missing resources are added.
188+
189+
### Single resource schema update
190+
191+
Update the schema for a single resource without affecting others:
192+
193+
```bash
194+
class-generator --update-schema-for LlamaStackDistribution
195+
```
196+
197+
This is useful when:
198+
199+
- Connected to an older cluster but need to update a specific CRD
200+
- A new operator was installed and you need its resource schema
201+
- You want to refresh just one resource without a full update
202+
203+
After updating the schema, regenerate the class:
171204

205+
```bash
206+
class-generator --kind LlamaStackDistribution --overwrite
172207
```
208+
209+
**Note:** `--update-schema` and `--update-schema-for` are mutually exclusive. Use one or the other, not both.

class_generator/cli.py

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@
1010
from typing import Any
1111

1212
import cloup
13-
from cloup.constraints import If, IsSet, accept_none, require_one
13+
from cloup.constraints import If, IsSet, accept_none, mutually_exclusive, require_one
1414
from simple_logger.logger import get_logger
1515

1616
from class_generator.constants import TESTS_MANIFESTS_DIR
1717
from class_generator.core.coverage import analyze_coverage, generate_report
1818
from class_generator.core.discovery import discover_generated_resources
1919
from class_generator.core.generator import class_generator
20-
from class_generator.core.schema import ClusterVersionError, update_kind_schema
20+
from class_generator.core.schema import (
21+
ClusterVersionError,
22+
update_kind_schema,
23+
update_single_resource_schema,
24+
)
25+
from class_generator.exceptions import ResourceNotFoundError
2126
from class_generator.tests.test_generation import generate_class_generator_tests
2227
from class_generator.utils import execute_parallel_tasks
2328
from ocp_resources.utils.utils import convert_camel_case_to_snake_case
@@ -28,16 +33,25 @@
2833
def validate_actions(
2934
kind: str | None,
3035
update_schema: bool,
36+
update_schema_for: str | None,
3137
discover_missing: bool,
3238
coverage_report: bool,
3339
generate_missing: bool,
3440
regenerate_all: bool,
3541
) -> None:
3642
"""Validate that at least one action is specified."""
37-
actions = [kind, update_schema, discover_missing, coverage_report, generate_missing, regenerate_all]
43+
actions = [
44+
kind,
45+
update_schema,
46+
update_schema_for,
47+
discover_missing,
48+
coverage_report,
49+
generate_missing,
50+
regenerate_all,
51+
]
3852
if not any(actions):
3953
LOGGER.error(
40-
"At least one action must be specified (--kind, --update-schema, --discover-missing, --coverage-report, --generate-missing, or --regenerate-all)"
54+
"At least one action must be specified (--kind, --update-schema, --update-schema-for, --discover-missing, --coverage-report, --generate-missing, or --regenerate-all)"
4155
)
4256
sys.exit(1)
4357

@@ -70,6 +84,33 @@ def handle_schema_update(update_schema: bool, generate_missing: bool) -> bool:
7084
return True
7185

7286

87+
def handle_single_schema_update(update_schema_for: str | None) -> bool:
88+
"""
89+
Handle single resource schema update operations.
90+
91+
Args:
92+
update_schema_for: The kind name to update schema for, or None
93+
94+
Returns:
95+
True if processing should continue, False if it should exit
96+
"""
97+
if update_schema_for:
98+
LOGGER.info(f"Updating schema for single resource: {update_schema_for}")
99+
try:
100+
update_single_resource_schema(kind=update_schema_for)
101+
except ResourceNotFoundError as e:
102+
LOGGER.error(f"Resource not found: {e}")
103+
sys.exit(1)
104+
except (OSError, RuntimeError) as e:
105+
LOGGER.exception(f"Failed to update schema for {update_schema_for}: {e}")
106+
sys.exit(1)
107+
108+
LOGGER.info(f"Schema updated for {update_schema_for}.")
109+
return False
110+
111+
return True
112+
113+
73114
def handle_coverage_analysis_and_reporting(
74115
coverage_report: bool,
75116
discover_missing: bool,
@@ -491,6 +532,17 @@ def handle_test_generation(add_tests: bool) -> None:
491532
is_flag=True,
492533
show_default=True,
493534
)
535+
@cloup.option(
536+
"--update-schema-for",
537+
type=cloup.STRING,
538+
help="""
539+
\b
540+
Update schema for a single resource kind only, without affecting other resources.
541+
Useful when connected to an older cluster but needing to update a specific CRD.
542+
Example: --update-schema-for LlamaStackDistribution
543+
Cannot be used together with --update-schema.
544+
""",
545+
)
494546
@cloup.option(
495547
"--discover-missing",
496548
help="Discover resources in the cluster that don't have wrapper classes",
@@ -555,6 +607,20 @@ def handle_test_generation(add_tests: bool) -> None:
555607
"regenerate_all",
556608
],
557609
)
610+
@cloup.constraint(
611+
mutually_exclusive,
612+
["update_schema", "update_schema_for"],
613+
)
614+
@cloup.constraint(
615+
If(IsSet("update_schema_for"), then=accept_none),
616+
[
617+
"kind",
618+
"discover_missing",
619+
"coverage_report",
620+
"generate_missing",
621+
"regenerate_all",
622+
],
623+
)
558624
@cloup.constraint(
559625
If(IsSet("backup"), then=require_one),
560626
["regenerate_all", "overwrite"],
@@ -577,6 +643,7 @@ def main(
577643
filter: str | None,
578644
json_output: bool,
579645
update_schema: bool,
646+
update_schema_for: str | None,
580647
verbose: bool,
581648
) -> None:
582649
"""Generate Python module for K8S resource."""
@@ -610,13 +677,18 @@ def main(
610677
validate_actions(
611678
kind=kind,
612679
update_schema=update_schema,
680+
update_schema_for=update_schema_for,
613681
discover_missing=discover_missing,
614682
coverage_report=coverage_report,
615683
generate_missing=generate_missing,
616684
regenerate_all=regenerate_all,
617685
)
618686

619-
# Handle schema update
687+
# Handle single resource schema update (if specified)
688+
if not handle_single_schema_update(update_schema_for=update_schema_for):
689+
return
690+
691+
# Handle full schema update
620692
if not handle_schema_update(update_schema=update_schema, generate_missing=generate_missing):
621693
return
622694

0 commit comments

Comments
 (0)