diff --git a/runbot/container.py b/runbot/container.py index 86c51180..06c5d14f 100644 --- a/runbot/container.py +++ b/runbot/container.py @@ -166,7 +166,7 @@ def _docker_pull(image_tag): """Pull a docker image from a registry. :param image_tag: the full image tag, including the registry host e.g.: `dockerhub.runbot102.odoo.com/odoo:PureNobleTest` - :return: tuple(success, image) where success is a boolean and image a Docker image object or None in case of failure + :return: DockerMager.result dict """ with DockerManager(image_tag) as dm: for chunk in dm.consume(dm.docker_client.api.pull(image_tag, stream=True)): diff --git a/runbot/docker_manager.py b/runbot/docker_manager.py index 1c298bcb..08072e1e 100644 --- a/runbot/docker_manager.py +++ b/runbot/docker_manager.py @@ -57,6 +57,7 @@ class DockerManager: def __exit__(self, exception_type, exception_value, exception_traceback): if self.log_progress: _logger.info('Finished in %.2fs', self.duration) + self.result['log_progress'] = self.log_progress if exception_value: self.result['success'] = False _logger.warning(exception_value) diff --git a/runbot/models/build.py b/runbot/models/build.py index 11d0fd56..e546125d 100644 --- a/runbot/models/build.py +++ b/runbot/models/build.py @@ -16,7 +16,7 @@ from psycopg2 import sql from psycopg2.extensions import TransactionRollbackError from ..common import dt2time, now, grep, local_pgadmin_cursor, s2human, dest_reg, os, list_local_dbs, pseudo_markdown, RunbotException, findall, sanitize, markdown_escape -from ..container import docker_stop, docker_state, Command, docker_run +from ..container import docker_stop, docker_state, Command, docker_run, docker_pull from ..fields import JsonDictField from odoo import models, fields, api @@ -853,6 +853,15 @@ class BuildResult(models.Model): if 'image_tag' not in kwargs: kwargs.update({'image_tag': self.params_id.dockerfile_id.image_tag}) self._log('Preparing', 'Using Dockerfile Tag [%s](/runbot/dockerfile/tag/%s)', kwargs['image_tag'], kwargs['image_tag'], log_type='markdown') + icp = self.env['ir.config_parameter'] + docker_registry_host = self.env['runbot.host'].browse(int(icp.get_param('runbot.docker_registry_host_id', default=0))) + if docker_registry_host and self.host_id.use_remote_docker_registry: + result = docker_pull(f"dockerhub.{docker_registry_host.name}/{kwargs['image_tag']}") + if result['success']: + result['image'].tag(kwargs['image_tag']) + if result.get('log_progress'): + self._log('Docker Run', f'Docker image was pulled {"" if result["success"] else "with errors"}') + containers_memory_limit = self.env['ir.config_parameter'].sudo().get_param('runbot.runbot_containers_memory', 0) if containers_memory_limit and 'memory' not in kwargs: kwargs['memory'] = int(float(containers_memory_limit) * 1024 ** 3) diff --git a/runbot/models/docker.py b/runbot/models/docker.py index c5d6e774..c61971a9 100644 --- a/runbot/models/docker.py +++ b/runbot/models/docker.py @@ -128,6 +128,7 @@ class Dockerfile(models.Model): arch_base = fields.Text(related='template_id.arch_base', readonly=False, related_sudo=True) dockerfile = fields.Text(compute='_compute_dockerfile', tracking=True) to_build = fields.Boolean('To Build', help='Build Dockerfile. Check this when the Dockerfile is ready.', default=False) + always_pull = fields.Boolean('Always pull', help='Always Pull on the hosts, not only at the use time', default=False, tracking=True) version_ids = fields.One2many('runbot.version', 'dockerfile_id', string='Versions') description = fields.Text('Description') view_ids = fields.Many2many('ir.ui.view', compute='_compute_view_ids', groups="runbot.group_runbot_admin") diff --git a/runbot/models/host.py b/runbot/models/host.py index a0dd7b89..d3cdc1d9 100644 --- a/runbot/models/host.py +++ b/runbot/models/host.py @@ -130,11 +130,16 @@ class Host(models.Model): all_tags = set(all_docker_files.mapped('image_tag')) if docker_registry_host and self.use_remote_docker_registry and not is_registry: _logger.info('Pulling docker images...') - for dockerfile in all_docker_files: + total_duration = 0 + for dockerfile in all_docker_files.filtered('always_pull'): remote_tag = f'dockerhub.{docker_registry_host.name}/{dockerfile.image_tag}' result = docker_pull(remote_tag) if result['success']: result['image'].tag(dockerfile.image_tag) + total_duration += result['duration'] + if total_duration > 60: + _logger.warning("Pulling images took more than 60 seconds... will continue later") + break else: _logger.info('Building docker images...') for dockerfile in self.env['runbot.dockerfile'].search([('to_build', '=', True)]): diff --git a/runbot/views/dockerfile_views.xml b/runbot/views/dockerfile_views.xml index b7b6d1f7..ec6e0e49 100644 --- a/runbot/views/dockerfile_views.xml +++ b/runbot/views/dockerfile_views.xml @@ -13,6 +13,7 @@ + @@ -104,6 +105,8 @@ + +