From 989513801abdfb3b05a5a746a5c5db95207e735f Mon Sep 17 00:00:00 2001 From: Christophe Monniez Date: Mon, 7 Jan 2019 12:01:46 +0100 Subject: [PATCH] [FIX] runbot: find docker gateway for build smtp host When a build is running, the stmp is the localhost. Since Docker builds, the localhost is the container which does not catch port 25 smtp. Mails are lost in the limbo. With this commit, the default gateway of the Docker network is used as smtp host for the builds. It's the responsability of the runbot host to catch smtp traffic from the container. This bridge interface exists by default on a system where Docker is running. However, Docker is affected by this issue: https://github.com/moby/moby/issues/26799 The first time the Docker daemon is installed, the Gateway is not defined on the bridge interface. When the Docker daemon is restarted, the gateway is correctly defined. Pay attention that restarting the Docker daemon will kill all the running/testing builds. --- runbot/container.py | 15 +++++++++++++++ runbot/models/build.py | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/runbot/container.py b/runbot/container.py index afd75c77..73b1da27 100644 --- a/runbot/container.py +++ b/runbot/container.py @@ -10,6 +10,7 @@ When testing this file: """ import argparse import datetime +import json import logging import os import shutil @@ -97,6 +98,17 @@ def docker_is_running(container_name): dinspect = subprocess.run(['docker', 'container', 'inspect', container_name], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL) return True if dinspect.returncode == 0 else False +def docker_get_gateway_ip(): + """Return the host ip of the docker default bridge gateway""" + docker_net_inspect = subprocess.run(['docker', 'network', 'inspect', 'bridge'], stdout=subprocess.PIPE) + if docker_net_inspect.returncode != 0: + return None + if docker_net_inspect.stdout: + try: + return json.loads(docker_net_inspect.stdout)[0]['IPAM']['Config'][0]['Gateway'] + except KeyError: + return None + def build(args): """Build container from CLI""" _logger.info('Building the base image container') @@ -157,6 +169,9 @@ def tests(args): '-r %s' % os.getlogin(), '-i', 'web', '--max-cron-threads=1', '--data-dir', '/data/build/datadir', '--workers', '2', '--longpolling-port', '8070'] + smtp_host = docker_get_gateway_ip() + if smtp_host: + odoo_cmd.extend(['--smtp', smtp_host]) container_name = 'odoo-container-test-%s' % datetime.datetime.now().microsecond docker_run(odoo_cmd, logfile, args.build_dir, container_name, exposed_ports=[args.odoo_port, args.odoo_port + 1], cpu_limit=300) diff --git a/runbot/models/build.py b/runbot/models/build.py index 69926f92..64abf0f0 100644 --- a/runbot/models/build.py +++ b/runbot/models/build.py @@ -12,7 +12,7 @@ import subprocess import time from subprocess import CalledProcessError from ..common import dt2time, fqdn, now, grep, time2str, rfind, uniq_list, local_pgadmin_cursor, get_py_version -from ..container import docker_build, docker_run, docker_stop, docker_is_running +from ..container import docker_build, docker_run, docker_stop, docker_is_running, docker_get_gateway_ip from odoo import models, fields, api from odoo.exceptions import UserError from odoo.http import request @@ -840,4 +840,7 @@ class runbot_build(models.Model): cmd += ['--db-filter', '%d.*$'] else: cmd += ['--db-filter', '%s.*$' % build.dest] + smtp_host = docker_get_gateway_ip() + if smtp_host: + cmd += ['--smtp', smtp_host] return docker_run(cmd, log_path, build._path(), build._get_docker_name(), exposed_ports = [build.port, build.port + 1])