104 lines
4.5 KiB
Python
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.name
|
|
|
|
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()
|