Merge pull request 'clan-config: allow passing schema or module file' (#72) from DavHau-clan-edit into main

This commit is contained in:
clan-bot
2023-08-02 19:11:19 +00:00
3 changed files with 65 additions and 9 deletions

12
pkgs/clan-cli/bin/clan-config Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env python3
import os
import sys
sys.path.insert(
0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
)
from clan_cli import config # NOQA
if __name__ == "__main__":
config.main()

View File

@@ -1,6 +1,8 @@
# !/usr/bin/env python3 # !/usr/bin/env python3
import argparse import argparse
import json import json
import subprocess
import sys
from pathlib import Path from pathlib import Path
from typing import Any, Optional, Union from typing import Any, Optional, Union
@@ -15,21 +17,41 @@ class Kwargs:
self.choices: Optional[list] = None 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 <nixpkgs/lib>;
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 # takes a (sub)parser and configures it
def register_parser( def register_parser(
parser: Optional[argparse.ArgumentParser] = None, 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: ) -> 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: with open(str(schema)) as f:
schema: dict = json.load(f) schema: dict = json.load(f)
assert "type" in schema and schema["type"] == "object" assert "type" in schema and schema["type"] == "object"
required_set = set(schema.get("required", [])) required_set = set(schema.get("required", []))
if parser is None:
parser = argparse.ArgumentParser(description=schema.get("description"))
type_map = { type_map = {
"array": list, "array": list,
"boolean": bool, "boolean": bool,
@@ -38,6 +60,9 @@ def register_parser(
"string": str, "string": str,
} }
if parser is None:
parser = argparse.ArgumentParser(description=schema.get("description"))
subparsers = parser.add_subparsers( subparsers = parser.add_subparsers(
title="more options", title="more options",
description="Other options to configure", description="Other options to configure",
@@ -92,8 +117,18 @@ def register_parser(
parser.add_argument(name, **vars(kwargs)) parser.add_argument(name, **vars(kwargs))
if __name__ == "__main__": def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
register_parser(parser) parser.add_argument(
args = parser.parse_args() "schema",
print(args) 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()

View File

@@ -19,6 +19,15 @@ let
in in
rec { 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 # parses a set of evaluated nixos options to a jsonschema
parseOptions = options': parseOptions = options':
let let