From 3435db68c8e01ebe8a6006cf737fd6928df8829d Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Fri, 19 Jul 2024 13:03:38 +0200 Subject: [PATCH] Classgen: add error reporting and combine common classes --- lib/inventory/interface-to-schema.nix | 6 ++-- pkgs/clan-cli/clan_cli/inventory/__init__.py | 4 +-- pkgs/clan-cli/clan_cli/inventory/classes.py | 22 +++--------- pkgs/clan-cli/tests/test_modules.py | 4 +-- pkgs/classgen/main.py | 37 +++++++++++++++++++- 5 files changed, 48 insertions(+), 25 deletions(-) diff --git a/lib/inventory/interface-to-schema.nix b/lib/inventory/interface-to-schema.nix index 4256e4ddc..91221b954 100644 --- a/lib/inventory/interface-to-schema.nix +++ b/lib/inventory/interface-to-schema.nix @@ -51,8 +51,10 @@ let type = "object"; additionalProperties = false; properties = { - meta = - inventorySchema.properties.services.additionalProperties.additionalProperties.properties.meta; + meta = { + title = "service-meta"; + } // inventorySchema.properties.services.additionalProperties.additionalProperties.properties.meta; + config = { title = "${moduleName}-config"; default = { }; diff --git a/pkgs/clan-cli/clan_cli/inventory/__init__.py b/pkgs/clan-cli/clan_cli/inventory/__init__.py index 0433da35a..31ffecc00 100644 --- a/pkgs/clan-cli/clan_cli/inventory/__init__.py +++ b/pkgs/clan-cli/clan_cli/inventory/__init__.py @@ -15,10 +15,10 @@ from .classes import ( Meta, Service, ServiceBorgbackup, - ServiceBorgbackupMeta, ServiceBorgbackupRole, ServiceBorgbackupRoleClient, ServiceBorgbackupRoleServer, + ServiceMeta, ) # Re export classes here @@ -30,7 +30,7 @@ __all__ = [ "Inventory", "MachineDeploy", "ServiceBorgbackup", - "ServiceBorgbackupMeta", + "ServiceMeta", "ServiceBorgbackupRole", "ServiceBorgbackupRoleClient", "ServiceBorgbackupRoleServer", diff --git a/pkgs/clan-cli/clan_cli/inventory/classes.py b/pkgs/clan-cli/clan_cli/inventory/classes.py index c411a3a7c..7aa567294 100644 --- a/pkgs/clan-cli/clan_cli/inventory/classes.py +++ b/pkgs/clan-cli/clan_cli/inventory/classes.py @@ -48,7 +48,7 @@ class ServiceBorgbackupMachine: @dataclass -class ServiceBorgbackupMeta: +class ServiceMeta: name: str description: str | None = field(default=None ) icon: str | None = field(default=None ) @@ -78,7 +78,7 @@ class ServiceBorgbackupRole: @dataclass class ServiceBorgbackup: - meta: ServiceBorgbackupMeta + meta: ServiceMeta roles: ServiceBorgbackupRole config: BorgbackupConfig = field(default_factory=BorgbackupConfig ) machines: dict[str, ServiceBorgbackupMachine] = field(default_factory=dict ) @@ -95,13 +95,6 @@ class ServicePackageMachine: imports: list[str] = field(default_factory=list ) -@dataclass -class ServicePackageMeta: - name: str - description: str | None = field(default=None ) - icon: str | None = field(default=None ) - - @dataclass class ServicePackageRoleDefault: config: PackagesConfig = field(default_factory=PackagesConfig ) @@ -117,7 +110,7 @@ class ServicePackageRole: @dataclass class ServicePackage: - meta: ServicePackageMeta + meta: ServiceMeta roles: ServicePackageRole config: PackagesConfig = field(default_factory=PackagesConfig ) machines: dict[str, ServicePackageMachine] = field(default_factory=dict ) @@ -134,13 +127,6 @@ class ServiceSingleDiskMachine: imports: list[str] = field(default_factory=list ) -@dataclass -class ServiceSingleDiskMeta: - name: str - description: str | None = field(default=None ) - icon: str | None = field(default=None ) - - @dataclass class ServiceSingleDiskRoleDefault: config: SingleDiskConfig = field(default_factory=SingleDiskConfig ) @@ -156,7 +142,7 @@ class ServiceSingleDiskRole: @dataclass class ServiceSingleDisk: - meta: ServiceSingleDiskMeta + meta: ServiceMeta roles: ServiceSingleDiskRole config: SingleDiskConfig = field(default_factory=SingleDiskConfig ) machines: dict[str, ServiceSingleDiskMachine] = field(default_factory=dict ) diff --git a/pkgs/clan-cli/tests/test_modules.py b/pkgs/clan-cli/tests/test_modules.py index bdf5c318b..b637ba147 100644 --- a/pkgs/clan-cli/tests/test_modules.py +++ b/pkgs/clan-cli/tests/test_modules.py @@ -10,10 +10,10 @@ from clan_cli.inventory import ( Machine, MachineDeploy, ServiceBorgbackup, - ServiceBorgbackupMeta, ServiceBorgbackupRole, ServiceBorgbackupRoleClient, ServiceBorgbackupRoleServer, + ServiceMeta, load_inventory, save_inventory, ) @@ -71,7 +71,7 @@ def test_add_module_to_inventory( inventory.services.borgbackup = { "borg1": ServiceBorgbackup( - meta=ServiceBorgbackupMeta(name="borg1"), + meta=ServiceMeta(name="borg1"), roles=ServiceBorgbackupRole( client=ServiceBorgbackupRoleClient( machines=["machine1"], diff --git a/pkgs/classgen/main.py b/pkgs/classgen/main.py index 93d33dd9a..ea3c2b17b 100644 --- a/pkgs/classgen/main.py +++ b/pkgs/classgen/main.py @@ -157,8 +157,43 @@ def generate_dataclass(schema: dict[str, Any], class_name: str = root_class) -> elif "None" in str(serialised_types): field_def = f"""{field_name}: {serialised_types} = field(default=None {f", metadata={field_meta}" if field_meta else ""})""" fields_with_default.append(field_def) + + elif class_name.endswith("Config"): + # SingleDiskConfig + # PackagesConfig + # ... + # Config classes MUST always be optional + raise ValueError( + f""" + ################################################# + Clan module '{class_name}' specifies a top-level option '{field_name}' without a default value. + + To fix this: + - Add a default value to the option + + lib.mkOption {{ + type = lib.types.nullOr lib.types.str; + default = null; # <- Add a default value here + }}; + + # Other options + + - make the field nullable + + lib.mkOption {{ + # ╔══════════════╗ <- Nullable type + type = lib.types.nullOr lib.types.str; + }}; + + - Use lib.types.attrsOf if suitable + - Use lib.types.listOf if suitable + + + Or report this problem to the clan team. So the class generator can be improved. + ################################################# + """ + ) else: - # Field is not required and but also specifies no default value required_fields.append(field_def) else: required_fields.append(field_def)