Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add convience targets #115

Merged
merged 3 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions apt/private/deb_translate_lock.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"repository rule for generating a dependency graph from a lockfile."

load("@bazel_skylib//lib:new_sets.bzl", "sets")
load(":lockfile.bzl", "lockfile")
load(":starlark_codegen_utils.bzl", "starlark_codegen_utils")

# header template for packages.bzl file
_DEB_IMPORT_HEADER_TMPL = '''\
Expand All @@ -20,12 +22,87 @@ _DEB_IMPORT_TMPL = '''\
)
'''

_BUILD_TMPL = """\
exports_files(glob(['packages.bzl']))
_PACKAGE_TEMPLATE = """\
alias(
name = "{target_name}",
actual = select({data_targets}),
visibility = ["//visibility:public"],
)

alias(
name = "control",
actual = select({control_targets}),
visibility = ["//visibility:public"],
)
"""

_ROOT_BUILD_TMPL = """\
"Generated by rules_distroless. DO NOT EDIT."

load("@rules_distroless//apt:defs.bzl", "dpkg_status")

exports_files(['packages.bzl'])

_ARCHITECTURE_MAP = {{
"amd64": "x86_64",
"arm64": "aarch64",
"ppc64el": "ppc",
"mips64el": "mips64"
}}

_ARCHITECTURES = {architectures}

# See officially supported platforms at https://www.debian.org/releases/stable/armel/ch02s01.en.html
thesayyn marked this conversation as resolved.
Show resolved Hide resolved
[
config_setting(
name = os + "_" + arch,
constraint_values = [
"@platforms//os:" + os,
"@platforms//cpu:" + (_ARCHITECTURE_MAP[arch] or arch),
],
)
for os in ["linux"]
for arch in _ARCHITECTURES
]


alias(
name = "lock",
actual = "@{}_resolve//:lock"
actual = "@{target_name}_resolve//:lock",
visibility = ["//visibility:public"],
)

# List of installed packages. For now it's private.
_PACKAGES = {packages}

# Creates /var/lib/dpkg/status with installed package information.
dpkg_status(
name = "dpkg_status",
controls = [
"//%s:control" % package
for package in _PACKAGES
],
visibility = ["//visibility:public"],
)

filegroup(
name = "packages",
srcs = [
"//%s" % package
for package in _PACKAGES
],
visibility = ["//visibility:public"],
)


# A filegroup that contains all the packages and the dpkg status file.
filegroup(
name = "{target_name}",
srcs = [
":dpkg_status",
":packages",
],
visibility = ["//visibility:public"],
)
"""

Expand All @@ -42,13 +119,20 @@ def _deb_translate_lock_impl(rctx):
if len(lockf.packages()) < 1:
package_defs.append(" pass")

# TODO: rework lockfile to include architecure information
architectures = sets.make()
packages = sets.make()
thesayyn marked this conversation as resolved.
Show resolved Hide resolved

for (package) in lockf.packages():
package_key = lockfile.make_package_key(
package["name"],
package["version"],
package["arch"],
)

sets.insert(architectures, package["arch"])
sets.insert(packages, package["name"])

if not lock_content:
package_defs.append(
_DEB_IMPORT_TMPL.format(
Expand All @@ -66,8 +150,8 @@ def _deb_translate_lock_impl(rctx):
package_template.format(
target_name = package["arch"],
src = '"@%s//:data"' % repo_name,
deps = ",\n ".join([
'"//%s/%s"' % (dep["name"], package["arch"])
deps = starlark_codegen_utils.to_list_attr([
"//%s/%s" % (dep["name"], package["arch"])
for dep in package["dependencies"]
]),
urls = [package["url"]],
Expand All @@ -78,8 +162,29 @@ def _deb_translate_lock_impl(rctx):
),
)

# TODO: rework lockfile to include architecure information and merge these two loops
thesayyn marked this conversation as resolved.
Show resolved Hide resolved
for (package) in lockf.packages():
rctx.file(
"%s/BUILD.bazel" % (package["name"]),
_PACKAGE_TEMPLATE.format(
target_name = package["name"],
data_targets = starlark_codegen_utils.to_dict_attr({
"//:linux_%s" % arch: "//%s/%s" % (package["name"], package["arch"])
for arch in architectures._values
}),
control_targets = starlark_codegen_utils.to_dict_attr({
"//:linux_%s" % arch: "//%s/%s:control" % (package["name"], package["arch"])
for arch in architectures._values
}),
),
)

rctx.file("packages.bzl", "\n".join(package_defs))
rctx.file("BUILD.bazel", _BUILD_TMPL.format(rctx.attr.name.split("~")[-1]))
rctx.file("BUILD.bazel", _ROOT_BUILD_TMPL.format(
target_name = rctx.attr.name.split("~")[-1],
packages = starlark_codegen_utils.to_list_attr(packages._values),
architectures = starlark_codegen_utils.to_list_attr(architectures._values),
))

deb_translate_lock = repository_rule(
implementation = _deb_translate_lock_impl,
Expand Down
4 changes: 1 addition & 3 deletions apt/private/package.BUILD.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,5 @@ alias(
filegroup(
name = "{target_name}",
visibility = ["//visibility:public"],
srcs = [
{deps}
] + [":data"]
srcs = {deps} + [":data"]
)
45 changes: 45 additions & 0 deletions apt/private/starlark_codegen_utils.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"Utilities for generating starlark source code"
thesayyn marked this conversation as resolved.
Show resolved Hide resolved

# https://github.com/aspect-build/rules_js/blob/main/npm/private/starlark_codegen_utils.bzl
def _to_list_attr(list, indent_count = 0, indent_size = 4, quote_value = True):
if not list:
return "[]"
tab = " " * indent_size
indent = tab * indent_count
result = "["
for v in list:
val = "\"{}\"".format(v) if quote_value else v
result += "\n%s%s%s," % (indent, tab, val)
result += "\n%s]" % indent
return result

def _to_dict_attr(dict, indent_count = 0, indent_size = 4, quote_key = True, quote_value = True):
if not len(dict):
return "{}"
tab = " " * indent_size
indent = tab * indent_count
result = "{"
for k, v in dict.items():
key = "\"{}\"".format(k) if quote_key else k
val = "\"{}\"".format(v) if quote_value else v
result += "\n%s%s%s: %s," % (indent, tab, key, val)
result += "\n%s}" % indent
return result

def _to_dict_list_attr(dict, indent_count = 0, indent_size = 4, quote_key = True):
if not len(dict):
return "{}"
tab = " " * indent_size
indent = tab * indent_count
result = "{"
for k, v in dict.items():
key = "\"{}\"".format(k) if quote_key else k
result += "\n%s%s%s: %s," % (indent, tab, key, v)
result += "\n%s}" % indent
return result

starlark_codegen_utils = struct(
to_list_attr = _to_list_attr,
to_dict_attr = _to_dict_attr,
to_dict_list_attr = _to_dict_list_attr,
)
78 changes: 32 additions & 46 deletions examples/debian_snapshot/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
load("@aspect_bazel_lib//lib:tar.bzl", "tar")
load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")
load("@container_structure_test//:defs.bzl", "container_structure_test")
load("@rules_distroless//apt:defs.bzl", "dpkg_status")
load("@rules_distroless//distroless:defs.bzl", "cacerts", "group", "passwd")
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_load")

Expand Down Expand Up @@ -54,66 +54,52 @@ cacerts(
}),
)

PACKAGES = [
"@bullseye//ncurses-base",
"@bullseye//libncurses6",
"@bullseye//tzdata",
"@bullseye_nolock//bash",
"@bullseye//coreutils",
"@bullseye//dpkg",
"@bullseye//apt",
"@bullseye//perl",
"@bullseye//openssl",
"@bullseye//nvidia-kernel-common",
]

# Creates /var/lib/dpkg/status with installed package information.
dpkg_status(
name = "dpkg_status",
controls = select({
"@platforms//cpu:arm64": [
"%s/arm64:control" % package
for package in PACKAGES
],
"@platforms//cpu:x86_64": [
"%s/amd64:control" % package
for package in PACKAGES
],
}),
)

oci_image(
name = "apt",
architecture = select({
"@platforms//cpu:arm64": "arm64",
"@platforms//cpu:x86_64": "amd64",
}),
name = "image",
architecture = "arm64",
thesayyn marked this conversation as resolved.
Show resolved Hide resolved
env = {
# Required to use the SSL certs from `cacerts()`
"SSL_CERT_FILE": "/etc/ssl/certs/ca-certificates.crt",
},
os = "linux",
tars = [
# This target contains all the installed packages.
"@bullseye//:bullseye",
thesayyn marked this conversation as resolved.
Show resolved Hide resolved
":sh",
":passwd",
":group",
":dpkg_status",
":cacerts",
] + select({
"@platforms//cpu:arm64": [
"%s/arm64" % package
for package in PACKAGES
],
"@platforms//cpu:x86_64": [
"%s/amd64" % package
for package in PACKAGES
],
],
)

platform(
name = "linux_arm64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm64",
],
)

platform(
name = "linux_amd64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)

platform_transition_filegroup(
name = "image_platform",
srcs = [":image"],
target_platform = select({
"@platforms//cpu:arm64": ":linux_arm64",
"@platforms//cpu:x86_64": ":linux_amd64",
}),
)

oci_load(
name = "tarball",
image = ":apt",
image = ":image_platform",
repo_tags = [
"distroless/test:latest",
],
Expand All @@ -125,7 +111,7 @@ container_structure_test(
"@platforms//cpu:arm64": ["test_linux_arm64.yaml"],
"@platforms//cpu:x86_64": ["test_linux_amd64.yaml"],
}),
image = ":apt",
image = ":image_platform",
target_compatible_with = select({
"@platforms//cpu:x86_64": ["@platforms//cpu:x86_64"],
"@platforms//cpu:arm64": ["@platforms//cpu:arm64"],
Expand Down
Loading
Loading