blob: b8bc8b571fad26d76ec8b5ffc4cc33cd28e83289 [file] [log] [blame]
# 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)