Support using container tag in rbe_autoconfig(). (#298)
* Support using container tag in rbe_autoconfig().
* Add a rbe_autoconfig target for RBE Ubuntu1604 container testing.
diff --git a/WORKSPACE b/WORKSPACE
index 225f6e9..513f28e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -101,7 +101,7 @@
sha256 = "5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9",
)
-load("//rules:rbe_repo.bzl", "rbe_autoconfig")
+load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
rbe_autoconfig(name = "rbe_default")
@@ -130,3 +130,12 @@
),
output_base = "configs/ubuntu16_04_clang/1.1",
)
+
+# Use in the RBE Ubuntu1604 container release.
+rbe_autoconfig(
+ name = "rbe_ubuntu1604_test",
+ env = clang_env(),
+ registry = "gcr.io",
+ repository = "asci-toolchain/test-rbe-ubuntu16_04",
+ tag = "latest",
+)
diff --git a/configs/ubuntu16_04_clang/versions.bzl b/configs/ubuntu16_04_clang/versions.bzl
index 0dbf8b8..2307032 100644
--- a/configs/ubuntu16_04_clang/versions.bzl
+++ b/configs/ubuntu16_04_clang/versions.bzl
@@ -12,9 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License
-# Returns a dict with major container versions mapped to supported bazel versions.
-def config_to_bazel_versions():
+# Returns a dict with suppported Bazel versions mapped to the config version to use.
+def bazel_to_config_versions():
return {
- "1.0": ["0.13.0", "0.14.1", "0.15.0", "0.16.1"],
- "1.1": ["0.16.1", "0.17.1", "0.18.0", "0.19.0", "0.19.2", "0.20.0", "0.21.0"],
+ "0.13.0": "1.0",
+ "0.14.1": "1.0",
+ "0.15.0": "1.0",
+ "0.16.1": "1.1",
+ "0.17.1": "1.1",
+ "0.18.0": "1.1",
+ "0.19.0": "1.1",
+ "0.19.2": "1.1",
+ "0.20.0": "1.1",
+ "0.21.0": "1.1",
+ "0.22.0": "1.1",
}
diff --git a/rules/get_java_home.sh.tpl b/rules/get_java_home.sh.tpl
index 7cd2593..5f4857c 100644
--- a/rules/get_java_home.sh.tpl
+++ b/rules/get_java_home.sh.tpl
@@ -20,4 +20,3 @@
# var in a docker image.
echo $(docker inspect -f '{{range $i, $v := .Config.Env}}{{println $v}}{{end}}' %{image_name} | grep JAVA_HOME | cut -d'=' -f2)
-
diff --git a/rules/rbe_repo.bzl b/rules/rbe_repo.bzl
index 2ea33f2..71caa74 100644
--- a/rules/rbe_repo.bzl
+++ b/rules/rbe_repo.bzl
@@ -78,7 +78,7 @@
name = "rbe_my_custom_container",
registry = "gcr.io",
repository = "my-project/my-base",
- # tag is not supported, always use a digest
+ # Digest is recommended for any use case other than testing.
digest = "sha256:deadbeef",
)
@@ -144,8 +144,8 @@
The {bazel_version} above corresponds to the version of bazel installed locally.
Note you can override this version and pass an optional rc # if desired.
Running this rule with a non release version (e.g., built from source) will result in
-picking as bazel version <bazel_version_fallback> defined in the attrs of this rule.
-Note the bazel_version / bazel_rc must be published in https://releases.bazel.build/...
+picking as bazel version _BAZEL_VERSION_FALLBACK. Note the bazel_version / bazel_rc_version
+must be published in https://releases.bazel.build/...
Note this is a very not hermetic repository rule that can actually change the
contents of your project sources. While this is generally not recommended by
@@ -168,7 +168,7 @@
load(
"//configs/ubuntu16_04_clang:versions.bzl",
- "config_to_bazel_versions",
+ "bazel_to_config_versions",
)
load("//rules:environments.bzl", "clang_env")
load(
@@ -183,6 +183,9 @@
"parse_rc",
)
+# Version to fallback to if not provided explicitly and local is non-release version.
+_BAZEL_VERSION_FALLBACK = "0.22.0"
+
# External folder is set to be deprecated, lets keep it here for easy
# refactoring
# https://github.com/bazelbuild/bazel/issues/1262
@@ -214,23 +217,11 @@
def _impl(ctx):
"""Core implementation of _rbe_autoconfig repository rule."""
- # Resolve the Bazel version to use
- bazel_version = None
- bazel_rc_version = None
- if ctx.attr.bazel_version == "local":
- bazel_version = str(extract_version_number(ctx.attr.bazel_version_fallback))
- rc = parse_rc(native.bazel_version)
- bazel_rc_version = rc if rc != -1 else None
- if ctx.attr.bazel_version != "local":
- bazel_version = ctx.attr.bazel_version
- bazel_rc_version = ctx.attr.bazel_rc_version
-
# Deal with the simple case first: if user picks rbe-ubuntu 16_04 container and
# a config exists for the current version of Bazel, just create aliases
- if ctx.attr.use_checked_in_confs:
- if _use_standard_config(ctx, bazel_version, bazel_rc_version, ctx.attr.revision):
- # If a standard config was found we are done and can just return.
- return
+ if ctx.attr.config_version:
+ _use_standard_config(ctx, ctx.attr.bazel_version, ctx.attr.config_version)
+ return
# Perform some safety checks
_validate_host(ctx)
@@ -256,9 +247,22 @@
outputs_tar = ctx.attr.name + "_out.tar"
# Pull the image using 'docker pull'
- image_name = ctx.attr.registry + "/" + ctx.attr.repository + "@" + ctx.attr.digest
+ image_name = None
+ if ctx.attr.digest:
+ image_name = ctx.attr.registry + "/" + ctx.attr.repository + "@" + ctx.attr.digest
+ else:
+ image_name = ctx.attr.registry + "/" + ctx.attr.repository + ":" + ctx.attr.tag
_pull_image(ctx, image_name)
+ # If tag is specified instead of digest, resolve it to digest in the
+ # image_name as it will be used later on in the platform targets.
+ if ctx.attr.tag:
+ result = ctx.execute(["docker", "inspect", "--format={{index .RepoDigests 0}}", image_name])
+ _print_exec_results("Resolve image digest", result, fail_on_error = True)
+ image_name = result.stdout.splitlines()[0]
+ print("Image with given tag `%s` is resolved to %s" %
+ (ctx.attr.tag, image_name))
+
# Get the value of JAVA_HOME to set in the produced
# java_runtime
java_home = _get_java_home(ctx, image_name)
@@ -266,8 +270,8 @@
# run the container and extract the autoconf directory
_run_and_extract(
ctx,
- bazel_version = bazel_version,
- bazel_rc_version = bazel_rc_version,
+ bazel_version = ctx.attr.bazel_version,
+ bazel_rc_version = ctx.attr.bazel_rc_version,
image_name = image_name,
outputs_tar = outputs_tar,
project_root = project_root,
@@ -278,7 +282,7 @@
# will work with RBE with the produced toolchain
_create_platform(
ctx,
- bazel_version = bazel_version,
+ bazel_version = ctx.attr.bazel_version,
image_name = image_name,
java_home = java_home,
name = name,
@@ -287,7 +291,7 @@
# Expand outputs to project dir if user requested it
_expand_outputs(
ctx,
- bazel_version = bazel_version,
+ bazel_version = ctx.attr.bazel_version,
project_root = project_root,
)
@@ -315,26 +319,11 @@
if not ctx.which("tar"):
fail("Cannot run rbe_autoconfig as 'tar' was not found on the path.")
-# Checks if a standard published config can be used for the given revision
-# of the rbe ubuntu 16_04 container. If so, produces BUILD files with aliases
-# for all the required toolchain / platform targets. Otherwise returns false.
-def _use_standard_config(ctx, bazel_version, bazel_rc_version, revision):
- # If rc version is required, simply return
- if bazel_rc_version:
- return False
+# Produces BUILD files with aliases for all the required toolchain / platform targets.
+def _use_standard_config(ctx, bazel_version, config_version):
+ print("Using checked-in configs.")
- # Verify a toolchain config exists for the given version of Bazel and the
- # given revision of the container
- config_version = public_rbe_ubuntu16_04_config_version().get(revision, None)
- config_found = False
- for b_v in config_to_bazel_versions().get(config_version):
- if b_v == bazel_version:
- config_found = True
- break
- if not config_found:
- return False
-
- # If a config is found, create the BUILD files with the aliases
+ # Create the BUILD files with the aliases
template = ctx.path(Label("@bazel_toolchains//rules:BUILD.std_container.tpl"))
jdk = "@bazel_toolchains//configs/ubuntu16_04_clang/%s:jdk8" % config_version
cc_toolchain = "@bazel_toolchains//configs/ubuntu16_04_clang/%s/bazel_%s/cpp:cc-toolchain-clang-x86_64-default" % (config_version, bazel_version)
@@ -360,11 +349,10 @@
},
False,
)
- return True
# Pulls an image using 'docker pull'.
def _pull_image(ctx, image_name):
- print("Pulling image.")
+ print("Pulling image %s." % image_name)
result = ctx.execute(["docker", "pull", image_name])
_print_exec_results("pull image", result, fail_on_error = True)
print("Image pulled.")
@@ -504,7 +492,10 @@
# If we use the default project, we need to modify the WORKSPACE
# and BUILD files, so don't mount read-only
mount_read_only_flag = ""
- target = project_root + ":" + _REPO_DIR + mount_read_only_flag
+
+ # If the rule is invoked from bazel-toolchains itself, then project_root
+ # is a symlink, which can cause mounting issues on GCB.
+ target = "$(realpath " + project_root + "):" + _REPO_DIR + mount_read_only_flag
docker_run_flags += ["-v", target]
docker_run_flags += ["-v", str(ctx.path("container")) + ":/container"]
@@ -603,29 +594,29 @@
_rbe_autoconfig = repository_rule(
attrs = {
"bazel_rc_version": attr.string(
- doc = ("Optional. An rc version to use. Note an installer for the rc " +
- "must be available in https://releases.bazel.build."),
+ doc = ("Optional. An rc version to use. Note an installer for " +
+ "the rc must be available in https://releases.bazel.build."),
),
"bazel_version": attr.string(
default = "local",
doc = ("The version of Bazel to use to generate toolchain configs." +
"Use only (major, minor, patch), e.g., '0.20.0'."),
),
- "bazel_version_fallback": attr.string(
- default = "0.22.0",
- doc = ("Version to fallback to if not provided explicitly and local " +
- "is non-release version."),
- ),
"config_dir": attr.string(
- doc = ("Optional. Use only if output_base is defined. If you want to " +
- "create multiple toolchain configs (for the same version of Bazel) " +
- "you can use this attr to indicate a type of config (e.g., default, " +
- "msan). The configs will be generated in a sub-directory when this attr " +
- "is used."),
+ doc = ("Optional. Use only if output_base is defined. If you " +
+ "want to create multiple toolchain configs (for the same " +
+ "version of Bazel) you can use this attr to indicate a " +
+ "type of config (e.g., default, msan). The configs will " +
+ "be generated in a sub-directory when this attr is used."),
+ ),
+ "config_version": attr.string(
+ doc = ("The config version found for the given container and " +
+ "Bazel version. " +
+ "Used internally when use_checked_in_confs is true."),
),
"digest": attr.string(
- mandatory = True,
- doc = ("The digest (sha256 sum) of the image to pull. For example, " +
+ doc = ("Optional. The digest (sha256 sum) of the image to pull. " +
+ "For example, " +
"sha256:f1330b2f02714d3a3e98c5b1f6524fbb9c15154e44a31fb3caecb7a6ad4e8445" +
", note the digest includes 'sha256:'"),
),
@@ -636,7 +627,7 @@
),
"exec_compatible_with": attr.string_list(
default = _RBE_UBUNTU_EXEC_COMPAT_WITH,
- doc = ("The list of constraints that will be added to the " +
+ doc = ("Optional. The list of constraints that will be added to the " +
"toolchain in its exec_compatible_with attribute (and to " +
"the platform in its constraint_values attr). For " +
"example, [\"@bazel_tools//platforms:linux\"]. Default " +
@@ -655,25 +646,25 @@
),
"registry": attr.string(
default = _RBE_UBUNTU_REGISTRY,
- doc = ("The registry to pull the container from. For example, " +
+ doc = ("Optional. The registry to pull the container from. For example, " +
"l.gcr.io or marketplace.gcr.io. The default is the " +
"value for rbe-ubuntu16-04 image."),
),
"repository": attr.string(
default = _RBE_UBUNTU_REPO,
- doc = ("The repository to pull the container from. For example," +
+ doc = ("Optional. The repository to pull the container from. For example," +
" google/ubuntu. The default is the " +
" value for the rbe-ubuntu16-04 image."),
),
- "revision": attr.string(
- doc = ("The revision of the rbe-ubuntu16-04 container."),
- ),
"setup_cmd": attr.string(
default = "cd .",
doc = ("Optional. Pass an additional command that will be executed " +
"(inside the container) before running bazel to generate the " +
"toolchain configs"),
),
+ "tag": attr.string(
+ doc = ("Optional. The tag of the image to pull, e.g. latest."),
+ ),
"target_compatible_with": attr.string_list(
default = _RBE_UBUNTU_TARGET_COMPAT_WITH,
doc = ("The list of constraints that will be added to the " +
@@ -681,11 +672,6 @@
"example, [\"@bazel_tools//platforms:linux\"]. Default " +
" is set to values for rbe-ubuntu16-04 container."),
),
- "use_checked_in_confs": attr.bool(
- default = True,
- doc = ("If set to False the checked-in configs in bazel-toolchains" +
- "repo are ignored and a container is allways pulled."),
- ),
},
environ = [
_RBE_AUTOCONF_ROOT,
@@ -696,14 +682,14 @@
def rbe_autoconfig(
name,
bazel_version = None,
- bazel_rc = None,
+ bazel_rc_version = None,
config_dir = None,
digest = None,
env = None,
exec_compatible_with = None,
java_home = None,
output_base = None,
- revision = None,
+ tag = None,
registry = None,
repository = None,
target_compatible_with = None,
@@ -718,33 +704,39 @@
`Use only (major, minor, patch), e.g., '0.20.0'. Default is "local"
which means the same version of Bazel that is currently running will
be used. If local is a non release version, rbe_autoconfig will fallback
- to using the latest release version (see default for bazel_version_fallback
- in attrs of _rbe_autoconfig for current latest).
- bazel_rc: The rc (for the given version of Bazel) to use. Must be published
- in https://releases.bazel.build
+ to using the latest release version (see _BAZEL_VERSION_FALLBACK).
+ bazel_rc_version: The rc (for the given version of Bazel) to use.
+ Must be published in https://releases.bazel.build. E.g. 2.
+ config_dir: Optional. Subdirectory where configs will be copied to.
+ Use only if output_base is defined.
+ digest: Optional. The digest of the image to pull.
+ Should not be set if tag is used.
+ Must be set together with registry and repository.
exec_compatible_with: Optional. List of constraints to add to the produced
toolchain/platform targets (e.g., ["@bazel_tools//platforms:linux"] in the
exec_compatible_with/constraint_values attrs, respectively.
- digest: Optional. The digest of the image to pull. Should only be set if
- a custom container is required.
- Must be set together with registry and repository.
+ env: dict. Optional. Additional env variables that will be set when
+ running the Bazel command to generate the toolchain configs.
+ Set to values for gcr.io/cloud-marketplace/google/rbe-ubuntu16-04 container.
+ Does not need to be set if your custom container extends
+ the rbe-ubuntu16-04 container.
+ Should be overriden if a custom container does not extend the
+ rbe-ubuntu16-04 container.
java_home: Optional. The location of java_home in the container. For
example , '/usr/lib/jvm/java-8-openjdk-amd64'. If not set, the rule
will attempt to read the JAVA_HOME env var from the container.
If that is not set the rule will fail.
output_base: Optional. The directory (under the project root) where the
produced toolchain configs will be copied to.
- config_dir: Optional. Subdirectory where configs will be copied to.
- Use only if output_base is defined.
+ tag: Optional. The tag of the container to use.
+ Should not be set if digest is used.
+ Must be set together with registry and repository.
registry: Optional. The registry from which to pull the base image.
Should only be set if a custom container is required.
Must be set together with digest and repository.
repository: Optional. he `repository` of images to pull from.
Should only be set if a custom container is required.
Must be set together with registry and digest.
- revision: Optional. A revision of an rbe-ubuntu16-04 container to use.
- Should not be set if repository, registry and digest are used.
- See gcr.io/cloud-marketplace/google/rbe-ubuntu16-04
target_compatible_with: List of constraints to add to the produced
toolchain target (e.g., ["@bazel_tools//platforms:linux"]) in the
target_compatible_with attr.
@@ -752,49 +744,58 @@
before generating them. If set to false the rule will allways attempt
to generate the configs by pulling a toolchain container and running
Bazel inside.
- env: dict. Optional. Additional env variables that will be set when
- running the Bazel command to generate the toolchain configs.
- Set to values for rbe-ubuntu16-04 container.
- Does not need to be set if your custom container extends
- an rbe-ubuntu16-04 container.
- Should be overriden if a custom container does not extend
- rbe-ubuntu16-04.
"""
if not output_base and config_dir:
fail("config_dir can only be used when output_base is set.")
- if revision and (digest or repository or registry):
- fail("'revision' cannot be set if 'digest', 'repository' or " +
- "'registry' are set.")
- if not ((not digest and not repository and not registry) or
- (digest and repository and registry)):
- fail("All of 'digest', 'repository' and 'registry' or none of them " +
- "must be set.")
- if bazel_rc and not bazel_version:
- fail("bazel_rc can only be used with bazel_version.")
- if not digest:
- if not revision or revision == "latest":
- revision = RBE_UBUNTU16_04_LATEST
- digest = public_rbe_ubuntu16_04_sha256s().get(revision, None)
- if not env:
- env = clang_env()
- if not digest:
- fail(("Could not find a valid digest for revision %s, " +
- "please make sure it is declared in " +
- "@bazel_toolchains//rules:toolchain_containers.bzl" % revision))
- # If the user has set a custom env, custom java_home,
- # registry or repository, don't use
- # checked in configs
- if ((env and env != clang_env()) or
- (java_home) or
- (registry and registry != _RBE_UBUNTU_REGISTRY) or
- (repository and repository != _RBE_UBUNTU_REPO)):
- use_checked_in_confs = False
+ if bazel_rc_version and not bazel_version:
+ fail("bazel_rc_version can only be used with bazel_version.")
+
+ # Resolve the Bazel version to use.
+ if not bazel_version or bazel_version == "local":
+ bazel_version = str(extract_version_number(_BAZEL_VERSION_FALLBACK))
+ rc = parse_rc(native.bazel_version)
+ bazel_rc_version = rc if rc != -1 else None
+
+ if tag and digest:
+ fail("'tag' and 'digest' cannot be set at the same time.")
+
+ if not ((not digest and not tag and not repository and not registry) or
+ (digest and repository and registry) or
+ (tag and repository and registry)):
+ fail("All of 'digest', 'repository' and 'registry' or " +
+ "all of 'tag', 'repository' and 'registry' or " +
+ "none of them must be set.")
+
+ # Set to defaults only if all are unset.
+ if not repository and not registry and not tag and not digest:
+ repository = _RBE_UBUNTU_REPO
+ registry = _RBE_UBUNTU_REGISTRY
+ tag = RBE_UBUNTU16_04_LATEST
+
+ if ((registry and registry == _RBE_UBUNTU_REGISTRY) and
+ (repository and repository == _RBE_UBUNTU_REPO) and
+ (not env)):
+ env = clang_env()
+
+ config_version = validateUseOfCheckedInConfigs(
+ registry = registry,
+ repository = repository,
+ tag = tag,
+ digest = digest,
+ use_checked_in_confs = use_checked_in_confs,
+ env = env,
+ java_home = java_home,
+ bazel_version = bazel_version,
+ bazel_rc_version = bazel_rc_version,
+ )
+
_rbe_autoconfig(
name = name,
bazel_version = bazel_version,
- bazel_rc = bazel_rc,
+ bazel_rc_version = bazel_rc_version,
config_dir = config_dir,
+ config_version = config_version,
digest = digest,
env = env,
exec_compatible_with = exec_compatible_with,
@@ -802,7 +803,55 @@
output_base = output_base,
registry = registry,
repository = repository,
- revision = revision,
+ tag = tag,
target_compatible_with = target_compatible_with,
- use_checked_in_confs = use_checked_in_confs,
)
+
+# Check if checked-in configs are available and should be used. If so, return
+# the config version. Otherwise return None.
+def validateUseOfCheckedInConfigs(
+ registry,
+ repository,
+ tag,
+ digest,
+ use_checked_in_confs,
+ env,
+ java_home,
+ bazel_version,
+ bazel_rc_version):
+ if not use_checked_in_confs:
+ return None
+ if registry and registry != _RBE_UBUNTU_REGISTRY:
+ return None
+ if repository and repository != _RBE_UBUNTU_REPO:
+ return None
+ if env and env != clang_env():
+ return None
+ if java_home:
+ return None
+ if bazel_rc_version:
+ return None
+
+ if tag: # Implies `digest` is not specified.
+ if tag == "latest":
+ tag = RBE_UBUNTU16_04_LATEST
+ digest = public_rbe_ubuntu16_04_sha256s().get(tag, None)
+ if not digest: # We didn't find checked-in configs in this repo.
+ return None
+ else: # Implies tag is not specified
+ for pair in public_rbe_ubuntu16_04_sha256s().items():
+ if pair[1] == digest:
+ tag = pair[0]
+ break
+ if not tag:
+ # The given RBE Ubuntu1604 container digest is not one of the
+ # released ones.
+ return None
+
+ # Verify a toolchain config exists for the given version of Bazel and the
+ # given tag of the container
+ config_version = public_rbe_ubuntu16_04_config_version().get(tag, None)
+ if not config_version or config_version != bazel_to_config_versions().get(bazel_version):
+ return None
+
+ return config_version