From 75987ced3c041c2ce3e2cc11777dca6ec827e98e Mon Sep 17 00:00:00 2001 From: Snowyo Date: Sat, 4 Aug 2018 21:52:49 +0200 Subject: [PATCH] added initial args --- extractor.py | 113 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/extractor.py b/extractor.py index 9f017b5..8cc3a57 100644 --- a/extractor.py +++ b/extractor.py @@ -3,23 +3,80 @@ import os import errno import time import json -import docker - +#import docker +import argparse +from argparse import ArgumentTypeError as err from base64 import b64decode from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler from pathlib import Path +class PathType(object): + def __init__(self, exists=True, type='file', dash_ok=True): + '''exists: + True: a path that does exist + False: a path that does not exist, in a valid parent directory + None: don't care + type: file, dir, symlink, None, or a function returning True for valid paths + None: don't care + dash_ok: whether to allow "-" as stdin/stdout''' -def restartContainerWithDomain(domain): - client = docker.from_env() - container = client.containers.list(filters = {"label" : "com.github.SnowMB.traefik-certificate-extractor.restart_domain"}) - for c in container: -# print(c.labels['com.github.SnowMB.traefik-certificate-extractor.restart_domain']) - domains = str.split(c.labels["com.github.SnowMB.traefik-certificate-extractor.restart_domain"], ',') - if domain in domains: - print('restarting container ' + c.id) - c.restart() + assert exists in (True, False, None) + assert type in ('file','dir','symlink',None) or hasattr(type,'__call__') + + self._exists = exists + self._type = type + self._dash_ok = dash_ok + + def __call__(self, string): + if string=='-': + # the special argument "-" means sys.std{in,out} + if self._type == 'dir': + raise err('standard input/output (-) not allowed as directory path') + elif self._type == 'symlink': + raise err('standard input/output (-) not allowed as symlink path') + elif not self._dash_ok: + raise err('standard input/output (-) not allowed') + else: + e = os.path.exists(string) + if self._exists==True: + if not e: + raise err("path does not exist: '%s'" % string) + + if self._type is None: + pass + elif self._type=='file': + if not os.path.isfile(string): + raise err("path is not a file: '%s'" % string) + elif self._type=='symlink': + if not os.path.symlink(string): + raise err("path is not a symlink: '%s'" % string) + elif self._type=='dir': + if not os.path.isdir(string): + raise err("path is not a directory: '%s'" % string) + elif not self._type(string): + raise err("path not valid: '%s'" % string) + else: + if self._exists==False and e: + raise err("path exists: '%s'" % string) + + p = os.path.dirname(os.path.normpath(string)) or '.' + if not os.path.isdir(p): + raise err("parent path is not a directory: '%s'" % p) + elif not os.path.exists(p): + raise err("parent directory does not exist: '%s'" % p) + + return string + + +#def restartContainerWithDomain(domain): +# client = docker.from_env() +# container = client.containers.list(filters = {"label" : "com.github.SnowMB.traefik-certificate-extractor.restart_domain"}) +# for c in container: +# domains = str.split(c.labels["com.github.SnowMB.traefik-certificate-extractor.restart_domain"], ',') +# if domain in domains: +# print('restarting container ' + c.id) +# c.restart() @@ -104,8 +161,8 @@ def createCerts(file): class Handler(FileSystemEventHandler): - def __init__(self): - self.filename = 'acme.json' + def __init__(self, args): + self.args = args def on_created(self, event): self.handle(event) @@ -116,32 +173,25 @@ class Handler(FileSystemEventHandler): def handle(self, event): # Check if it's a JSON file print ('DEBUG : event fired') - if not event.is_directory and event.src_path.endswith(self.filename): + if not event.is_directory and event.src_path.endswith(str(self.args.FILE)): print('Certificates changed') createCerts(event.src_path) if __name__ == "__main__": - # Determine path to watch - val = sys.argv[1] if len(sys.argv) > 1 else './data/acme.json' + parser = argparse.ArgumentParser(description='Extract traefik letsencrypt certificates.') + parser.add_argument('FILE', nargs='?', default='acme.json', type= PathType(exists=True), help='file that contains the traefik certificates (default acme.json)') + parser.add_argument('OUTPUT', nargs='?', default='.', type=PathType(type='dir'), help='output folder') + parser.add_argument('-f', '--flat',action='store_true', help='outputs all certificates into one folder') + args = parser.parse_args() - path = Path(val) - - if not path.exists() or path.is_dir(): - print ('ERROR ' + str(path) + ' does not exist.') - sys.exit(1) - - print('watching path: ' + str(path)) + print('DEBUG: watching path: ' + str(args.FILE)) + print('DEBUG: output path: ' + str(args.OUTPUT)) # Create output directories if it doesn't exist try: - os.makedirs('certs') - except OSError as error: - if error.errno != errno.EEXIST: - raise - try: - os.makedirs('certs_flat') + os.makedirs(args.OUTPUT) except OSError as error: if error.errno != errno.EEXIST: raise @@ -149,12 +199,11 @@ if __name__ == "__main__": # Create event handler and observer - event_handler = Handler() - event_handler.filename = str(path.name) + event_handler = Handler(args) observer = Observer() # Register the directory to watch - observer.schedule(event_handler, str(path.parent)) + observer.schedule(event_handler, str(args.FILE.parent)) # Main loop to watch the directory observer.start()