Fix: Schema implementation across plugins

This commit is contained in:
mrjk 2022-01-15 05:30:23 -05:00
parent 45a40dfa86
commit 50c7af2f58
11 changed files with 247 additions and 145 deletions

View File

@ -26,6 +26,12 @@ class App():
"type": "object", "type": "object",
"additionalProperties": False, "additionalProperties": False,
"default": {}, "default": {},
"$def" :{
'backends_items': None,
'backends_config': None,
'rules_items': None,
'rules_config': None,
},
"patternProperties": { "patternProperties": {
".*": { ".*": {
"type": "object", "type": "object",
@ -64,10 +70,12 @@ class App():
"tree": { "tree": {
"type": "array", "type": "array",
"default": [], "default": [],
"arrayItem": { "$ref": "#/$defs/backends_items" },
}, },
"rules": { "rules": {
"type": "array", "type": "array",
"default": [], "default": [],
"arrayItem": { "$ref": "#/$defs/rules_items" },
}, },
}, },
}, },
@ -104,3 +112,23 @@ class App():
print ("=== Query Result ===") 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))

View File

@ -107,6 +107,8 @@ class CmdApp:
subparsers = parser.add_subparsers( subparsers = parser.add_subparsers(
title="subcommands", description="valid subcommands", dest="command" title="subcommands", description="valid subcommands", dest="command"
) )
# Manage command: schema
add_p = subparsers.add_parser("schema")
# Manage command: demo # Manage command: demo
add_p = subparsers.add_parser("lookup") add_p = subparsers.add_parser("lookup")
@ -175,6 +177,14 @@ class CmdApp:
explain=self.args.explain 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__": if __name__ == "__main__":
app = CmdApp() app = CmdApp()

View File

@ -44,23 +44,48 @@ class LoadPlugin():
# Return plugin Classe # Return plugin Classe
return plugin_cls.Plugin 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 = { plugins_kind = ['engine', 'backend']
"$schema": 'http://json-schema.org/draft-04/schema#',
"default": "", _schema_props_new = {
"oneOf": [
{
"type": "string",
"default": "BLAAAAHHH"
},
{
"type": "object",
"additionalProperties": True,
"default": {},
"properties": {
"engine": { "engine": {
"type": "string", "type": "string",
"default": "jerakia", "default": "jerakia",
@ -70,7 +95,25 @@ class BackendsManager():
"default": 'UNSET', "default": 'UNSET',
"optional": False, "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 = { plugins_kind = ['strategy']
"$schema": 'http://json-schema.org/draft-04/schema#',
"type": "object", _schema_props_new = {
"additionalProperties": False,
"properties": {
"rule": { "rule": {
"default": ".*", "default": ".*",
"optional": True, "optional": True,
@ -192,6 +233,14 @@ class RulesManager():
}, },
], ],
}, },
"strategy": {
"type": "string",
"default": "schema",
# "default": "last",
"optional": True,
# "enum": ["first", "last", "merge"],
},
"trace": { "trace": {
"type": "boolean", "type": "boolean",
"default": False, "default": False,
@ -200,26 +249,49 @@ class RulesManager():
"type": "boolean", "type": "boolean",
"default": False, "default": False,
}, },
"strategy": { }
"type": "string",
"default": "schema", _schema_props_default = {
# "default": "last", "$schema": 'http://json-schema.org/draft-04/schema#',
"optional": True, "default": "",
# "enum": ["first", "last", "merge"], "$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": { "schema": {
"type": "object", "type": "object",
"default": None, "default": None,
"optional": True, "optional": True,
"oneOf": [ "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['trace'] = trace
matched_rule['explain'] = explain matched_rule['explain'] = explain
schema_validate(matched_rule, self.rule_schema) schema_validate(matched_rule, self._schema_props_default)
# Prepare plugins # Prepare plugins
assert(isinstance(matched_candidates, list)), f"Got: {matched_candidates}" assert(isinstance(matched_candidates, list)), f"Got: {matched_candidates}"
assert(isinstance(matched_rule, dict)), f"Got: {matched_rule}" 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") log.debug(f"Key '{key}' matched rule '{rule}' with '{strategy}' strategy")
# Load plugin # Load plugin

View File

@ -18,48 +18,49 @@ log = logging.getLogger(__name__)
class Plugin(PluginBackendClass): class Plugin(PluginBackendClass):
_plugin_name = "hier" _plugin_name = "hier"
_schema_props_files = { _schema_props_new = {
"path": { "hier": {
"anyOf": [ "default": None,
"optional": True,
"oneOf": [
{ {
"type": "string", "type": "null",
}, },
{ {
"type": "array",
"items": {
"type": "string", "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): def process(self, backends: list, ctx: dict) -> (list, dict):

View File

@ -10,52 +10,10 @@ import copy
class Plugin(PluginBackendClass): class Plugin(PluginBackendClass):
_plugin_name = "init" _plugin_name = "init"
_schema_props_files = { _schema_props_new = None
"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,
},
},
},
]
}
default_engine = 'jerakia' default_engine = 'jerakia'
def process(self, backends: list, ctx: dict) -> (list, dict): def process(self, backends: list, ctx: dict) -> (list, dict):
new_backends = [] new_backends = []

View File

@ -14,48 +14,41 @@ import textwrap
class Plugin(PluginBackendClass): class Plugin(PluginBackendClass):
_plugin_name = "loop" _plugin_name = "loop"
_schema_props_files = { _schema_props_new = {
"path": { "loop": {
"anyOf": [ "default": None,
{ "optional": True,
"type": "string",
},
{
"type": "array",
"items": {
"type": "string",
}
},
]
}
}
sssss_schema_props_default = {
"$schema": 'http://json-schema.org/draft-04/schema#',
"default": "",
"oneOf": [ "oneOf": [
{
"type": "null",
},
{ {
"type": "string", "type": "string",
"default": "BLAAAAHHH"
}, },
{ {
"type": "object", "type": "object",
"additionalProperties": True, "additionalProperties": True,
"default": {}, "default": {},
"properties": { "properties": {
"engine": { "data": {
"type": "string", "default": None,
"default": "jerakia",
"optional": False, "optional": False,
"anyOf":[
{"type": "null"},
{"type": "string"},
{"type": "array"},
]
}, },
"value": { "var": {
"default": 'UNSET', "type": "string",
"optional": False, "default": "loop_item",
"optional": True,
}, },
}, },
}, },
] ]
} }
}
def process(self, backends: list, ctx: dict) -> (list, dict): def process(self, backends: list, ctx: dict) -> (list, dict):

View File

@ -50,6 +50,9 @@ class Candidate():
class PluginClass(): class PluginClass():
_plugin_type = "none" _plugin_type = "none"
_plugin_value = None _plugin_value = None
_schema_props_new = "UNSET PLUGIN PROPRIETIES"
_schema_props_plugin = { _schema_props_plugin = {
"engine": { "engine": {
"type": "string", "type": "string",

View File

@ -31,26 +31,23 @@ class Plugin(PluginEngineClass, PluginFileGlob):
### OLD ### OLD
_plugin_engine = "jerakia" _plugin_engine = "jerakia"
_schema_props_files = { # _schema_props_files = {
_schema_props_new = {
"path": { "path": {
"anyOf": [ "anyOf": [
{ {
"type": "string", "type": "string",
}, },
{ {
"type": "array", "type": "array",
"items": { "items": {
"type": "string", "type": "string",
} }
}, },
] ]
} }
} }
# def __repr__(self):
# engine = self.config.get('engine')
# value = self.
# return f"Plugin instance {engine}: {value}"
def _init(self): def _init(self):

View File

@ -7,6 +7,7 @@ log = logging.getLogger(__name__)
class Plugin(PluginStrategyClass): class Plugin(PluginStrategyClass):
_plugin_name = "last" _plugin_name = "last"
_schema_props_new = None
def process(self, candidates: list, rule=None) -> (list, dict): def process(self, candidates: list, rule=None) -> (list, dict):

View File

@ -14,6 +14,44 @@ from prettytable import PrettyTable
class Plugin(PluginStrategyClass): class Plugin(PluginStrategyClass):
_plugin_name = "schema" _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 = { default_merge_schema = {
"$schema": 'http://json-schema.org/draft-04/schema#', "$schema": 'http://json-schema.org/draft-04/schema#',

View File

@ -14,6 +14,7 @@ python-box = "^5.4.1"
prettytable = "^3.0.0" prettytable = "^3.0.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
json-schema-for-humans = "^0.40"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]