| # Copyright 2017 The Bazel Authors. All rights reserved. |
| # |
| # 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. |
| |
| load("@base_images_docker//package_managers:apt_key.bzl", _apt_key = "key") |
| load("@base_images_docker//package_managers:download_pkgs.bzl", _download_deb_pkgs = "download") |
| load("@bazel_skylib//lib:dicts.bzl", "dicts") |
| |
| def _input_validation(kwargs): |
| allowed_attribues = ["name", "base", "language_layers"] |
| |
| for key in kwargs.keys(): |
| if key not in allowed_attribues: |
| fail("Attribute " + key + " is not supported.") |
| |
| container = [ |
| ".tar.gz", |
| ".tgz", |
| ".tar", |
| ".tar.xz", |
| ] |
| |
| generate_deb_tar_attrs = dicts.add(_download_deb_pkgs.attrs, { |
| "base": attr.label(allow_files = container), |
| "keys": attr.label_list( |
| allow_files = True, |
| ), |
| "packages": attr.string_list(), |
| }) |
| |
| aggregate_debian_pkgs_attrs = { |
| |
| # Declare the following attributes since _download_deb_pkgs.implementation |
| # need access those attribute if their overrides are None |
| "additional_repos": attr.string_list(), |
| "base": attr.label(allow_files = container), |
| "language_layers": attr.label_list(), |
| "_image_id_extractor": attr.label( |
| default = "@io_bazel_rules_docker//contrib:extract_image_id.py", |
| allow_single_file = True, |
| ), |
| } |
| |
| InstallableTarInfo = provider(fields = [ |
| "installables_tar", |
| ]) |
| |
| def _generate_deb_tar( |
| ctx, |
| packages = None, |
| additional_repos = None, |
| keys = None, |
| download_pkgs_output_tar = None, |
| download_pkgs_output_script = None): |
| """A function for producing a tarball for a set of debian packages. |
| |
| Args: |
| ctx: ctx has either generate_deb_tar_attrs or aggregate_debian_pkgs_attrs, |
| this depends on the rule that uses this function |
| packages: list of packages to fetch and install in the base image. |
| additional_repos: list of additional debian package repos to use, |
| in sources.list format. |
| keys: list of labels of additional gpg keys to use while downloading |
| packages. |
| download_pkgs_output_tar: output tar file generated by download_pkgs rule to |
| override default output_tar |
| download_pkgs_output_script: output script generated by download_pkgs rule to |
| override default output_script |
| """ |
| |
| # Prepare base image for the download_pkgs rule. |
| download_base = ctx.files.base[0] |
| |
| # Create an intermediate image with additional gpg keys used to download packages. |
| if keys != []: |
| image_with_keys = "%s_with_keys" % ctx.attr.name |
| |
| # Declare intermediate output file generated by add_apt_key rule. |
| image_with_keys_output_executable = ctx.actions.declare_file(image_with_keys) |
| image_with_keys_output_tarball = ctx.actions.declare_file(image_with_keys + ".tar") |
| image_with_keys_output_layer = ctx.actions.declare_file(image_with_keys + "-layer.tar") |
| image_with_keys_output_digest = ctx.actions.declare_file(image_with_keys + ".digest") |
| |
| _apt_key.implementation( |
| ctx, |
| name = image_with_keys, |
| image_tar = ctx.files.base[0], |
| keys = keys, |
| output_executable = image_with_keys_output_executable, |
| output_tarball = image_with_keys_output_tarball, |
| output_layer = image_with_keys_output_layer, |
| output_digest = image_with_keys_output_digest, |
| ) |
| download_base = image_with_keys_output_tarball |
| |
| # Declare intermediate output file generated by download_pkgs rule. |
| output_executable = ctx.actions.declare_file(ctx.attr.name + "-output_executable.sh") |
| download_pkgs_output_tar = download_pkgs_output_tar or ctx.attr.name + ".tar" |
| download_pkgs_output_script = download_pkgs_output_script or ctx.attr.name + ".sh" |
| output_tar = ctx.actions.declare_file(download_pkgs_output_tar) |
| output_script = ctx.actions.declare_file(download_pkgs_output_script) |
| |
| # download_pkgs rule consumes 'packages' and 'additional_repos'. |
| _download_deb_pkgs.implementation( |
| ctx, |
| image_tar = download_base, |
| packages = packages, |
| additional_repos = additional_repos, |
| output_executable = output_executable, |
| output_tar = output_tar, |
| output_script = output_script, |
| ) |
| |
| return struct( |
| providers = [ |
| InstallableTarInfo( |
| installables_tar = output_tar, |
| ), |
| ], |
| ) |
| |
| def _aggregate_debian_pkgs_impl(ctx): |
| """Implementation for the aggregate_debian_pkgs rule. |
| |
| aggregate_debian_pkgs rule produces a tarball with all debian packages declared |
| in the language_tool_layer(s) this rule depends on. |
| |
| Args: |
| ctx: ctx only has name, base, and language_layers attributes |
| """ |
| |
| packages = [] |
| additional_repos = [] |
| keys = [] |
| |
| for layer in ctx.attr.language_layers: |
| packages.extend(layer.packages) |
| additional_repos.extend(layer.additional_repos) |
| keys.extend(layer.keys) |
| |
| packages = depset(packages).to_list() |
| additional_repos = depset(additional_repos).to_list() |
| keys = depset(keys).to_list() |
| |
| return _generate_deb_tar( |
| ctx, |
| packages = packages, |
| additional_repos = additional_repos, |
| keys = keys, |
| ) |
| |
| # Export _generate_deb_tar function for other bazel rules to use. |
| generate = struct( |
| attrs = generate_deb_tar_attrs, |
| outputs = _download_deb_pkgs.outputs, |
| implementation = _generate_deb_tar, |
| ) |
| |
| aggregate_debian_pkgs_ = rule( |
| attrs = aggregate_debian_pkgs_attrs, |
| outputs = _download_deb_pkgs.outputs, |
| implementation = _aggregate_debian_pkgs_impl, |
| ) |
| |
| def aggregate_debian_pkgs(**kwargs): |
| """Aggregate debian packages from multiple language_tool_layers into a tarball. |
| |
| Args: |
| name: a unique name for this rule. |
| base: base os image used for this rule. |
| language_layers: a list of language_tool_layer targets. |
| |
| Only name, base, and language_layers attributes are allowed in this rule. |
| |
| Experimental rule. |
| """ |
| |
| _input_validation(kwargs) |
| |
| aggregate_debian_pkgs_(**kwargs) |