Forráskód Böngészése

add docker support

Olivier Massot 5 éve
szülő
commit
2d0c6fd0a8

+ 17 - 10
clonedb.py

@@ -27,6 +27,7 @@ from docopt import docopt
 from path import Path
 
 from core import logging_
+from core.docker import resolve_docker_ip
 from core.locker import Lockfile
 from core.pipe_handler import PipeHandler
 from core.ssh import SshTunnel
@@ -38,7 +39,7 @@ HERE = Path(__file__).parent
 
 # Start logger
 logger = logging.getLogger('clonedb')
-logging_.start("clonedb", replace=True)
+logging_.start("clonedb", filename=HERE / 'log' / 'clonedb.log', replace=True)
 
 # FIX the default ascii encoding on some linux dockers...
 sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1)
@@ -47,8 +48,8 @@ sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1)
 SHOW_PROGRESSION = True
 MAX_ALLOWED_PACKET = 1073741824
 
-LOG_MYSQL_QUERIES = False
-LOG_MYSQLDUMP_OUTPUT = False
+DEBUG = False
+LOG_MYSQL_QUERIES = DEBUG
 
 
 # Utilities
@@ -72,11 +73,9 @@ class MysqldumpHandler(PipeHandler):
         if SHOW_PROGRESSION:
             match = self._rx_newtable.search(line)
             if match:
-                if not LOG_MYSQLDUMP_OUTPUT:
-                    logger.debug('... %s', match.group(1))
+                # logger.debug('... %s', match.group(1))
                 print('.', end="", flush=True)
-        if LOG_MYSQLDUMP_OUTPUT:
-            logger.debug(line)
+        logger.debug(line)
 
     def close(self):
         """ Close the write end of the pipe.
@@ -284,7 +283,6 @@ class CloningOperation:
         logger.debug(">>> Piped into: %s", " ".join(map(str, restore_cmd)))
 
         pipe_handler = MysqldumpHandler(logger.name)
-
         try:
             # noinspection PyTypeChecker
             with Popen(restore_cmd, stdin=PIPE, stdout=pipe_handler, stderr=pipe_handler) as mysql:
@@ -292,8 +290,10 @@ class CloningOperation:
                 with Popen(dump_cmd, stdout=PIPE, stderr=pipe_handler) as mysqldump:
                     mysql.stdin.write(mysqldump.stdout.read())
 
-            if mysqldump.returncode or mysql.returncode:
-                raise RuntimeError
+            if mysqldump.returncode:
+                raise RuntimeError('mysqldump returned a non zero code')
+            if mysql.returncode:
+                raise RuntimeError('mysql returned a non zero code')
 
         except (OSError, RuntimeError, CalledProcessError) as e:
             logger.error("Execution failed: %s", e)
@@ -392,6 +392,13 @@ def main(settings, arguments):
     for server_name, server_settings in settings['servers'].items():
         hostname = server_settings['host']
 
+        match = re.search(r"^docker:(\w+)$", hostname)
+        if match:
+            logger.debug("resolve IP for docker %s", match.group(1))
+            ip = resolve_docker_ip(match.group(1))
+            logger.debug("substitute '%s' to '%s' as hostname", ip, hostname)
+            hostname = ip
+
         if 'ssh' in server_settings:
             ssh_tunnel = SshTunnel(hostname, server_settings['mysql']['port'], **server_settings['ssh'])
         else:

BIN
core/__pycache__/docker.cpython-36.pyc


BIN
core/__pycache__/pipe_handler.cpython-36.pyc


+ 20 - 0
core/docker.py

@@ -0,0 +1,20 @@
+"""
+Docker support
+
+@author: olivier.massot, 05-2020
+"""
+import subprocess
+from subprocess import Popen, PIPE
+
+
+def resolve_docker_ip(docker_name):
+    cmd = ["docker",
+           "inspect",
+           "-f",
+           "'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'",
+           docker_name]
+    try:
+        output = subprocess.check_output(cmd)
+    except subprocess.CalledProcessError as e:
+        raise RuntimeError("An error occured while retrieving IP for docker %s: %s", docker_name, e)
+    return output.decode('utf-8').strip('\n').replace("'", "")

+ 1 - 1
core/pipe_handler.py

@@ -9,7 +9,7 @@ import threading
 
 
 class PipeHandler(threading.Thread):
-    """ Handle the stderr output from a Popen object """
+    """ Handle the stdout/stderr output from a Popen object """
 
     def __init__(self, logger_name, default_level=logging.INFO):
         """ Setup the object with a logger and a loglevel