Files
skato-ansible/confctx.py

104 lines
4.5 KiB
Python

from pathlib import Path, PurePath
from whereami import PROJ_ROOT
from custtypes import ExecutedPath, IdlePath, VirtualPrivateServers, AnsibleScopes
from anodes import RemoteNode, ControlNode, _userSSHSubParams
# from ansible_vault import Vault
import yaml as yams
import re
from typing import Literal
# @TODO for 'Config' class, write methods to pull and push from Ansible YAML files
# @NOTE https://docs.python.org/3/library/configparser.html#quick-start
class Config:
path: ExecutedPath = PROJ_ROOT / "config.ini"
__controller = ControlNode()
setattr(__controller, AnsibleScopes.INTERNAL.name, {
"vars": (PurePath(str(path)),)
})
def __init__(self, filepath: str = "config.ini", scope: AnsibleScopes = AnsibleScopes.INTERNAL.name, index: int = 0, mode: str = "r+"):
self.scope = scope
parent_dir = self.__controller.get_scope(scope, index)
filepath = Path(parent_dir) / filepath
filename: str = filepath.stem
self.parse_method = "YML"
if "." in filename:
filename_arr = filename.split(".")
basename: str = filename_arr[0]
ext: str = filename_arr[len(filename_arr) - 1]
if re.match(r"toml|ini", ext):
self.parse_method: str = ext.upper()
self.filepath: ExecutedPath = filepath
self.mode = mode
self.model = None
self.file = None
self.__remote: RemoteNode | None = None
def __enter__(self):
if not self.filepath.exists():
self.__remote = RemoteNode(self.__controller)
return self.__remote
self.file = open(str(self.filepath), self.mode)
model = self.file.read()
if self.parse_method == "INI":
raise NotImplementedError
elif self.parse_method == "TOML":
raise NotImplementedError
else:
self.model = yams.load(model)
if self.scope == AnsibleScopes.GROUPVARS.name or self.scope == AnsibleScopes.HOSTVARS.name:
api_key: str = model["vps_service"]["api_key"]
vault = Vault(model["vps_service"]["password"])
password: str = vault.load(model["vps_service"]["password"])
fqdn: str = model["fqdn"]
service: VirtualPrivateServers = model["vps_service"]["type"]
region: Literal["us-east"] = model["vps_service"]["region"]
keywords: list[str] = model["keywords"]
self.__remote = RemoteNode(self.__controller, api_key, password, fqdn, service, region, keywords)
# @TODO add portion wherein SSH keys from 'model' are made to be present in 'self.__remote'
self.__remote.import_keys("*")
keyfiles = self.__remote.show_keys("available", list)
keyfiles_contents = set(map(lambda p: p.read_text(), keyfiles))
keyfiles_pub = list(set(model["vps_service"]["ssh_authorized_keys"]) - keyfiles_contents)
self.__remote.ssh.keys["available"] = tuple(keyfiles_pub)
self.__remote.ssh.keys["selected"] = keyfiles_pub
self.__remote.ssh.keys["authorized"] += keyfiles_pub
keyfiles_paths = set(map(lambda p: str(p), keyfiles))
keyfiles_priv = list(set(model["vps_service"]["ssh_private_key_paths"]) - keyfiles_paths)
self.__remote.ssh.keys["available"] = (*self.__remote.ssh.keys["available"],*keyfiles_priv)
self.__remote.ssh.keys["selected"] += keyfiles_priv
self.__remote.ssh.keys["used"] += keyfiles_priv
self.__remote.ssh.fate: Literal["disposal", "retention"] = model["vps_service"]["root_fate"]
return self.__remote
else:
raise ValueError
def __exit__(self):
if self.scope == AnsibleScopes.GROUPVARS.name or self.scope == AnsibleScopes.HOSTVARS.name:
ansible_chunk = self.__remote.itemize()
ansible_chunk["vps_service"]["ssh_motd_script_basenames"] = self.model["ssh_motd_script_basenames"]
ansible_chunk["vps_service"]["ssh_private_key_path_pref"] = self.model["ssh_private_key_path_pref"]
del self.model["fqdn"]
del self.model["vps_service"]
del self.model["keywords"]
else:
raise ValueError
if self.parse_method == "INI":
raise NotImplementedError
elif self.parse_method == "TOML":
raise NotImplementedError
else:
file_model = yams.dump(self.model | ansible_chunk)
self.file.write(file_model)
self.file.close()