Bug 1432390 - Hash the contents of the docker image context as it is created. r?dustin
This will allow us, down the line, to avoid creating a file at all in
some cases.
--- a/taskcluster/taskgraph/util/docker.py
+++ b/taskcluster/taskgraph/util/docker.py
@@ -60,16 +60,31 @@ def generate_context_hash(topsrcdir, ima
fd, p = tempfile.mkstemp()
os.close(fd)
try:
return create_context_tar(topsrcdir, image_path, p, image_name, args)
finally:
os.unlink(p)
+class HashingWriter(object):
+ """A file object with write capabilities that hashes the written data at
+ the same time it passes down to a real file object."""
+ def __init__(self, writer):
+ self._hash = hashlib.sha256()
+ self._writer = writer
+
+ def write(self, buf):
+ self._hash.update(buf)
+ self._writer.write(buf)
+
+ def hexdigest(self):
+ return self._hash.hexdigest()
+
+
def create_context_tar(topsrcdir, context_dir, out_path, prefix, args=None):
"""Create a context tarball.
A directory ``context_dir`` containing a Dockerfile will be assembled into
a gzipped tar file at ``out_path``. Files inside the archive will be
prefixed by directory ``prefix``.
We also scan the source Dockerfile for special syntax that influences
@@ -140,26 +155,19 @@ def create_context_tar(topsrcdir, contex
else:
archive_path = os.path.join(prefix, 'topsrcdir', p)
archive_files[archive_path] = fs_path
archive_files[os.path.join(prefix, 'Dockerfile')] = \
GeneratedFile(b''.join(content))
with open(out_path, 'wb') as fh:
- create_tar_gz_from_files(fh, archive_files, '%s.tar.gz' % prefix)
-
- h = hashlib.sha256()
- with open(out_path, 'rb') as fh:
- while True:
- data = fh.read(32768)
- if not data:
- break
- h.update(data)
- return h.hexdigest()
+ writer = HashingWriter(fh)
+ create_tar_gz_from_files(writer, archive_files, '%s.tar.gz' % prefix)
+ return writer.hexdigest()
def build_from_context(docker_bin, context_path, prefix, tag=None):
"""Build a Docker image from a context archive.
Given the path to a `docker` binary, a image build tar.gz (produced with
``create_context_tar()``, a prefix in that context containing files, and
an optional ``tag`` for the produced image, build that Docker image.