diff --git a/docker/macros.j2 b/docker/macros.j2 index c10973ef64..5cdb12b4cc 100644 --- a/docker/macros.j2 +++ b/docker/macros.j2 @@ -1,7 +1,12 @@ {% macro install_packages(packages) -%} {% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] -%} - yum -y install {{ packages | join(' ') }} && yum clean all + yum -y install {{ packages | join(' ') }} && yum clean all {%- elif base_distro in ['ubuntu', 'debian'] -%} - apt-get -y install --no-install-recommends {{ packages | join(' ') }} && apt-get clean + {#- + debian_package_install is a utility method to build up an appropriate + set of commands to install packages in a debian-based environment that + may include URL links to a .deb package (e.g, heka) + -#} + {{ debian_package_install(packages) }} {%- endif %} {%- endmacro %} diff --git a/kolla/image/build.py b/kolla/image/build.py index 090b28f4b5..20d26e01b2 100644 --- a/kolla/image/build.py +++ b/kolla/image/build.py @@ -51,6 +51,7 @@ if PROJECT_ROOT not in sys.path: from kolla.common import config as common_config from kolla.common import task from kolla.template import filters as jinja_filters +from kolla.template import methods as jinja_methods from kolla import version @@ -625,6 +626,17 @@ class KollaWorker(object): } return filters + def _get_methods(self): + """Mapping of available Jinja methods + + return a dictionary that maps available function names and their + corresponding python methods to make them available in jinja templates + """ + + return { + 'debian_package_install': jinja_methods.debian_package_install, + } + def create_dockerfiles(self): kolla_version = version.version_info.cached_version_string() supported_distro_release = common_config.DISTRO_RELEASE.get( @@ -648,6 +660,7 @@ class KollaWorker(object): env = jinja2.Environment( # nosec: not used to render HTML loader=jinja2.FileSystemLoader(self.working_dir)) env.filters.update(self._get_filters()) + env.globals.update(self._get_methods()) tpl_path = os.path.join( os.path.relpath(path, self.working_dir), template_name) diff --git a/kolla/template/methods.py b/kolla/template/methods.py new file mode 100644 index 0000000000..8e655f4c8a --- /dev/null +++ b/kolla/template/methods.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def debian_package_install(packages): + """Jinja utility method for building debian-based package install command + + apt-get is not capable of installing .deb files from a URL and the + template logic to construct a series of steps to install regular packages + from apt repos as well as .deb files that need to be downloaded, manually + installed, and cleaned up is complicated. This method will contruct the + proper string required to install all packages in a way that's a bit + easier to follow + + :param packages: a list of strings that are either packages to install + from an apt repo, or URLs to .deb files + :type packages: list + + :returns: string suitable to provide to RUN command in a Dockerfile that + will install the given packages + :rtype: string + """ + cmds = [] + + # divide the list into two groups, one for regular packages and one for + # URL packages + reg_packages, url_packages = [], [] + for package in packages: + if package.startswith('http'): + url_packages.append(package) + else: + reg_packages.append(package) + + # handle the apt-get install + if reg_packages: + cmds.append('apt-get -y install --no-install-recommends {}'.format( + ' '.join(reg_packages) + )) + cmds.append('apt-get clean') + + # handle URL packages + for url in url_packages: + # the path portion should be the file name + name = url[url.rfind('/') + 1:] + cmds.extend([ + 'curl --location {} -o {}'.format(url, name), + 'dpkg -i {}'.format(name), + 'rm -rf {}'.format(name), + ]) + + # return the list of commands + return ' && '.join(cmds)