import requests import logging import json class CaddyAPI: """API wrapper for Caddy""" __AUTHOR__ = 'anima' __VERSION__ = '0.2.0' _log = logging.getLogger(__name__) __logFile = logging.FileHandler('CaddyAPI.log') __logPrinter = logging.StreamHandler() __logFormat = logging.Formatter('%(asctime)s %(levelname)s \t %(name)s : %(message)s') __logFile.setFormatter(__logFormat) __logPrinter.setFormatter(__logFormat) _log.addHandler(__logFile) _log.addHandler(__logPrinter) def __init__(self, host: str, port: int = 2019) -> None: self.__baseurl = host self.__port = port def __query(self, path: str, data: str = None, contentType: str = 'json') -> dict | bool: """base query method """ url = f'http://{self.__baseurl}:{self.__port}/{path}' headers = {"Accept": "application/json"} match contentType: case 'json': headers['Content-Type'] = 'application/json' case 'caddyfile': headers['Content-Type'] = 'text/caddyfile' case _: self._log.error(f'not a supported {contentType=}') return False if data is None: response = requests.get(url, headers = headers) else: if contentType == 'json': response = requests.post(url, headers = headers, json = data) else: response = requests.post(url, headers = headers, data = data) if response.status_code == 200: content = response.content.decode() if content.startswith('{'): return response.json() else: return True else: self._log.error(f'error on api call {response.status_code} {response.url=} {data=}') return False def get_config(self, saveTo: str = None, path: str = None) -> dict: if path is None: path = 'config' config = self.__query(path) if config and config is not None: if saveTo is not None: with open(saveTo, 'w') as f: f.write(json.dumps(config)) return config def load_config(self, configFile: str, configAdapter: str = 'json'): if configFile is not None: match configAdapter: case 'json': with open(configFile, 'r') as f: config = json.load(f) return self.__query('load', config) case 'caddyfile': with open(configFile) as f: config = f.read() return self.__query('load', config, configAdapter) case _: self._log.error(f'not supported {configAdapter=}') return False else: self._log.error(f'cant load config without configfile {configFile=}') return False if __name__ == '__main__': from datetime import datetime from os import mkdir from os.path import exists now = datetime.now() with open('api-conf.json', 'r') as f: conf = json.load(f) caddy = CaddyAPI(conf['host'], conf['port']) backdir = 'backup' if not exists(backdir): mkdir(backdir) data = caddy.get_config(f'{backdir}/caddy_{now.strftime("%Y-%m-%d_%H-%M-%s")}_.json') if conf['configAdapter'] == 'json': load = caddy.load_config('caddy.json') else: load = caddy.load_config('Caddyfile', 'caddyfile') print(f'{load=}')