kheops/albero/app.py

233 lines
7.7 KiB
Python

#!/usr/bin/env python3
# import sys
# sys.path.append("/home/jez/prj/bell/training/tiger-ansible/ext/ansible-tree")
import sys
import yaml
import anyconfig
from pprint import pprint
from albero.query import Query
from albero.utils import schema_validate
import anyconfig
# from box import Box
from pathlib import Path
import logging
log = logging.getLogger(__name__)
class App:
schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": False,
"default": {},
"$def": {
"backends_items": {},
"backends_config": {},
"rules_items": {},
"rules_config": {},
},
"patternProperties": {
".*": {
"type": "object",
"optional": True,
"additionalProperties": False,
"properties": {
"config": {
"type": "object",
"default": {},
"additionalProperties": False,
"properties": {
"app": {
"type": "object",
#"default": {},
"additionalProperties": False,
"properties": {
"root": {
"default": None,
"oneOf": [
{
"type": "null",
"description": "Application current working directory is the `albero.yml` directory",
},
{
"type": "string",
"description": "Application working directory. If a relative path is used, it will be depending on `albero.yml` directory",
},
]
},
},
},
"tree": {
# "additionalProperties": False,
"type": "object",
"default": {},
"properties": {
"prefix": {
"default": None,
"oneOf": [
{
"type": "null",
"description": "Disable prefix, all files are lookup up from the app root dir.",
},
{
"type": "string",
"description": "Add a path prefix before all paths. This is quite useful to store your YAML data in a dedicated tree.",
},
]
},
}
},
"rules": {
"type": "object",
"default": {},
},
},
},
"tree": {
"type": "array",
"default": [],
"items": {
"type": "object",
"properties": {"$ref": "#/$defs/backends_items"},
},
},
"rules": {
"type": "array",
"default": [],
# "arrayItem": { "$ref": "#/$defs/rules_items" },
},
},
},
},
}
def __init__(self, config="albero.yml", namespace="default"):
conf2 = anyconfig.load(config)
self.run = {}
# Validate configuration
schema_validate(conf2, self.schema)
try:
conf2 = conf2[namespace]
except KeyError:
log.error(f"Can't find namespace '{namespace}' in config '{config}'")
sys.exit(1)
# Get application paths
# =====================
# Fetch app root
if conf2["config"]["app"]["root"]:
path_root = Path(conf2["config"]["app"]["root"])
log.debug ("Root path is hard coded.")
else:
path_root = Path(config).parent
log.debug ("Root path guessed from conf file.")
#path_prefix = conf2["config"]["app"]["prefix"]
#if not path_prefix:
# path_prefix = ''
#p = Path(path_prefix)
#if not p.is_absolute():
# p = path_root / p
# try:
# p = p.resolve().relative_to(Path.cwd().resolve())
# except ValueError:
# pass
# Save paths
path_cwd = str(Path.cwd().resolve())
path_root = str(path_root.resolve())
self.run['path_cwd'] = path_cwd
self.run['path_root'] = path_root
#self.run['path_prefix'] = str(p.resolve())
log.debug (f"Working directory is {path_root} while cwd is: {path_cwd}")
# path_root = path_root.resolve().relative_to(Path.cwd())
#conf2["config"]["app"]["root"] = str(path_root)
# Finish
self.conf2 = dict(conf2)
log.debug("Loading config: %s", config)
log.debug("Root directory is: %s", path_root)
def lookup(self, key=None, policy=None, scope=None, trace=False, explain=False):
log.debug(f"Lookup key {key} with scope: {scope}")
q = Query(app=self)
r = q.exec(key=key, scope=scope, policy=policy, trace=trace, explain=explain)
return r
#print("=== Query Result ===")
print(anyconfig.dumps(r, ac_parser=fmt))
#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, mode='parts')
r2 = RulesManager.get_schema(AlberoPlugins)
#pprint (r1)
print(json.dumps(r1, indent=2))
return
d = self.schema
d["patternProperties"][".*"]["properties"]["tree"]["items"]["properties"] = r1
d["patternProperties"][".*"]["properties"]["tree"]["items"] = r2
print(json.dumps(d, indent=2))
def gen_docs(self):
import json
import albero.plugin as AlberoPlugins
from albero.managers import BackendsManager, RulesManager
print ("WIP")
#src = {
# "app": {
# "config_schema": None,
# "plugin_managers": {
# 'tree': None,
# 'rules': None,
# }
# }
#
#r1 = BackendsManager.get_schema(AlberoPlugins, mode='parts')
#print (json.dumps(r1, indent=2))
#ret = {
#
# }
#part_config = r1.get('config_schema', None)
#part_item = r1['items']['core_schema']
#part_item_plugins = r1['items']['plugin']
#for kind, plugins in part_item_plugins.items():
# for plugin_name, schema in plugins.items():
# part_item_