diff --git a/commodore/inventory/parameters.py b/commodore/inventory/parameters.py index 511ed5ea..014d6a7d 100644 --- a/commodore/inventory/parameters.py +++ b/commodore/inventory/parameters.py @@ -6,10 +6,7 @@ from pathlib import Path from typing import Any, Optional -from kapitan.reclass import reclass -from kapitan.reclass.reclass import settings as reclass_settings -from kapitan.reclass.reclass import core as reclass_core -from kapitan.reclass.reclass import errors as reclass_errors +from reclass_rs import Reclass from commodore.cluster import Cluster, render_params from commodore.component import component_parameters_key @@ -20,28 +17,6 @@ FAKE_CLUSTER_ID = "c-bar" -class ClassNotFound(reclass_errors.ClassNotFound): - """ - Create a wrapper around kapitan.reclass's ClassNotFound exception. - - This allows us to have clean exception handling outside of this file, because we - unfortunately can't catch ClassNotFound directly in our code if we import - and use Kapitan reclass's ClassNotFound with any import which doesn't map the class - to `reclass.errors.ClassNotFound`. This is the case because Python's implementation - doesn't try to figure out if two imports are the same if they have different import - paths, cf. https://docs.python.org/3/reference/import.html. - - The only import that should work (in my understanding) would be - `from kapitan.reclass import reclass` but with that import we get the error - "AttributeError: module 'kapitan.reclass.reclass' has no attribute 'errors'" - """ - - @classmethod - def from_reclass(cls, e: reclass_errors.ClassNotFound): - """Wrap a reclass.errors.ClassNotFound instance in our wrapper.""" - return ClassNotFound(e.storage, e.name, e.path) - - class InventoryFacts: def __init__( self, @@ -176,53 +151,25 @@ def global_dir(self) -> Path: def tenant_dir(self) -> Optional[Path]: return self._tenant_dir - def _reclass_config( - self, allow_missing_classes: bool, ignore_class_notfound_warning: bool = True - ) -> dict: - return { - "storage_type": "yaml_fs", - "inventory_base_uri": str(self.directory.absolute()), - "nodes_uri": str(self.targets_dir.absolute()), - "classes_uri": str(self.classes_dir.absolute()), - "compose_node_name": False, - "allow_none_override": True, - "ignore_class_notfound": allow_missing_classes, - "ignore_class_notfound_warning": ignore_class_notfound_warning, - } - def _render_inventory( self, target: Optional[str] = None, allow_missing_classes: bool = True, ignore_class_notfound_warning: bool = True, ) -> dict[str, Any]: - rc = self._reclass_config( - allow_missing_classes, - ignore_class_notfound_warning=ignore_class_notfound_warning, - ) - storage = reclass.get_storage( - rc["storage_type"], - rc["nodes_uri"], - rc["classes_uri"], - rc["compose_node_name"], - ) - class_mappings = rc.get("class_mappings") - _reclass = reclass_core.Core( - storage, class_mappings, reclass_settings.Settings(rc) + r = Reclass( + nodes_path=str(self.targets_dir.absolute()), + classes_path=str(self.classes_dir.absolute()), + ignore_class_notfound=allow_missing_classes, ) try: if target: - return _reclass.nodeinfo(target) - - return _reclass.inventory() - except Exception as e: - if type(e).__name__ == "ClassNotFound": - # Wrap Kapitan reclass's ClassNotFound with ours so we can cleanly - # catch it. See docsstring for our ClassNotFound for a more detailed - # explanation why this is necessary. - raise ClassNotFound.from_reclass(e) - raise + return r.nodeinfo(target).as_dict() + + return r.inventory().as_dict() + except ValueError as e: + raise e def reclass(self, invfacts: InventoryFacts) -> InventoryParameters: cluster_response: dict[str, Any] = { diff --git a/commodore/inventory/render.py b/commodore/inventory/render.py index 80db2607..c145e013 100644 --- a/commodore/inventory/render.py +++ b/commodore/inventory/render.py @@ -10,7 +10,6 @@ from commodore.config import Config from .parameters import ( - ClassNotFound, InventoryFactory, InventoryFacts, InventoryParameters, @@ -67,11 +66,11 @@ def _get_inventory(cfg: Config, invfacts: InventoryFacts) -> InventoryParameters try: inv = invfactory.reclass(invfacts) - except ClassNotFound as e: + except ValueError as e: _cleanup_work_dir(cfg, work_dir) raise ValueError( "Unable to render inventory with `--no-allow-missing-classes`. " - + f"Class '{e.name}' not found. " + + f"{e}. " + "Verify the provided values or allow missing classes." ) from e diff --git a/tests/test_inventory_render.py b/tests/test_inventory_render.py index 3836d450..dfd60021 100644 --- a/tests/test_inventory_render.py +++ b/tests/test_inventory_render.py @@ -57,19 +57,19 @@ def test_extract_components( lambda t, g: create_inventory_facts( t, g, None, "x-invalid-dist", None, None, allow_missing_classes=False ), - "Class 'global.distribution.x-invalid-dist' not found.", + "Error while rendering global: Class global.distribution.x-invalid-dist not found.", ), ( lambda t, g: create_inventory_facts( t, g, None, "a", "x-invalid-cloud", None, allow_missing_classes=False ), - "Class 'global.cloud.x-invalid-cloud' not found.", + "Error while rendering global: Class global.cloud.x-invalid-cloud not found.", ), ( lambda t, g: create_inventory_facts( t, g, None, "a", "y", "x-invalid-region", allow_missing_classes=False ), - "Class 'global.cloud.y.x-invalid-region' not found.", + "Error while rendering global: Class global.cloud.y.x-invalid-region not found.", ), ], )