diff --git a/runbot/container.py b/runbot/container.py index e5538340..7796e607 100644 --- a/runbot/container.py +++ b/runbot/container.py @@ -28,15 +28,6 @@ with warnings.catch_warnings(): _logger = logging.getLogger(__name__) -DOCKERUSER = """ -RUN groupadd -g %(group_id)s odoo \\ -&& useradd -u %(user_id)s -g odoo -G audio,video odoo \\ -&& mkdir /home/odoo \\ -&& chown -R odoo:odoo /home/odoo -USER odoo -ENV COVERAGE_FILE /data/build/.coverage -""" % {'group_id': os.getgid(), 'user_id': os.getuid()} - class Command(): @@ -113,9 +104,6 @@ def _docker_build(build_dir, image_tag): :param image_tag: name used to tag the resulting docker image :return: tuple(success, msg) where success is a boolean and msg is the error message or None """ - # synchronise the current user with the odoo user inside the Dockerfile - with open(os.path.join(build_dir, 'Dockerfile'), 'a') as df: - df.write(DOCKERUSER) docker_client = docker.from_env() try: docker_client.images.build(path=build_dir, tag=image_tag, rm=True) diff --git a/runbot/models/build.py b/runbot/models/build.py index 9977513c..dde8e190 100644 --- a/runbot/models/build.py +++ b/runbot/models/build.py @@ -19,6 +19,7 @@ from odoo.tools.safe_eval import safe_eval from collections import defaultdict from psycopg2 import sql from subprocess import CalledProcessError +import getpass _logger = logging.getLogger(__name__) @@ -770,7 +771,8 @@ class BuildResult(models.Model): else: rc_content = starting_config self.write_file('.odoorc', rc_content) - ro_volumes['/home/odoo/.odoorc'] = self._path('.odoorc') + user = getpass.getuser() + ro_volumes[f'/home/{user}/.odoorc'] = self._path('.odoorc') kwargs.pop('build_dir', False) # todo check python steps docker_run(cmd=cmd, build_dir=self._path(), ro_volumes=ro_volumes, **kwargs) diff --git a/runbot/models/host.py b/runbot/models/host.py index fb4fde22..8c879a11 100644 --- a/runbot/models/host.py +++ b/runbot/models/host.py @@ -1,4 +1,5 @@ import logging +import getpass from odoo import models, fields, api from odoo.tools import config from ..common import fqdn, local_pgadmin_cursor, os @@ -79,16 +80,32 @@ class Host(models.Model): static_path = self._get_work_path() self.clear_caches() # needed to ensure that content is updated on all hosts for dockerfile in self.env['runbot.dockerfile'].search([('to_build', '=', True)]): - _logger.info('Building %s, %s', dockerfile.name, hash(str(dockerfile.dockerfile))) - docker_build_path = os.path.join(static_path, 'docker', dockerfile.image_tag) - os.makedirs(docker_build_path, exist_ok=True) - with open(os.path.join(docker_build_path, 'Dockerfile'), 'w') as Dockerfile: - Dockerfile.write(dockerfile.dockerfile) - docker_build_success, msg = docker_build(docker_build_path, dockerfile.image_tag) - if not docker_build_success: - dockerfile.to_build = False - dockerfile.message_post(body=f'Build failure:\n{msg}') - self.env['runbot.runbot'].warning(f'Dockerfile build "{dockerfile.image_tag}" failed on host {self.name}') + self._docker_build_dockerfile(dockerfile, static_path) + + def _docker_build_dockerfile(self, dockerfile, workdir): + _logger.info('Building %s, %s', dockerfile.name, hash(str(dockerfile.dockerfile))) + docker_build_path = os.path.join(workdir, 'docker', dockerfile.image_tag) + os.makedirs(docker_build_path, exist_ok=True) + + user = getpass.getuser() + + docker_append = f""" + RUN groupadd -g {os.getgid()} {user} \\ + && useradd -u {os.getuid()} -g {user} -G audio,video {user} \\ + && mkdir /home/{user} \\ + && chown -R {user}:{user} /home/{user} + USER {user} + ENV COVERAGE_FILE /data/build/.coverage + """ + + with open(os.path.join(docker_build_path, 'Dockerfile'), 'w') as Dockerfile: + Dockerfile.write(dockerfile.dockerfile + docker_append) + + docker_build_success, msg = docker_build(docker_build_path, dockerfile.image_tag) + if not docker_build_success: + dockerfile.to_build = False + dockerfile.message_post(body=f'Build failure:\n{msg}') + self.env['runbot.runbot'].warning(f'Dockerfile build "{dockerfile.image_tag}" failed on host {self.name}') def _get_work_path(self): return os.path.abspath(os.path.join(os.path.dirname(__file__), '../static')) diff --git a/runbot/tests/test_upgrade.py b/runbot/tests/test_upgrade.py index 582016fc..0e866d6d 100644 --- a/runbot/tests/test_upgrade.py +++ b/runbot/tests/test_upgrade.py @@ -1,4 +1,5 @@ import logging +import getpass from odoo.exceptions import UserError from odoo.tools import mute_logger from .common import RunbotCase @@ -438,7 +439,8 @@ class TestUpgradeFlow(RunbotCase): self.patchers['docker_run'].assert_called() def docker_run_upgrade(cmd, *args, ro_volumes=False, **kwargs): - self.assertTrue(ro_volumes.pop('/home/odoo/.odoorc').startswith('/tmp/runbot_test/static/build/')) + user = getpass.getuser() + self.assertTrue(ro_volumes.pop(f'/home/{user}/.odoorc').startswith('/tmp/runbot_test/static/build/')) self.assertEqual( ro_volumes, { '/data/build/addons': '/tmp/runbot_test/static/sources/addons/addons120',