diff --git a/pkgs/clan-cli/clan_cli/config/__init__.py b/pkgs/clan-cli/clan_cli/config/__init__.py index e1e652c90..f51a524e3 100644 --- a/pkgs/clan-cli/clan_cli/config/__init__.py +++ b/pkgs/clan-cli/clan_cli/config/__init__.py @@ -1,6 +1,8 @@ # !/usr/bin/env python3 import argparse import json +import subprocess +import sys from pathlib import Path from typing import Any, Optional, Union @@ -15,21 +17,41 @@ class Kwargs: self.choices: Optional[list] = None +def schema_from_module_file( + file: Union[str, Path] = "./tests/config/example-interface.nix", +) -> dict: + absolute_path = Path(file).absolute() + # define a nix expression that loads the given module file using lib.evalModules + nix_expr = f""" + let + lib = import ; + slib = import {__file__}/../schema-lib.nix {{inherit lib;}}; + in + slib.parseModule {absolute_path} + """ + # run the nix expression and parse the output as json + return json.loads( + subprocess.check_output( + ["nix", "eval", "--impure", "--json", "--expr", nix_expr] + ) + ) + + # takes a (sub)parser and configures it def register_parser( parser: Optional[argparse.ArgumentParser] = None, - schema: Union[dict, str, Path] = "./tests/config/example-schema.json", + schema: Union[dict, str, Path] = "./tests/config/example-interface.nix", ) -> dict: - if not isinstance(schema, dict): + # check if schema is a .nix file and load it in that case + if isinstance(schema, str) and schema.endswith(".nix"): + schema = schema_from_module_file(schema) + elif not isinstance(schema, dict): with open(str(schema)) as f: schema: dict = json.load(f) assert "type" in schema and schema["type"] == "object" required_set = set(schema.get("required", [])) - if parser is None: - parser = argparse.ArgumentParser(description=schema.get("description")) - type_map = { "array": list, "boolean": bool, @@ -38,6 +60,9 @@ def register_parser( "string": str, } + if parser is None: + parser = argparse.ArgumentParser(description=schema.get("description")) + subparsers = parser.add_subparsers( title="more options", description="Other options to configure", @@ -92,8 +117,18 @@ def register_parser( parser.add_argument(name, **vars(kwargs)) -if __name__ == "__main__": +def main(): parser = argparse.ArgumentParser() - register_parser(parser) - args = parser.parse_args() - print(args) + parser.add_argument( + "schema", + help="The schema to use for the configuration", + type=str, + ) + args = parser.parse_args(sys.argv[1:2]) + schema = args.schema + register_parser(schema=schema, parser=parser) + parser.parse_args(sys.argv[2:]) + + +if __name__ == "__main__": + main() diff --git a/pkgs/clan-cli/clan_cli/config/schema-lib.nix b/pkgs/clan-cli/clan_cli/config/schema-lib.nix index d0f2daa4e..2e6ab09b3 100644 --- a/pkgs/clan-cli/clan_cli/config/schema-lib.nix +++ b/pkgs/clan-cli/clan_cli/config/schema-lib.nix @@ -19,6 +19,15 @@ let in rec { + # parses a nixos module to a jsonschema + parseModule = module: + let + evaled = lib.evalModules { + modules = [ module ]; + }; + in + parseOptions evaled.options; + # parses a set of evaluated nixos options to a jsonschema parseOptions = options': let