diff --git a/container/image.bzl b/container/image.bzl index 92e0d579c..1893a3364 100644 --- a/container/image.bzl +++ b/container/image.bzl @@ -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: @@ -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 @@ -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. @@ -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. @@ -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( @@ -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", ), diff --git a/docs/container.md b/docs/container.md index d30aeee58..27acd6491 100644 --- a/docs/container.md +++ b/docs/container.md @@ -404,7 +404,7 @@ image.implementation(ctx, compression_options, experimental_tarball_format, debs, tars, architecture, operating_system, os_version, output_executable, output_tarball, output_config, output_config_digest, output_digest, output_layer, workdir, user, null_cmd, - null_entrypoint) + null_entrypoint, tag_name) Implementation for the container_image rule. @@ -469,5 +469,6 @@ You can write a customized container_image rule by writing something like: | user | str, overrides ctx.attr.user | None | | null_cmd | bool, overrides ctx.attr.null_cmd | None | | null_entrypoint | bool, overrides ctx.attr.null_entrypoint | None | +| tag_name | str, overrides ctx.attr.tag_name | None | diff --git a/testdata/BUILD b/testdata/BUILD index 319f7db1c..aaac2697b 100644 --- a/testdata/BUILD +++ b/testdata/BUILD @@ -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"], diff --git a/tests/container/BUILD b/tests/container/BUILD index 5251d6bbc..afd029d32 100644 --- a/tests/container/BUILD +++ b/tests/container/BUILD @@ -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", diff --git a/tests/container/image_test.py b/tests/container/image_test.py index 2758205bc..a3d9fa658 100644 --- a/tests/container/image_test.py +++ b/tests/container/image_test.py @@ -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()))