From 5c34f1e708b483969620419fcfde1cfc6dc369cc Mon Sep 17 00:00:00 2001 From: Kit Barnes Date: Thu, 27 Nov 2014 18:31:08 +0000 Subject: [PATCH 1/6] Add .dockerignore parser and use it in filter_func --- dockerfeed | 77 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/dockerfeed b/dockerfeed index 6589589..713b10f 100755 --- a/dockerfeed +++ b/dockerfeed @@ -16,31 +16,59 @@ limitations under the License. """ - -from tarfile import TarFile,TarInfo +import argparse +import fnmatch +import os +import sys +from tarfile import TarFile from cStringIO import StringIO -import os, sys, argparse + + +class DockerIgnoreParser(object): + def __init__(self, ignore_string): + self.ignore_rules = [line for line in ignore_string.split('\n') if line] + + def ignores(self, filename): + return any(fnmatch.fnmatchcase(filename, pattern) for pattern in self.ignore_rules) + + @classmethod + def from_filename(cls, filename): + with open(filename, 'r') as f: + return cls(f.read()) + + @classmethod + def from_file_obj(cls, file_obj): + return cls(file_obj.read()) class DockerContextGenerator(object): - def __init__(self, context, dockerfile, filter_list, replacement_list): + def __init__(self, context, dockerfile, filter_list, replacement_list, dockerignore): self.context = context self.filter_list = filter_list self.replacement_list = replacement_list self.dockerfile = dockerfile + self.dockerignore = dockerignore def filter_func(self, info): - if os.path.relpath(info.name) in filter_list: + path = os.path.relpath(info.name) + in_filter_list = path in filter_list + + if self.dockerignore is not None: + ignored = self.dockerignore.ignores(path) + else: + ignored = False + + if in_filter_list or ignored: return None else: return info def create_context(self): stringfile = StringIO() - with TarFile.open(mode='w',fileobj=stringfile) as tarfile: + with TarFile.open(mode='w', fileobj=stringfile) as tarfile: tarfile.add(self.context, arcname='.', filter=self.filter_func) - for src,dst in self.replacement_list: - tarfile.add(os.path.join(src,dst),arcname=os.path.join('.',dst)) + for src, dst in self.replacement_list: + tarfile.add(os.path.join(src, dst), arcname=os.path.join('.', dst)) if self.dockerfile: tarfile.add(self.dockerfile, arcname='./Dockerfile') stringfile.seek(0) @@ -53,27 +81,40 @@ if __name__ == '__main__': default=[], help='path to add/override in context. example: /path/to/./path_to_be_inserted') parser.add_argument('-d', '--dockerfile', metavar='DOCKERFILE', type=str, dest='dockerfile', default=None, action='store', help='replacement dockerfile') + parser.add_argument('-i', '--dockerignore', default=None, + help='A file containing glob rules for which files to exclude from the context.') parsed = parser.parse_args() filter_list = [] replacement_list = [] dockerfile = None - if parsed.dockerfile: + if parsed.dockerfile is not None: filter_list.append('Dockerfile') dockerfile = parsed.dockerfile if not os.path.isfile(dockerfile): - parser.error('Dockerfile is expected to be a plain file') + parser.error('DOCKERFILE is expected to be a plain file') + + if parsed.dockerignore is not None: + if not os.path.isfile(parsed.dockerignore): + parser.error('DOCKERIGNORE must be a file') + dockerignore = DockerIgnoreParser.from_filename(parsed.dockerignore) + else: + if os.path.isfile('.dockerignore'): + dockerignore = DockerIgnoreParser.from_filename('.dockerignore') + else: + dockerignore = None + for path in parsed.paths: try: - (source,dest) = path.split('/./') + (source, dest) = path.split('/./') except: parser.error('wrong path syntax') filter_list.append(os.path.relpath(dest)) - replacement_list.append((source,dest)) - dcg = DockerContextGenerator(os.path.relpath(parsed.context), dockerfile, filter_list, replacement_list) - dcg.create_context() - - - - + replacement_list.append((source, dest)) + dcg = DockerContextGenerator(os.path.relpath(parsed.context), + dockerfile, + filter_list, + replacement_list, + dockerignore) + tarstring = dcg.create_context() From cbbb4b36264a6d62a8036850db08c75f42cd3845 Mon Sep 17 00:00:00 2001 From: Kit Barnes Date: Thu, 27 Nov 2014 18:32:48 +0000 Subject: [PATCH 2/6] Update -h output in README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2ebbca6..9b7fd6f 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ dockerfeed -d ../Dockerfile.special path/to/dockerimagesource | docker build -t The `-p` option will allow to add extra content to the build context. ``` -usage: dockerfeed [-h] [-p PATH] [-d DOCKERFILE] context +usage: dockerfeed [-h] [-p PATH] [-d DOCKERFILE] [-i DOCKERIGNORE] context Replace Dockerfile and/or replace file path in context @@ -31,4 +31,7 @@ optional arguments: /path/to/./path_to_be_inserted -d DOCKERFILE, --dockerfile DOCKERFILE replacement dockerfile - ``` + -i DOCKERIGNORE, --dockerignore DOCKERIGNORE + A file containing glob rules for which files to + exclude from the context. +``` From f6f48cd355dffbc27b18dce11b5dfdff88884c56 Mon Sep 17 00:00:00 2001 From: Kit Barnes Date: Thu, 27 Nov 2014 18:34:33 +0000 Subject: [PATCH 3/6] Mention that dockerignore will use .dockignore in help text --- README.md | 3 ++- dockerfeed | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9b7fd6f..20cc8ca 100644 --- a/README.md +++ b/README.md @@ -33,5 +33,6 @@ optional arguments: replacement dockerfile -i DOCKERIGNORE, --dockerignore DOCKERIGNORE A file containing glob rules for which files to - exclude from the context. + exclude from the context. .dockerignore will be used + by default if it exists. ``` diff --git a/dockerfeed b/dockerfeed index 713b10f..f039b0a 100755 --- a/dockerfeed +++ b/dockerfeed @@ -82,7 +82,8 @@ if __name__ == '__main__': parser.add_argument('-d', '--dockerfile', metavar='DOCKERFILE', type=str, dest='dockerfile', default=None, action='store', help='replacement dockerfile') parser.add_argument('-i', '--dockerignore', default=None, - help='A file containing glob rules for which files to exclude from the context.') + help='A file containing glob rules for which files to exclude from the context. ' + '.dockerignore will be used by default if it exists.') parsed = parser.parse_args() filter_list = [] From aa7c3456a527d1f470cc8e92c059b52740a3fc0d Mon Sep 17 00:00:00 2001 From: Kit Barnes Date: Thu, 27 Nov 2014 19:20:28 +0000 Subject: [PATCH 4/6] Make it recognise when we put directories in with a trailing / --- dockerfeed | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dockerfeed b/dockerfeed index f039b0a..f499b35 100755 --- a/dockerfeed +++ b/dockerfeed @@ -26,7 +26,13 @@ from cStringIO import StringIO class DockerIgnoreParser(object): def __init__(self, ignore_string): - self.ignore_rules = [line for line in ignore_string.split('\n') if line] + self.ignore_rules = [self._mangle(line) for line in ignore_string.split('\n') if line] + + def _mangle(self, line): + if line.endswith('/'): + # Everything gets passed through os.path.relpath which *strips* trailing slashes + line = line[:-1] + return line def ignores(self, filename): return any(fnmatch.fnmatchcase(filename, pattern) for pattern in self.ignore_rules) From adaa2e6d68d08e7074a783c4c7292a73583a90a3 Mon Sep 17 00:00:00 2001 From: Kit Barnes Date: Thu, 27 Nov 2014 19:26:45 +0000 Subject: [PATCH 5/6] Remove unnecessary variable Definitely not leftover from changes in another branch, why would you think that? --- dockerfeed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockerfeed b/dockerfeed index f499b35..449edd9 100755 --- a/dockerfeed +++ b/dockerfeed @@ -124,4 +124,4 @@ if __name__ == '__main__': filter_list, replacement_list, dockerignore) - tarstring = dcg.create_context() + dcg.create_context() From c15f5b35af318ac26823a95cc1cbd1af9b83e1b3 Mon Sep 17 00:00:00 2001 From: Kit Barnes Date: Thu, 27 Nov 2014 19:39:09 +0000 Subject: [PATCH 6/6] Stop accidentally relying on globally scoped filter_list --- dockerfeed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockerfeed b/dockerfeed index 449edd9..7d164ec 100755 --- a/dockerfeed +++ b/dockerfeed @@ -57,7 +57,7 @@ class DockerContextGenerator(object): def filter_func(self, info): path = os.path.relpath(info.name) - in_filter_list = path in filter_list + in_filter_list = path in self.filter_list if self.dockerignore is not None: ignored = self.dockerignore.ignores(path)