diff --git a/albero/app.py b/albero/app.py index 351d2c5..366d82d 100755 --- a/albero/app.py +++ b/albero/app.py @@ -26,6 +26,12 @@ class App(): "type": "object", "additionalProperties": False, "default": {}, + "$def" :{ + 'backends_items': None, + 'backends_config': None, + 'rules_items': None, + 'rules_config': None, + }, "patternProperties": { ".*": { "type": "object", @@ -64,10 +70,12 @@ class App(): "tree": { "type": "array", "default": [], + "arrayItem": { "$ref": "#/$defs/backends_items" }, }, "rules": { "type": "array", "default": [], + "arrayItem": { "$ref": "#/$defs/rules_items" }, }, }, }, @@ -104,3 +112,23 @@ class App(): print ("=== Query Result ===") + def dump_schema(self): + + import json + import albero.plugin as AlberoPlugins + from albero.managers import BackendsManager, RulesManager + + r1 = BackendsManager.get_schema(AlberoPlugins) + r2 = RulesManager.get_schema(AlberoPlugins) + + d = self.schema + d['$def']['backends_items'] = r1 + d['$def']['rules_items'] = r2 + d['$def']['backends_config'] = None + d['$def']['rules_config'] = None + + #pprint(d) + print(json.dumps(d, indent=2)) + + + diff --git a/albero/cli.py b/albero/cli.py index 79aadf8..2ed8cb5 100644 --- a/albero/cli.py +++ b/albero/cli.py @@ -107,6 +107,8 @@ class CmdApp: subparsers = parser.add_subparsers( title="subcommands", description="valid subcommands", dest="command" ) + # Manage command: schema + add_p = subparsers.add_parser("schema") # Manage command: demo add_p = subparsers.add_parser("lookup") @@ -175,6 +177,14 @@ class CmdApp: explain=self.args.explain ) + def cli_schema(self): + """Display configuration schema""" + + config = '/home/jez/prj/bell/training/tiger-ansible/tree.yml' + + app = Albero.App(config=config) #, namespace=self.args.namespace) + app.dump_schema() + if __name__ == "__main__": app = CmdApp() diff --git a/albero/managers.py b/albero/managers.py index 9c279a3..fbbf8d7 100644 --- a/albero/managers.py +++ b/albero/managers.py @@ -44,23 +44,48 @@ class LoadPlugin(): # Return plugin Classe return plugin_cls.Plugin +class Manager(): + + plugins_kind = [] + + _schema_props_default = {} + _schema_props_default = {} + + @classmethod + def get_schema(cls, plugins_db): + pprint (cls.plugins_kind) + + ret = {} + ret3 = [] + + for kind in cls.plugins_kind: + ret[kind] = {} + plugin_kind = getattr(plugins_db, kind) + + for plugin_name in [i for i in dir(plugin_kind) if not i.startswith('_')]: + plugin = getattr(plugin_kind, plugin_name) + print (plugin.Plugin) + #pprint (dir(plugin)) + plugin_cls = getattr(plugin, 'Plugin', None) + if plugin_cls: + schema_props = getattr(plugin_cls, '_schema_props_new', 'MISSING ITEM') + if schema_props: + ret[kind][plugin_name] = schema_props + print (plugin_name) + ret3.append( schema_props ) + + ret3.append( cls._schema_props_new ) + + ret1 = cls._schema_props_default + ret1["$def"]["items"] = ret3 + return ret1 -class BackendsManager(): +class BackendsManager(Manager): - _schema_props_default = { - "$schema": 'http://json-schema.org/draft-04/schema#', - "default": "", - "oneOf": [ - { - "type": "string", - "default": "BLAAAAHHH" - }, - { - "type": "object", - "additionalProperties": True, - "default": {}, - "properties": { + plugins_kind = ['engine', 'backend'] + + _schema_props_new = { "engine": { "type": "string", "default": "jerakia", @@ -70,7 +95,25 @@ class BackendsManager(): "default": 'UNSET', "optional": False, }, - }, + #### INSERT HERE SUBSCHEMA !!!!! + } + + _schema_props_default = { + "$schema": 'http://json-schema.org/draft-04/schema#', + "default": "", + "$def": { + "items": {}, + }, + "oneOf": [ + { + "type": "string", + "default": "BLAAAAHHH" + }, + { + "type": "object", + "additionalProperties": True, + "default": {}, + "properties": { "$ref": "#/$defs/name" }, }, ] } @@ -173,13 +216,11 @@ class BackendsManager(): -class RulesManager(): +class RulesManager(Manager): - rule_schema = { - "$schema": 'http://json-schema.org/draft-04/schema#', - "type": "object", - "additionalProperties": False, - "properties": { + plugins_kind = ['strategy'] + + _schema_props_new = { "rule": { "default": ".*", "optional": True, @@ -192,6 +233,14 @@ class RulesManager(): }, ], }, + "strategy": { + "type": "string", + "default": "schema", + # "default": "last", + "optional": True, + # "enum": ["first", "last", "merge"], + }, + "trace": { "type": "boolean", "default": False, @@ -200,26 +249,49 @@ class RulesManager(): "type": "boolean", "default": False, }, - "strategy": { - "type": "string", - "default": "schema", - # "default": "last", - "optional": True, - # "enum": ["first", "last", "merge"], + } + + _schema_props_default = { + "$schema": 'http://json-schema.org/draft-04/schema#', + "default": "", + "$def": { + "items": {}, }, + "oneOf": [ + { + "type": "string", + "default": "BLAAAAHHH" + }, + { + "type": "object", + "additionalProperties": True, + "default": {}, + "properties": { "$ref": "#/$defs/name" }, + }, + ] + } + + OLD_rule_schema = { + "$schema": 'http://json-schema.org/draft-04/schema#', + "type": "object", + "additionalProperties": False, + "properties": { "schema": { "type": "object", "default": None, "optional": True, "oneOf": [ { - "type": "string", + "type": "null", }, { - "type": "null", + "type": "string", }, { - "type": "object", + "type": "object", + "additionalProperties": True, + "default": {}, + "properties": { "$ref": "#/$defs/name" }, }, ], }, @@ -262,14 +334,14 @@ class RulesManager(): matched_rule['trace'] = trace matched_rule['explain'] = explain - schema_validate(matched_rule, self.rule_schema) + schema_validate(matched_rule, self._schema_props_default) # Prepare plugins assert(isinstance(matched_candidates, list)), f"Got: {matched_candidates}" assert(isinstance(matched_rule, dict)), f"Got: {matched_rule}" - strategy = matched_rule.get('strategy', 'first') + strategy = matched_rule.get('strategy', 'schema') log.debug(f"Key '{key}' matched rule '{rule}' with '{strategy}' strategy") # Load plugin diff --git a/albero/plugin/backend/hier.py b/albero/plugin/backend/hier.py index 96cc82c..401b9b4 100644 --- a/albero/plugin/backend/hier.py +++ b/albero/plugin/backend/hier.py @@ -18,48 +18,49 @@ log = logging.getLogger(__name__) class Plugin(PluginBackendClass): _plugin_name = "hier" - _schema_props_files = { - "path": { - "anyOf": [ + _schema_props_new = { + "hier": { + "default": None, + "optional": True, + "oneOf": [ { - "type": "string", + "type": "null", }, { - "type": "array", - "items": { "type": "string", - } + }, + { + "additionalProperties": True, + "properties": { + "data": { + "default": None, + "anyOf": [ + { "type": "null" }, + { "type": "string" }, + { "type": "array" }, + ] + }, + "var": { + "type": "string", + "default": "hier_item", + "optional": True, + }, + "separator": { + "type": "string", + "default": "/", + "optional": True, + }, + "reversed": { + "type": "boolean", + "default": False, + "optional": True, + }, + }, }, ] } } - sssss_schema_props_default = { - "$schema": 'http://json-schema.org/draft-04/schema#', - "default": "", - "oneOf": [ - { - "type": "string", - "default": "BLAAAAHHH" - }, - { - "type": "object", - "additionalProperties": True, - "default": {}, - "properties": { - "engine": { - "type": "string", - "default": "jerakia", - "optional": False, - }, - "value": { - "default": 'UNSET', - "optional": False, - }, - }, - }, - ] - } def process(self, backends: list, ctx: dict) -> (list, dict): diff --git a/albero/plugin/backend/init.py b/albero/plugin/backend/init.py index 94c41c8..0f8e149 100644 --- a/albero/plugin/backend/init.py +++ b/albero/plugin/backend/init.py @@ -10,52 +10,10 @@ import copy class Plugin(PluginBackendClass): _plugin_name = "init" - _schema_props_files = { - "path": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "array", - "items": { - "type": "string", - } - }, - ] - } - } - - sssss_schema_props_default = { - "$schema": 'http://json-schema.org/draft-04/schema#', - "default": "", - "oneOf": [ - { - "type": "string", - "default": "BLAAAAHHH" - }, - { - "type": "object", - "additionalProperties": True, - "default": {}, - "properties": { - "engine": { - "type": "string", - "default": "jerakia", - "optional": False, - }, - "value": { - "default": 'UNSET', - "optional": False, - }, - }, - }, - ] - } + _schema_props_new = None default_engine = 'jerakia' - def process(self, backends: list, ctx: dict) -> (list, dict): new_backends = [] diff --git a/albero/plugin/backend/loop.py b/albero/plugin/backend/loop.py index 61be192..2d0c0d9 100644 --- a/albero/plugin/backend/loop.py +++ b/albero/plugin/backend/loop.py @@ -14,48 +14,41 @@ import textwrap class Plugin(PluginBackendClass): _plugin_name = "loop" - _schema_props_files = { - "path": { - "anyOf": [ - { - "type": "string", - }, - { - "type": "array", - "items": { - "type": "string", - } - }, - ] - } - } - - sssss_schema_props_default = { - "$schema": 'http://json-schema.org/draft-04/schema#', - "default": "", + _schema_props_new = { + "loop": { + "default": None, + "optional": True, "oneOf": [ + { + "type": "null", + }, { "type": "string", - "default": "BLAAAAHHH" }, { "type": "object", "additionalProperties": True, "default": {}, "properties": { - "engine": { - "type": "string", - "default": "jerakia", + "data": { + "default": None, "optional": False, + "anyOf":[ + {"type": "null"}, + {"type": "string"}, + {"type": "array"}, + ] }, - "value": { - "default": 'UNSET', - "optional": False, + "var": { + "type": "string", + "default": "loop_item", + "optional": True, }, }, }, ] - } + } + } def process(self, backends: list, ctx: dict) -> (list, dict): diff --git a/albero/plugin/common.py b/albero/plugin/common.py index a3030be..1d9ec9f 100644 --- a/albero/plugin/common.py +++ b/albero/plugin/common.py @@ -50,6 +50,9 @@ class Candidate(): class PluginClass(): _plugin_type = "none" _plugin_value = None + + _schema_props_new = "UNSET PLUGIN PROPRIETIES" + _schema_props_plugin = { "engine": { "type": "string", diff --git a/albero/plugin/engine/jerakia.py b/albero/plugin/engine/jerakia.py index f74cf12..b84e5e0 100644 --- a/albero/plugin/engine/jerakia.py +++ b/albero/plugin/engine/jerakia.py @@ -31,26 +31,23 @@ class Plugin(PluginEngineClass, PluginFileGlob): ### OLD _plugin_engine = "jerakia" - _schema_props_files = { + # _schema_props_files = { + _schema_props_new = { "path": { "anyOf": [ { - "type": "string", + "type": "string", }, { - "type": "array", - "items": { - "type": "string", - } + "type": "array", + "items": { + "type": "string", + } }, ] } } -# def __repr__(self): -# engine = self.config.get('engine') -# value = self. -# return f"Plugin instance {engine}: {value}" def _init(self): diff --git a/albero/plugin/strategy/last.py b/albero/plugin/strategy/last.py index ef5886d..689beef 100644 --- a/albero/plugin/strategy/last.py +++ b/albero/plugin/strategy/last.py @@ -7,6 +7,7 @@ log = logging.getLogger(__name__) class Plugin(PluginStrategyClass): _plugin_name = "last" + _schema_props_new = None def process(self, candidates: list, rule=None) -> (list, dict): diff --git a/albero/plugin/strategy/schema.py b/albero/plugin/strategy/schema.py index d65c27f..6d07942 100644 --- a/albero/plugin/strategy/schema.py +++ b/albero/plugin/strategy/schema.py @@ -14,6 +14,44 @@ from prettytable import PrettyTable class Plugin(PluginStrategyClass): _plugin_name = "schema" + _schema_props_new = { + "schema": { + "default": None, + "optional": True, + "oneOf": [ + { + "type": "null", + }, + { + "type": "string", + }, + { + "type": "array", + }, + { + "type": "object", + "additionalProperties": True, + "default": {}, + "properties": { + "data": { + "default": None, + "optional": False, + "anyOf":[ + {"type": "null"}, + {"type": "string"}, + {"type": "array"}, + ] + }, + "var": { + "type": "string", + "default": "loop_item", + "optional": True, + }, + }, + }, + ] + } + } default_merge_schema = { "$schema": 'http://json-schema.org/draft-04/schema#', diff --git a/pyproject.toml b/pyproject.toml index 3d60ce0..efa0b17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ python-box = "^5.4.1" prettytable = "^3.0.0" [tool.poetry.dev-dependencies] +json-schema-for-humans = "^0.40" [build-system] requires = ["poetry-core>=1.0.0"]