--- a/taskcluster/taskgraph/util/docker.py
+++ b/taskcluster/taskgraph/util/docker.py
@@ -68,32 +68,54 @@ def create_context_tar(topsrcdir, contex
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
context generation.
- If a line in the Dockerfile has the form ``# %include <path>``,
+ If a line in the ``Dockerfile`` has the form ``# %include <path>``,
the relative path specified on that line will be matched against
files in the source repository and added to the context under the
path ``topsrcdir/``. If an entry is a directory, we add all files
under that directory.
Returns the SHA-256 hex digest of the created archive.
"""
+ if os.path.exists(os.path.join(context_dir, 'Dockerfile')):
+ archive_files = _archive_files_from_dockerfile(topsrcdir, context_dir)
+ else:
+ raise Exception('do not know how to build docker image from %s; must '
+ 'have Dockerfile' % context_dir)
+
+ archive_files = {os.path.join(prefix, k): v
+ for k, v in archive_files.items()}
+
+ 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()
+
+
+def _archive_files_from_dockerfile(topsrcdir, context_dir):
archive_files = {}
for root, dirs, files in os.walk(context_dir):
for f in files:
source_path = os.path.join(root, f)
rel = source_path[len(context_dir) + 1:]
- archive_path = os.path.join(prefix, rel)
- archive_files[archive_path] = source_path
+ archive_files[rel] = source_path
# Parse Dockerfile for special syntax of extra files to include.
with open(os.path.join(context_dir, 'Dockerfile'), 'rb') as fh:
for line in fh:
line = line.rstrip()
if not line.startswith('# %include'):
continue
@@ -108,33 +130,25 @@ def create_context_tar(topsrcdir, contex
if not os.path.exists(fs_path):
raise Exception('extra include path does not exist: %s' % p)
if os.path.isdir(fs_path):
for root, dirs, files in os.walk(fs_path):
for f in files:
source_path = os.path.join(root, f)
- archive_path = os.path.join(prefix, 'topsrcdir', p, f)
+ archive_path = os.path.join('topsrcdir', p, f)
archive_files[archive_path] = source_path
else:
- archive_path = os.path.join(prefix, 'topsrcdir', p)
+ archive_path = os.path.join('topsrcdir', p)
archive_files[archive_path] = fs_path
- with open(out_path, 'wb') as fh:
- create_tar_gz_from_files(fh, archive_files, '%s.tar.gz' % prefix)
+ return archive_files
- 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()
+
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.