diff --git a/runbot/controllers/frontend.py b/runbot/controllers/frontend.py index 38b13229..c7980c1d 100644 --- a/runbot/controllers/frontend.py +++ b/runbot/controllers/frontend.py @@ -662,3 +662,33 @@ class Runbot(Controller): 'trigger': trigger_id, 'project': trigger_id.project_id, }) + + @route([ + '/runbot/dockerfile', + '/runbot/dockerfile/', + '/runbot/dockerfile/tag/', + '/runbot/dockerfile/version/', + ], type='http', auth='public', sitemap=False) + def dockerfile_content(self, dockerfile_id=None, version=None, docker_tag=None, **kwargs): + dockerfile_sudo = request.env['runbot.dockerfile'].sudo() + if 'id' in kwargs: + dockerfile_id = int(kwargs['id']) + if dockerfile_id: # keep 'id' for historical reasons + dockerfile = dockerfile_sudo.browse(dockerfile_id).exists() + elif docker_tag: + dockerfile = dockerfile_sudo.search([('image_tag', '=', docker_tag)]) + elif version: + dockerfile = dockerfile_sudo.search([('version_ids.name', '=', version)]) + else: + raise NotFound + + if dockerfile.public_visibility: + return Response(response=dockerfile.layer_ids.render_layers({ + 'USERUID': '${USERUID}', + 'USERGID': '${USERGID}', + 'USERNAME': '${USERNAME}', + }), status=200, mimetype='text/plain') + + if dockerfile: + _logger.error('Trying to access a non public docker image') + raise NotFound diff --git a/runbot/data/runbot_data.xml b/runbot/data/runbot_data.xml index 8f812caa..adef8dc3 100644 --- a/runbot/data/runbot_data.xml +++ b/runbot/data/runbot_data.xml @@ -42,6 +42,11 @@ admin_passwd=running_master_password + + runbot.runbot_dockerfile_public_by_default + + + runbot.runbot_is_base_regex ^((master)|(saas-)?\d+\.\d+)$ diff --git a/runbot/models/build.py b/runbot/models/build.py index 04cc5c8d..063ccd73 100644 --- a/runbot/models/build.py +++ b/runbot/models/build.py @@ -850,8 +850,7 @@ class BuildResult(models.Model): ro_volumes[f'/data/build/{dest}'] = source if 'image_tag' not in kwargs: kwargs.update({'image_tag': self.params_id.dockerfile_id.image_tag}) - if kwargs['image_tag'] != 'odoo:DockerDefault': - self._log('Preparing', 'Using Dockerfile Tag %s' % kwargs['image_tag']) + self._log('Preparing', 'Using Dockerfile Tag [%s](/runbot/dockerfile/tag/%s)' % (kwargs['image_tag'], kwargs['image_tag']), log_type='markdown') 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 0c5a7417..e5063564 100644 --- a/runbot/models/docker.py +++ b/runbot/models/docker.py @@ -140,7 +140,9 @@ class Dockerfile(models.Model): referencing_dockerlayer_ids = fields.One2many('runbot.docker_layer', 'reference_dockerfile_id', string='Layers referencing this one') use_count = fields.Integer('Used count', compute="_compute_use_count", store=True) # maybe we should have global values here? branch version, chrome version, ... then use a os layer when possible (jammy, ...) - # we could also have a variant param, to use the version image in a specific trigger? Add a layer or change a param? + # we could also have a variant param, to use the version image in a specific trigger? Add a layer or change a param? + + public_visibility = fields.Boolean('Public', default=lambda self: self.env['ir.config_parameter'].sudo().get_param('runbot.runbot_dockerfile_public_by_default'), help="Dockerfile is public and can be accessed by anyone with /runbot/dockerfile route") _sql_constraints = [('runbot_dockerfile_name_unique', 'unique(name)', 'A Dockerfile with this name already exists')] diff --git a/runbot/models/res_config_settings.py b/runbot/models/res_config_settings.py index a8d8eaff..77f52797 100644 --- a/runbot/models/res_config_settings.py +++ b/runbot/models/res_config_settings.py @@ -29,6 +29,7 @@ class ResConfigSettings(models.TransientModel): runbot_forwardport_author = fields.Char('Forwardbot author') runbot_organisation = fields.Char('Organisation') runbot_disable_host_on_fetch_failure = fields.Boolean('Disable host on fetch failure') + runbot_dockerfile_public_by_default = fields.Boolean('Docker files are public by default') runbot_use_ssl = fields.Boolean('Use ssl for workers', help="select if worker ressources (log, dump, ...) uses ssl or not.", config_parameter="runbot.use_ssl") runbot_db_gc_days = fields.Integer( @@ -77,6 +78,7 @@ class ResConfigSettings(models.TransientModel): runbot_forwardport_author=get_param('runbot.runbot_forwardport_author', default=''), runbot_organisation=get_param('runbot.runbot_organisation', default=''), runbot_disable_host_on_fetch_failure=get_param('runbot.runbot_disable_host_on_fetch_failure', default=False), + runbot_dockerfile_public_by_default=get_param('runbot.runbot_dockerfile_public_by_default', default=False), ) return res @@ -101,6 +103,7 @@ class ResConfigSettings(models.TransientModel): set_param('runbot.runbot_forwardport_author', self.runbot_forwardport_author) set_param('runbot.runbot_organisation', self.runbot_organisation) set_param('runbot.runbot_disable_host_on_fetch_failure', self.runbot_disable_host_on_fetch_failure) + set_param('runbot.runbot_dockerfile_public_by_default', self.runbot_dockerfile_public_by_default) @api.onchange('runbot_is_base_regex') def _on_change_is_base_regex(self): diff --git a/runbot/views/dockerfile_views.xml b/runbot/views/dockerfile_views.xml index 07b0c4d8..077542a6 100644 --- a/runbot/views/dockerfile_views.xml +++ b/runbot/views/dockerfile_views.xml @@ -14,6 +14,7 @@ + @@ -105,6 +106,7 @@ + diff --git a/runbot/views/res_config_settings_views.xml b/runbot/views/res_config_settings_views.xml index e98e75da..65b9a483 100644 --- a/runbot/views/res_config_settings_views.xml +++ b/runbot/views/res_config_settings_views.xml @@ -37,6 +37,9 @@ + + +