diff options
author | 2015-10-06 21:41:25 +0000 | |
---|---|---|
committer | 2015-10-07 07:11:55 +0000 | |
commit | 3cd6c64d75ed9135db9b6cd96e03321359d9c5a9 (patch) | |
tree | 1cefed78647f32e31e97579bcd0d08d013cb3628 /tools | |
parent | 15843b74fcc86b91263c7fd863fb62dea618dfac (diff) |
Rollback of commit fb8ee791d3b39f294bf4e083b972aee2ac6f8e27.
*** Reason for rollback ***
Broke internal builds
--
MOS_MIGRATED_REVID=104801084
Diffstat (limited to 'tools')
-rw-r--r-- | tools/build_defs/docker/BUILD | 30 | ||||
-rw-r--r-- | tools/build_defs/docker/README.md | 57 | ||||
-rw-r--r-- | tools/build_defs/docker/docker.bzl | 97 | ||||
-rw-r--r-- | tools/build_defs/docker/incremental_load.sh.tpl | 49 | ||||
-rw-r--r-- | tools/build_defs/docker/join_layers.py | 102 |
5 files changed, 30 insertions, 305 deletions
diff --git a/tools/build_defs/docker/BUILD b/tools/build_defs/docker/BUILD index ca1aad1151..91ea88cfe2 100644 --- a/tools/build_defs/docker/BUILD +++ b/tools/build_defs/docker/BUILD @@ -26,17 +26,17 @@ TEST_TARGETS = [ ] TEST_DATA = [ - "//tools/build_defs/docker/testdata:%s.tar" % t + "//tools/build_defs/docker/testdata:" + t for t in TEST_TARGETS ] + [ - "//tools/build_defs/docker/testdata:notop_%s.tar" % t + "//tools/build_defs/docker/testdata:notop_" + t for t in TEST_TARGETS ] + [ - "//tools/build_defs/docker/testdata:gen_image.tar", - "//tools/build_defs/docker/testdata:data_path_image.tar", - "//tools/build_defs/docker/testdata:no_data_path_image.tar", - "//tools/build_defs/docker/testdata:dummy_repository.tar", - "//tools/build_defs/docker/testdata:extras_with_deb.tar", + "//tools/build_defs/docker/testdata:gen_image", + "//tools/build_defs/docker/testdata:data_path_image", + "//tools/build_defs/docker/testdata:no_data_path_image", + "//tools/build_defs/docker/testdata:dummy_repository", + "//tools/build_defs/docker/testdata:extras_with_deb", ] sh_test( @@ -108,19 +108,3 @@ py_binary( "//third_party/py/gflags", ], ) - -py_binary( - name = "join_layers", - srcs = ["join_layers.py"], - visibility = ["//visibility:public"], - deps = [ - ":archive", - "//third_party/py/gflags", - ], -) - -filegroup( - name = "incremental_load_template", - srcs = ["incremental_load.sh.tpl"], - visibility = ["//visibility:public"], -) diff --git a/tools/build_defs/docker/README.md b/tools/build_defs/docker/README.md index 7734b92d1a..8a13076a15 100644 --- a/tools/build_defs/docker/README.md +++ b/tools/build_defs/docker/README.md @@ -98,12 +98,11 @@ docker_build( ) ``` -You can build this with `bazel build my/image:helloworld.tar`. +You can build this with `bazel build my/image:helloworld`. This will produce the file `bazel-genfiles/my/image/helloworld.tar`. You can load this into my local Docker client by running `docker load -i bazel-genfiles/my/image/helloworld.tar`, or simply -`bazel run my/image:helloworld` (this last command only update the -changed layers and thus is faster). +`bazel run my/image:helloworld`. Upon success you should be able to run `docker images` and see: @@ -117,12 +116,6 @@ You can now use this docker image with the name `bazel/my_image:helloworld` or tag it with another name, for example: `docker tag bazel/my_image:helloworld gcr.io/my-project/my-awesome-image:v0.9` -You can do all that at once with specifying the tag on the command line of -`bazel run`: -``` -bazel run my/image:helloworld gcr.io/my-project/my-awesome-image:v0.9 -``` - __Nota Bene:__ the `docker images` command will show a really old timestamp because `docker_build` remove all timestamps from the build to make it reproducible. @@ -193,52 +186,6 @@ debs, symlinks, entrypoint, cmd, env, ports, volumes, workdir, repository)` <table> <thead> <tr> - <th colspan="2">Implicit output targets</th> - </tr> - </thead> - <tbody> - <tr> - <td><code><i>name</i>.tar</code></td> - <td> - <code>The full Docker image</code> - <p> - A full Docker image containing all the layers, identical to - what <code>docker save</code> would return. This is - only generated on demand. - </p> - </td> - </tr> - <tr> - <td><code><i>name</i>-layer.tar</code></td> - <td> - <code>An image of the current layer</code> - <p> - A Docker image containing only the layer corresponding to - that target. It is used for incremental loading of the layer. - </p> - <p> - <b>Note:</b> this target is not suitable for direct comsumption. - It is used for incremental loading and non-docker rules should - depends on the docker image (<i>name</i>.tar) instead. - </p> - </td> - </tr> - <tr> - <td><code><i>name</i></code></td> - <td> - <code>Incremental image loader</code> - <p> - The incremental image loader. It will load only changed - layers inside the Docker registry. - </p> - </td> - </tr> - </tbody> -</table> - -<table> - <thead> - <tr> <th>Attribute</th> <th>Description</th> </tr> diff --git a/tools/build_defs/docker/docker.bzl b/tools/build_defs/docker/docker.bzl index 0cfe8f77b5..67e17e0761 100644 --- a/tools/build_defs/docker/docker.bzl +++ b/tools/build_defs/docker/docker.bzl @@ -123,9 +123,8 @@ def _sha256(ctx, artifact): def _get_base_artifact(ctx): if ctx.files.base: - if hasattr(ctx.attr.base, "docker_layers"): - # The base is the first layer in docker_layers if provided. - return ctx.attr.base.docker_layers[0]["layer"] + if hasattr(ctx.attr.base, "docker_image"): + return ctx.attr.base.docker_image if len(ctx.files.base) != 1: fail("base attribute should be a single tar file.") return ctx.files.base[0] @@ -193,89 +192,45 @@ def _create_image(ctx, layer, name, metadata): """Create the new image.""" create_image = ctx.executable._create_image args = [ - "--output=" + ctx.outputs.layer.path, + "--output=" + ctx.outputs.out.path, "--metadata=" + metadata.path, "--layer=" + layer.path, "--id=@" + name.path, + # We label at push time, so we only put a single name in this file: + # repository/package:target => {the layer being appended} + "--repository=%s/%s" % (ctx.attr.repository, + ctx.label.package.replace("/", "_")), + "--name=" + ctx.label.name ] inputs = [layer, metadata, name] # If we have been provided a base image, add it. - if ctx.attr.base and not hasattr(ctx.attr.base, "docker_layers"): - base = _get_base_artifact(ctx) - if base: - args += ["--base=%s" % base.path] - inputs += [base] + base = _get_base_artifact(ctx) + if base: + args += ["--base=%s" % base.path] + inputs += [base] ctx.action( executable = create_image, arguments = args, inputs = inputs, - outputs = [ctx.outputs.layer], - mnemonic = "CreateLayer", + use_default_shell_env = True, + outputs = [ctx.outputs.out] ) -def _assemble_image(ctx, layers, name): - """Create the full image from the list of layers.""" - layers = [l["layer"] for l in layers] - args = [ - "--output=" + ctx.outputs.out.path, - "--id=@" + name.path, - "--repository=" + _repository_name(ctx), - "--name=" + ctx.label.name - ] + ["--layer=" + l.path for l in layers] - inputs = [name] + layers - ctx.action( - executable = ctx.executable._join_layers, - arguments = args, - inputs = inputs, - outputs = [ctx.outputs.out], - mnemonic = "JoinLayers" - ) - -def _repository_name(ctx): - """Compute the repository name for the current rule.""" - return "%s/%s" % (ctx.attr.repository, ctx.label.package.replace("/", "_")) - -def reverse(lst): - result = [] - for el in lst: - result = [el] + result - return result - def _docker_build_impl(ctx): """Implementation for the docker_build rule.""" layer = _build_layer(ctx) name = _compute_layer_name(ctx, layer) metadata = _metadata(ctx, layer, name) _create_image(ctx, layer, name, metadata) - # Compute the layers transitive provider. - # It includes the current layers, and, if they exists the layer from - # base docker_build rules. We do not extract the list of layer in - # a base tarball as they probably do not respect the convention on - # layer naming that our rules use. - layers = [ - {"layer": ctx.outputs.layer, "name": name} - ] + getattr(ctx.attr.base, "docker_layers", []) - # Generate the incremental load statement - ctx.template_action( - template = ctx.file._incremental_load_template, - substitutions = { - "%{load_statements}": "\n".join([ - "incr_load '%s' '%s'" % (l["name"].short_path, - l["layer"].short_path) - # The last layer is the first in the list of layers. - # We reverse to load the layer from the parent to the child. - for l in reverse(layers)]), - "%{repository}": _repository_name(ctx), - "%{tag}" : ctx.label.name, - }, + ctx.file_action( + content = "\n".join([ + "#!/bin/bash -eu", + "docker load -i " + ctx.outputs.out.short_path + ]), output = ctx.outputs.executable, executable = True) - _assemble_image(ctx, layers, name) - runfiles = ctx.runfiles( - files = [l["layer"] for l in layers] + [l["name"] for l in layers]) - return struct(runfiles = runfiles, - files = set([ctx.outputs.layer]), - docker_layers = layers) + return struct(runfiles = ctx.runfiles(files = [ctx.outputs.out]), + docker_image = ctx.outputs.out) docker_build_ = rule( implementation = _docker_build_impl, @@ -306,15 +261,6 @@ docker_build_ = rule( cfg=HOST_CFG, executable=True, allow_files=True), - "_incremental_load_template": attr.label( - default=Label("//tools/build_defs/docker:incremental_load_template"), - single_file=True, - allow_files=True), - "_join_layers": attr.label( - default=Label("//tools/build_defs/docker:join_layers"), - cfg=HOST_CFG, - executable=True, - allow_files=True), "_rewrite_tool": attr.label( default=Label("//tools/build_defs/docker:rewrite_json"), cfg=HOST_CFG, @@ -328,7 +274,6 @@ docker_build_ = rule( }, outputs = { "out": "%{name}.tar", - "layer": "%{name}-layer.tar", }, executable = True) diff --git a/tools/build_defs/docker/incremental_load.sh.tpl b/tools/build_defs/docker/incremental_load.sh.tpl deleted file mode 100644 index 7217fccd77..0000000000 --- a/tools/build_defs/docker/incremental_load.sh.tpl +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -eu -# -# Copyright 2015 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. - -# This is a generated files that load all docker layer built by "docker_build". - -RUNFILES=${BASH_SOURCE[0]}.runfiles - -# List all images identifier (only the identifier) from the local -# docker registry. -IMAGES="$(docker images -aq)" -IMAGE_LEN=$(for i in $IMAGES; do echo -n $i | wc -c; done | sort -g | head -1 | xargs) - -[ -n "$IMAGE_LEN" ] || IMAGE_LEN=64 - -function incr_load() { - # Load a layer if and only if the layer is not in "$IMAGES", that is - # in the local docker registry. - name=$(cat ${RUNFILES}/$1) - if (echo "$IMAGES" | grep -q ^${name:0:$IMAGE_LEN}$); then - echo "Skipping $name, already loaded." - else - echo "Loading $name..." - docker load -i ${RUNFILES}/$2 - fi -} - -# List of 'incr_load' statements for all layers. -# This generated and injected by docker_build. -%{load_statements} - -# Tag the last layer. -if [ -n "${name}" ]; then - TAG="${1:-%{repository}:%{tag}}" - echo "Tagging ${name} as ${TAG}" - docker tag -f ${name} ${TAG} -fi diff --git a/tools/build_defs/docker/join_layers.py b/tools/build_defs/docker/join_layers.py deleted file mode 100644 index 361a6a6667..0000000000 --- a/tools/build_defs/docker/join_layers.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2015 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. -"""This tool creates a docker image from a list of layers.""" -# This is the main program to create a docker image. It expect to be run with: -# join_layers --output=output_file \ -# --layer=layer1 [--layer=layer2 ... --layer=layerN] \ -# --id=@identifier \ -# --name=myname --repository=repositoryName -# See the gflags declaration about the flags argument details. - -import os.path -import sys - -from tools.build_defs.docker import archive -from third_party.py import gflags - -gflags.DEFINE_string('output', None, 'The output file, mandatory') -gflags.MarkFlagAsRequired('output') - -gflags.DEFINE_multistring('layer', [], 'The tar files for layers to join.') - -gflags.DEFINE_string( - 'id', None, 'The hex identifier of the top layer (hexstring or @filename).') - -gflags.DEFINE_string( - 'repository', None, - 'The name of the repository to add this image (use with --id and --name).') - -gflags.DEFINE_string( - 'name', None, - 'The symbolic name of this image (use with --id and --repsoitory).') - -FLAGS = gflags.FLAGS - - -def _layer_filter(name): - """Ignore files 'top' and 'repositories' when merging layers.""" - basename = os.path.basename(name) - return basename not in ('top', 'repositories') - - -def create_image(output, layers, identifier=None, - name=None, repository=None): - """Creates a Docker image from a list of layers. - - Args: - output: the name of the docker image file to create. - layers: the layers (tar files) to join to the image. - identifier: the identifier of the top layer for this image. - name: symbolic name for this docker image. - repository: repository name for this docker image. - """ - tar = archive.TarFileWriter(output) - for layer in layers: - tar.add_tar(layer, name_filter=_layer_filter) - # In addition to N layers of the form described above, there might be - # a single file at the top of the image called repositories. - # This file contains a JSON blob of the form: - # { - # 'repo':{ - # 'tag-name': 'top-most layer hex', - # ... - # }, - # ... - # } - if identifier: - # If the identifier is not provided, then the resulted layer will be - # created without a 'top' file. Docker doesn't needs that file nor - # the repository to load the image and for intermediate layer, - # docker_build store the name of the layer in a separate artifact so - # this 'top' file is not needed. - tar.add_file('top', content=identifier) - if repository and name: - tar.add_file('repositories', - content='\n'.join([ - '{', ' "%s": {' % repository, ' "%s": "%s"' % ( - name, identifier), ' }', '}' - ])) - - -def main(unused_argv): - identifier = FLAGS.id - if identifier and identifier.startswith('@'): - with open(identifier[1:], 'r') as f: - identifier = f.read() - create_image(FLAGS.output, FLAGS.layer, identifier, FLAGS.name, - FLAGS.repository) - - -if __name__ == '__main__': - main(FLAGS(sys.argv)) |