From e5f970906594d9097bb7c3736b2de1750cc8655f Mon Sep 17 00:00:00 2001 From: Damien Martin-Guillerez Date: Wed, 19 Jul 2017 14:59:44 +0200 Subject: Refactor docker tests to be buildable without docker. This make this build a bit non-deterministic since the way it will be built depend on wether docker is installed or not. We now use the docker_pull from bazelbuild/continuous-integration to generate the base docker images and generate a fake docker binary that just error out when docker is not found so test will fails. Note that the docker_pull is set to timeout after an hour and can be extremely slow so we also set it to non quiet. Fixes #3278. Change-Id: I98d5b436e424f53981e113c1a4fd1346a5564df7 PiperOrigin-RevId: 162476033 --- WORKSPACE | 3 +- src/test/docker/BUILD | 41 +----------------- src/test/docker/docker_pull.bzl | 80 +++++++++++++++++++++++++++++++++++ src/test/docker/docker_repository.bzl | 9 +++- src/test/docker/flavours.bzl | 37 ++++++++++++++++ 5 files changed, 129 insertions(+), 41 deletions(-) create mode 100644 src/test/docker/docker_pull.bzl create mode 100644 src/test/docker/flavours.bzl diff --git a/WORKSPACE b/WORKSPACE index 08fd58595b..a86ba4e6b4 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -35,8 +35,9 @@ bind( # For src/test/docker/... load("//src/test/docker:docker_repository.bzl", "docker_repository") - docker_repository() +load("//src/test/docker:flavours.bzl", "pull_images_for_docker_tests") +pull_images_for_docker_tests() # To run the Android integration tests in //src/test/shell/bazel/android:all or # build the Android sample app in //examples/android/java/bazel:hello_world diff --git a/src/test/docker/BUILD b/src/test/docker/BUILD index 7393126af3..e489a6b019 100644 --- a/src/test/docker/BUILD +++ b/src/test/docker/BUILD @@ -1,43 +1,6 @@ load("//tools/build_defs/docker:docker.bzl", "docker_build") load("//tools/build_defs/pkg:pkg.bzl", "pkg_tar") - -# This is totally non hermetic, we should really replace that by a -# docker_pull rule. -FLAVOURS = [f[f.find(".") + 1:] for f in glob(["Dockerfile.*"])] - -[ - # This is totally non hermetic. - genrule( - name = "docker-" + flavour, - srcs = ["Dockerfile." + flavour], - outs = ["docker-%s.tar" % flavour], - cmd = "\n".join([ - "DIR=\"$$(dirname $<)\"", - "IMG=\"$$(basename $<)\"", - "DOCKER=\"$${PWD}/$(location @docker//:docker)\"", - "(", - " cd $$DIR", - " $$DOCKER build -f $$IMG -t bazel_tools_cpp_test:%s ." % flavour, - ")", - "$$DOCKER save bazel_tools_cpp_test:%s > $@" % flavour, - ]), - tags = ["local"], - # Docker needs to knows how to contact the daemon from the environment. - # @docker//:docker point to a docker wrapper that copy the environment - # of the user. - tools = ["@docker//:docker"], - ) - for flavour in FLAVOURS -] - -# Just to avoid re-reading docker images all the time -[ - docker_build( - name = "base-" + flavour, - base = "docker-" + flavour, - ) - for flavour in FLAVOURS -] +load("//src/test/docker:flavours.bzl", "FLAVOURS") pkg_tar( name = "bazel_cc_configure", @@ -49,7 +12,7 @@ pkg_tar( [ [docker_build( name = "bazel_cc_configure-%s-%s" % (flavour, mode), - base = ":base-" + flavour, + base = "@docker-%s//:image" % flavour, entrypoint = "/opt/workspace/compile.sh && ./output/bazel test ${EXTRA_BAZEL_ARGS} //examples/cpp:hello-success_test", env = { "EXTRA_BAZEL_ARGS": "--spawn_strategy=standalone --genrule_strategy=standalone -c %s" % mode, diff --git a/src/test/docker/docker_pull.bzl b/src/test/docker/docker_pull.bzl new file mode 100644 index 0000000000..8fab57fe88 --- /dev/null +++ b/src/test/docker/docker_pull.bzl @@ -0,0 +1,80 @@ +# Copyright 2016 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. + +"""Quick and not really nice docker_pull rules based on the docker daemon.""" + +def _impl(repository_ctx): + docker = repository_ctx.which("docker") + if docker == None and repository_ctx.attr.optional: + repository_ctx.file("BUILD", """ +load("@bazel_tools//tools/build_defs/docker:docker.bzl", "docker_build") + +# an empty image to still allow building despite not having the base +# image. +docker_build( + name = "image", + visibility = ['//visibility:public'], +) +""") + repository_ctx.file("image.tar") + return + + repository_ctx.file("BUILD", """ +load("@bazel_tools//tools/build_defs/docker:docker.bzl", "docker_build") + +docker_build( + name = "image", + base = ":base.tar", + visibility = ["//visibility:public"], +) +""") + tag = repository_ctx.attr.tag + cmd = "pull" + if repository_ctx.attr.dockerfile: + dockerfile = repository_ctx.path(repository_ctx.attr.dockerfile) + cmd = "build" + print("Running `docker build`") + result = repository_ctx.execute([ + docker, + "build", + "-q", + "-t", + tag, + "-f", + dockerfile, + dockerfile.dirname, + ], quiet=False, timeout=3600) + else: + print("Running `docker pull`") + result = repository_ctx.execute([docker, "pull", tag], quiet=False, timeout=3600) + if result.return_code: + fail("docker %s failed with error code %s:\n%s" % ( + cmd, + result.return_code, + result.stderr)) + result = repository_ctx.execute([ + docker, "save", "-o", repository_ctx.path("base.tar"), tag]) + if result.return_code: + fail("docker save failed with error code %s:\n%s" % ( + result.return_code, + result.stderr)) + +docker_pull = repository_rule( + implementation = _impl, + attrs = { + "tag": attr.string(mandatory=True), + "dockerfile": attr.label(default=None), + "optional": attr.bool(default=False), + }, +) diff --git a/src/test/docker/docker_repository.bzl b/src/test/docker/docker_repository.bzl index 4f96170176..1b49d1a9ed 100644 --- a/src/test/docker/docker_repository.bzl +++ b/src/test/docker/docker_repository.bzl @@ -20,11 +20,17 @@ def _impl(ctx): # on it, silently ignoring. ctx.file("BUILD", "\n".join([ - "filegroup(", + "sh_binary(", " name = 'docker',", + " srcs = ['docker.sh'],", " visibility = ['//visibility:public'],", ")" ])) + ctx.file("docker.sh", "\n".join([ + "#!/bin/bash", + "echo 'ERROR: docker is not installed' >&2", + "exit 1" + ])) else: exports = [] for k in ctx.os.environ: @@ -55,3 +61,4 @@ docker_repository_ = repository_rule(_impl) def docker_repository(): """Declare a @docker repository that provide a docker binary.""" docker_repository_(name = "docker") + diff --git a/src/test/docker/flavours.bzl b/src/test/docker/flavours.bzl new file mode 100644 index 0000000000..713c7c5243 --- /dev/null +++ b/src/test/docker/flavours.bzl @@ -0,0 +1,37 @@ +# 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. +"""Create base images for docker tests.""" +# TODO(dmarting): Right now we use a custom docker_pull that can build +# docker images, which is not reproducible and as a high cost, ideally +# we would switch to the docker_pull from bazelbuild/rules_docker but +# we do not have an easy mean to create and maintain the images we need +# for those tests. +load("//src/test/docker:docker_pull.bzl", "docker_pull") + +FLAVOURS = [ + "centos6.7", + "debian-stretch", + "fedora23", + "ubuntu-15.04", + "ubuntu-16.04", +] + +def pull_images_for_docker_tests(): + for flavour in FLAVOURS: + docker_pull( + name = "docker-" + flavour, + tag = "bazel_tools_cpp_test:" + flavour, + dockerfile = "//src/test/docker:Dockerfile." + flavour, + optional = True, + ) -- cgit v1.2.3