Skip to content
This repository has been archived by the owner on Oct 2, 2023. It is now read-only.

Commit

Permalink
image.bzl: implement tag_name (#2205)
Browse files Browse the repository at this point in the history
rules_docker decides the name of the resulting docker image:

    bazel/{target}:{name}

The repository (`bazel/` by default) and `{target}` are fine. However,
we want to customize the tag part -- the thing after the colon. This
patch allows customizing the last part.

Why?
====

In our case, we are always building two images for two architectures
using transitions. Here is an extract of a macro that builds two
containers:

Then we build two containers using outgoing transitions:

    container_image(
        name = "{name}-post_transition".format(name = name),
        ...,
    )

    multiplatform_image(
        name = "{name}-amd64".format(name),
        src_image = ":{name}-post_transition".format(name = name),
        ...,
    )

    multiplatform_image(
        name = "{name}-arm64".format(name = name),
        src_image = ":{name}-post_transition".format(name = name),
        ...,
    )

Both images (`-amd64` and `-arm64`) build correctly, but the resulting
image name, according to Docker, happens to be
`bazel/{target}:{name}-post_transition`. So the internal implementation
details of the transitions leak to the resulting images.

This patch makes it possible to rename the post-transition image name to
something we like more, e.g. the architecture name, or remove the suffix
altogether.
  • Loading branch information
motiejus committed Jan 7, 2023
1 parent 48ad6d6 commit 7d34678
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 5 deletions.
16 changes: 12 additions & 4 deletions container/image.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ def _impl(
workdir = None,
user = None,
null_cmd = None,
null_entrypoint = None):
null_entrypoint = None,
tag_name = None):
"""Implementation for the container_image rule.
You can write a customized container_image rule by writing something like:
Expand Down Expand Up @@ -346,6 +347,7 @@ def _impl(
user: str, overrides ctx.attr.user
null_cmd: bool, overrides ctx.attr.null_cmd
null_entrypoint: bool, overrides ctx.attr.null_entrypoint
tag_name: str, overrides ctx.attr.tag_name
"""
name = name or ctx.label.name
base = base or ctx.attr.base
Expand All @@ -367,6 +369,7 @@ def _impl(
build_script = ctx.outputs.build_script
null_cmd = null_cmd or ctx.attr.null_cmd
null_entrypoint = null_entrypoint or ctx.attr.null_entrypoint
tag_name = tag_name or ctx.attr.tag_name

# If this target specifies docker_run_flags, they are always used.
# Fall back to the base image's run flags if present, otherwise use the default value.
Expand Down Expand Up @@ -459,8 +462,10 @@ def _impl(
null_cmd = null_cmd,
)

# Construct a temporary name based on the build target.
tag_name = "{}:{}".format(_repository_name(ctx), name)
# Construct a temporary name based on the build target. This is the name
# of the docker container.
final_tag = tag_name if tag_name else name
container_name = "{}:{}".format(_repository_name(ctx), final_tag)

# These are the constituent parts of the Container image, which each
# rule in the chain must preserve.
Expand Down Expand Up @@ -497,7 +502,7 @@ def _impl(
# We support incrementally loading or assembling this single image
# with a temporary name given by its build rule.
images = {
tag_name: container_parts,
container_name: container_parts,
}

_incr_load(
Expand Down Expand Up @@ -744,6 +749,9 @@ _attrs = dicts.add(_layer.attrs, {
This field supports stamp variables.""",
),
"tag_name": attr.string(
doc = """Override final tag name. If unspecified, is set to name.""",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
Expand Down
3 changes: 2 additions & 1 deletion docs/container.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ image.implementation(<a href="#image.implementation-ctx">ctx</a>, <a href="#imag
<a href="#image.implementation-compression_options">compression_options</a>, <a href="#image.implementation-experimental_tarball_format">experimental_tarball_format</a>, <a href="#image.implementation-debs">debs</a>, <a href="#image.implementation-tars">tars</a>, <a href="#image.implementation-architecture">architecture</a>,
<a href="#image.implementation-operating_system">operating_system</a>, <a href="#image.implementation-os_version">os_version</a>, <a href="#image.implementation-output_executable">output_executable</a>, <a href="#image.implementation-output_tarball">output_tarball</a>, <a href="#image.implementation-output_config">output_config</a>,
<a href="#image.implementation-output_config_digest">output_config_digest</a>, <a href="#image.implementation-output_digest">output_digest</a>, <a href="#image.implementation-output_layer">output_layer</a>, <a href="#image.implementation-workdir">workdir</a>, <a href="#image.implementation-user">user</a>, <a href="#image.implementation-null_cmd">null_cmd</a>,
<a href="#image.implementation-null_entrypoint">null_entrypoint</a>)
<a href="#image.implementation-null_entrypoint">null_entrypoint</a>, <a href="#image.implementation-tag_name">tag_name</a>)
</pre>

Implementation for the container_image rule.
Expand Down Expand Up @@ -469,5 +469,6 @@ You can write a customized container_image rule by writing something like:
| <a id="image.implementation-user"></a>user | str, overrides ctx.attr.user | <code>None</code> |
| <a id="image.implementation-null_cmd"></a>null_cmd | bool, overrides ctx.attr.null_cmd | <code>None</code> |
| <a id="image.implementation-null_entrypoint"></a>null_entrypoint | bool, overrides ctx.attr.null_entrypoint | <code>None</code> |
| <a id="image.implementation-tag_name"></a>tag_name | str, overrides ctx.attr.tag_name | <code>None</code> |


6 changes: 6 additions & 0 deletions testdata/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ container_image(
repository = "gcr.io/dummy",
)

container_image(
name = "tag_name",
files = ["foo"],
tag_name = "this-tag-instead",
)

container_image(
name = "no_data_path_image",
files = ["//testdata/test:test-data"],
Expand Down
1 change: 1 addition & 0 deletions tests/container/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,7 @@ TEST_TARGETS = [
":absolute_data_path_image",
":root_data_path_image",
":dummy_repository",
":tag_name",
# TODO(mattmoor): Re-enable once archive is visible
# "extras_with_deb",
":bundle_test",
Expand Down
7 changes: 7 additions & 0 deletions tests/container/image_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ def test_dummy_repository(self):
self.assertEqual(1, len(img.fs_layers()))
self.assertTopLayerContains(img, ['.', './foo'])

def test_tag_name(self):
# users may override the tag that comes after ':'
name = 'bazel/%s:this-tag-instead' % TEST_DATA_TARGET_BASE
with TestBundleImage('tag_name', name) as img:
self.assertEqual(1, len(img.fs_layers()))
self.assertTopLayerContains(img, ['.', './foo'])

def test_with_double_env(self):
with TestImage('with_double_env') as img:
self.assertEqual(3, len(img.fs_layers()))
Expand Down

0 comments on commit 7d34678

Please sign in to comment.