Module paracrine.helpers.config
Expand source code
import json
import os
import pathlib
from typing import Any, Dict, Optional
import jinja2
import yaml
from mergedeep import merge
_jinja_env = None
data = None
CONFIG_NAME = "config.yaml"
def jinja_env():
assert _jinja_env is not None, "Need to run set_data first!"
return _jinja_env
def host():
return data["host"]
def config():
return data["config"]
def data_files():
return data["data"]
def get_config_keys():
return data["configs"].keys()
def get_config_file(fname):
if fname not in get_config_keys():
raise KeyError(f"Can't find {fname}. We have: {sorted(get_config_keys())}")
return data["configs"][fname]
def core_config():
return yaml.safe_load(get_config_file(CONFIG_NAME))
def set_data(new_data: Dict[str, Any]) -> None:
loader = jinja2.DictLoader(new_data["templates"])
global _jinja_env, data
_jinja_env = jinja2.Environment(
loader=loader, undefined=jinja2.StrictUndefined, keep_trailing_newline=True
)
data = new_data
return_data = {}
def clear_return_data() -> None:
global return_data
return_data = {}
def add_return_data(new_data: Dict[str, Any]) -> None:
global return_data
merge(return_data, new_data)
def get_return_data() -> Dict:
global return_data
return return_data
def add_folder_to_config(configs, folder, shortname=None, filter=None, prefix=""):
if not os.path.exists(folder):
print("Skipping %s from config as doesn't exist" % folder)
return
for f in os.listdir(folder):
if filter is not None:
if not filter(f):
continue
if shortname is not None:
key = os.path.join(shortname, f)
full = os.path.join(folder, f)
else:
full = key = os.path.join(folder, f)
if os.path.isfile(full):
if prefix != "":
if "/" in key:
parts = key.split("/")
key = "/".join(parts[:-1]) + "/" + prefix + parts[-1]
else:
key = prefix + key
configs[key] = open(full).read()
else:
if prefix != "":
prefix += "/"
add_folder_to_config(
configs,
full,
shortname=shortname,
filter=filter,
prefix=prefix + f + "/",
)
inventory = None
inventory_directory = None
def set_config(inventory_path):
global inventory, inventory_directory
inventory_directory = os.path.dirname(inventory_path)
inventory = yaml.safe_load(open(inventory_path))
def get_config():
if inventory is None:
assert data is not None
return data["inventory"]
return inventory
def config_path(shortname=False):
if inventory is None or shortname:
return "configs"
else:
return os.path.join(data_path(), "configs")
def path_to_config_file(name: str) -> str:
if name.find("~") != -1:
return pathlib.Path(name).expanduser()
return pathlib.Path(config_path()).joinpath(name)
def data_path():
if inventory is None:
return None
return os.path.join(inventory_directory, inventory["data_path"])
def environment():
if inventory is None:
return data["environment"]
return inventory["environment"]
def servers():
try:
return get_config()["servers"]
except NotADirectoryError:
return core_config()["servers"]
def walk(path):
for p in pathlib.Path(path).iterdir():
if p.is_dir():
yield from walk(p)
continue
yield p.resolve()
def create_data(server: Optional[Dict] = None):
config = get_config()
templates = {}
template_paths = [
pathlib.Path("templates"),
pathlib.Path(__file__).parent.parent.joinpath("templates"),
]
for template_path in template_paths:
if not template_path.exists():
continue
for path in walk(template_path):
templates[path.name] = path.open("r").read()
data = {}
data_paths = [
pathlib.Path("data"),
pathlib.Path(__file__).parent.joinpath("data"),
]
for data_path in data_paths:
if not data_path.exists():
continue
data_path = data_path.absolute()
for path in walk(data_path):
try:
local_path = path.relative_to(data_path).as_posix()
except ValueError:
# Symlink outside of local folder
continue
data[local_path] = path.open("rb").read()
configs = {
CONFIG_NAME: open(CONFIG_NAME).read(),
}
add_folder_to_config(
configs,
config_path(),
shortname="configs",
filter=lambda f: not f.startswith("."),
)
return {
"templates": templates,
"host": server,
"config": config,
"configs": configs,
"environment": environment(),
"inventory": get_config(),
"data": data,
}
def network_config_file(name, shortname=False):
return config_path(shortname) + "/networks-{name}".format(name=name)
def network_config(name):
return json.loads(get_config_file(network_config_file(name, shortname=True)))
def other_config_file(name, shortname=False):
return config_path(shortname) + "/other-{name}".format(name=name)
def other_config(name):
return json.loads(get_config_file(other_config_file(name, shortname=True)))
def other_self_config():
return other_config(host()["name"])
def build_config(config: Dict) -> Dict:
env = environment()
LOCAL = config["environments"][env]
common = config.get("common", {})
ret = dict(**common)
ret.update(LOCAL)
return ret
def local_config() -> Dict:
return yaml.safe_load(open(CONFIG_NAME).read())
def local_server():
local_hostname = host()["name"]
for server in servers():
name = server["name"]
if name == local_hostname:
return server
raise Exception(f"Cannot find {local_hostname}")
def in_docker():
return os.path.exists("/.dockerenv")
Functions
def add_folder_to_config(configs, folder, shortname=None, filter=None, prefix='')
-
Expand source code
def add_folder_to_config(configs, folder, shortname=None, filter=None, prefix=""): if not os.path.exists(folder): print("Skipping %s from config as doesn't exist" % folder) return for f in os.listdir(folder): if filter is not None: if not filter(f): continue if shortname is not None: key = os.path.join(shortname, f) full = os.path.join(folder, f) else: full = key = os.path.join(folder, f) if os.path.isfile(full): if prefix != "": if "/" in key: parts = key.split("/") key = "/".join(parts[:-1]) + "/" + prefix + parts[-1] else: key = prefix + key configs[key] = open(full).read() else: if prefix != "": prefix += "/" add_folder_to_config( configs, full, shortname=shortname, filter=filter, prefix=prefix + f + "/", )
def add_return_data(new_data: Dict[str, Any]) ‑> None
-
Expand source code
def add_return_data(new_data: Dict[str, Any]) -> None: global return_data merge(return_data, new_data)
def build_config(config: Dict) ‑> Dict
-
Expand source code
def build_config(config: Dict) -> Dict: env = environment() LOCAL = config["environments"][env] common = config.get("common", {}) ret = dict(**common) ret.update(LOCAL) return ret
def clear_return_data() ‑> None
-
Expand source code
def clear_return_data() -> None: global return_data return_data = {}
def config()
-
Expand source code
def config(): return data["config"]
def config_path(shortname=False)
-
Expand source code
def config_path(shortname=False): if inventory is None or shortname: return "configs" else: return os.path.join(data_path(), "configs")
def core_config()
-
Expand source code
def core_config(): return yaml.safe_load(get_config_file(CONFIG_NAME))
def create_data(server: Optional[Dict] = None)
-
Expand source code
def create_data(server: Optional[Dict] = None): config = get_config() templates = {} template_paths = [ pathlib.Path("templates"), pathlib.Path(__file__).parent.parent.joinpath("templates"), ] for template_path in template_paths: if not template_path.exists(): continue for path in walk(template_path): templates[path.name] = path.open("r").read() data = {} data_paths = [ pathlib.Path("data"), pathlib.Path(__file__).parent.joinpath("data"), ] for data_path in data_paths: if not data_path.exists(): continue data_path = data_path.absolute() for path in walk(data_path): try: local_path = path.relative_to(data_path).as_posix() except ValueError: # Symlink outside of local folder continue data[local_path] = path.open("rb").read() configs = { CONFIG_NAME: open(CONFIG_NAME).read(), } add_folder_to_config( configs, config_path(), shortname="configs", filter=lambda f: not f.startswith("."), ) return { "templates": templates, "host": server, "config": config, "configs": configs, "environment": environment(), "inventory": get_config(), "data": data, }
def data_files()
-
Expand source code
def data_files(): return data["data"]
def data_path()
-
Expand source code
def data_path(): if inventory is None: return None return os.path.join(inventory_directory, inventory["data_path"])
def environment()
-
Expand source code
def environment(): if inventory is None: return data["environment"] return inventory["environment"]
def get_config()
-
Expand source code
def get_config(): if inventory is None: assert data is not None return data["inventory"] return inventory
def get_config_file(fname)
-
Expand source code
def get_config_file(fname): if fname not in get_config_keys(): raise KeyError(f"Can't find {fname}. We have: {sorted(get_config_keys())}") return data["configs"][fname]
def get_config_keys()
-
Expand source code
def get_config_keys(): return data["configs"].keys()
def get_return_data() ‑> Dict
-
Expand source code
def get_return_data() -> Dict: global return_data return return_data
def host()
-
Expand source code
def host(): return data["host"]
def in_docker()
-
Expand source code
def in_docker(): return os.path.exists("/.dockerenv")
def jinja_env()
-
Expand source code
def jinja_env(): assert _jinja_env is not None, "Need to run set_data first!" return _jinja_env
def local_config() ‑> Dict
-
Expand source code
def local_config() -> Dict: return yaml.safe_load(open(CONFIG_NAME).read())
def local_server()
-
Expand source code
def local_server(): local_hostname = host()["name"] for server in servers(): name = server["name"] if name == local_hostname: return server raise Exception(f"Cannot find {local_hostname}")
def network_config(name)
-
Expand source code
def network_config(name): return json.loads(get_config_file(network_config_file(name, shortname=True)))
def network_config_file(name, shortname=False)
-
Expand source code
def network_config_file(name, shortname=False): return config_path(shortname) + "/networks-{name}".format(name=name)
def other_config(name)
-
Expand source code
def other_config(name): return json.loads(get_config_file(other_config_file(name, shortname=True)))
def other_config_file(name, shortname=False)
-
Expand source code
def other_config_file(name, shortname=False): return config_path(shortname) + "/other-{name}".format(name=name)
def other_self_config()
-
Expand source code
def other_self_config(): return other_config(host()["name"])
def path_to_config_file(name: str) ‑> str
-
Expand source code
def path_to_config_file(name: str) -> str: if name.find("~") != -1: return pathlib.Path(name).expanduser() return pathlib.Path(config_path()).joinpath(name)
def servers()
-
Expand source code
def servers(): try: return get_config()["servers"] except NotADirectoryError: return core_config()["servers"]
def set_config(inventory_path)
-
Expand source code
def set_config(inventory_path): global inventory, inventory_directory inventory_directory = os.path.dirname(inventory_path) inventory = yaml.safe_load(open(inventory_path))
def set_data(new_data: Dict[str, Any]) ‑> None
-
Expand source code
def set_data(new_data: Dict[str, Any]) -> None: loader = jinja2.DictLoader(new_data["templates"]) global _jinja_env, data _jinja_env = jinja2.Environment( loader=loader, undefined=jinja2.StrictUndefined, keep_trailing_newline=True ) data = new_data
def walk(path)
-
Expand source code
def walk(path): for p in pathlib.Path(path).iterdir(): if p.is_dir(): yield from walk(p) continue yield p.resolve()