From e30cd931d11b6028bc85e76b6e6814f0d6e245c6 Mon Sep 17 00:00:00 2001 From: Charlton Austin Date: Thu, 2 Mar 2017 11:24:04 -0500 Subject: [PATCH] feat(buildtrigger): allow use to specify dockerfile users can only specify the folder and the dockerfile must be names "Dockerfile" this allows users to specify the file and it can be called "Dockerfile" or .Dockerfile --- .gitignore | 1 + buildman/component/buildcomponent.py | 7 ++++++- buildman/manager/executor.py | 1 + buildtrigger/basehandler.py | 14 ++++++-------- buildtrigger/bitbuckethandler.py | 19 +++++++------------ buildtrigger/githubhandler.py | 6 +++--- buildtrigger/gitlabhandler.py | 7 ++----- buildtrigger/test/test_basehandler.py | 15 +++++++++++++++ buildtrigger/test/test_bitbuckethandler.py | 6 +++--- buildtrigger/test/test_githubhandler.py | 6 +++--- buildtrigger/test/test_gitlabhandler.py | 6 +++--- static/js/services/trigger-service.js | 4 ---- 12 files changed, 50 insertions(+), 42 deletions(-) create mode 100644 buildtrigger/test/test_basehandler.py diff --git a/.gitignore b/.gitignore index 9c8de6681..d5a2ef909 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ htmlcov .tox .cache .npm-debug.log +Dockerfile-e diff --git a/buildman/component/buildcomponent.py b/buildman/component/buildcomponent.py index e7730cd81..eeb6d0dba 100644 --- a/buildman/component/buildcomponent.py +++ b/buildman/component/buildcomponent.py @@ -1,4 +1,5 @@ import datetime +import os import time import logging import json @@ -122,9 +123,13 @@ class BuildComponent(BaseComponent): # base_image: The image name and credentials to use to conduct the base image pull. # username: The username for pulling the base image (if any). # password: The password for pulling the base image (if any). + + subdir, dockerfile_name = os.path.split(build_config.get('build_subdir', '/Dockerfile')) + build_arguments = { 'build_package': build_job.get_build_package_url(self.user_files), - 'sub_directory': build_config.get('build_subdir', ''), + 'sub_directory': subdir, + 'dockerfile_name': dockerfile_name, 'repository': repository_name, 'registry': self.registry_hostname, 'pull_token': build_job.repo_build.access_token.code, diff --git a/buildman/manager/executor.py b/buildman/manager/executor.py index 202cf0921..585267c05 100644 --- a/buildman/manager/executor.py +++ b/buildman/manager/executor.py @@ -276,6 +276,7 @@ class PopenExecutor(BuilderExecutor): 'DOCKER_TLS_VERIFY': os.environ.get('DOCKER_TLS_VERIFY', ''), 'DOCKER_CERT_PATH': os.environ.get('DOCKER_CERT_PATH', ''), 'DOCKER_HOST': os.environ.get('DOCKER_HOST', ''), + 'PATH': "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" } logpipe = LogPipe(logging.INFO) diff --git a/buildtrigger/basehandler.py b/buildtrigger/basehandler.py index f8ed97563..a991c3be9 100644 --- a/buildtrigger/basehandler.py +++ b/buildtrigger/basehandler.py @@ -258,6 +258,11 @@ class BuildTriggerHandler(object): can be called in a loop, so it should be as fast as possible. """ pass + @classmethod + def path_is_dockerfile(cls, file_name): + """ Returns whether the file is named Dockerfile or follows the convention .Dockerfile""" + return file_name.endswith(".Dockerfile") or u"Dockerfile" == file_name + @classmethod def service_name(cls): """ @@ -285,14 +290,7 @@ class BuildTriggerHandler(object): def get_dockerfile_path(self): """ Returns the normalized path to the Dockerfile found in the subdirectory in the config. """ - subdirectory = self.config.get('subdir', '') - if subdirectory == '/': - subdirectory = '' - else: - if not subdirectory.endswith('/'): - subdirectory = subdirectory + '/' - - return subdirectory + 'Dockerfile' + return self.config.get('subdir', '') def prepare_build(self, metadata, is_manual=False): # Ensure that the metadata meets the scheme. diff --git a/buildtrigger/bitbuckethandler.py b/buildtrigger/bitbuckethandler.py index 02e6b228f..68290cde4 100644 --- a/buildtrigger/bitbuckethandler.py +++ b/buildtrigger/bitbuckethandler.py @@ -1,23 +1,21 @@ import logging +import os import re - from calendar import timegm import dateutil.parser - +from bitbucket import BitBucket from jsonschema import validate + +from app import app, get_app_url +from buildtrigger.basehandler import BuildTriggerHandler from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException, TriggerDeactivationException, TriggerStartException, InvalidPayloadException, TriggerProviderException, determine_build_ref, raise_if_skipped_build, find_matching_branches) - -from buildtrigger.basehandler import BuildTriggerHandler - -from app import app, get_app_url -from bitbucket import BitBucket -from util.security.ssh import generate_ssh_keypair from util.dict_wrappers import JSONPathDict, SafeDictSetter +from util.security.ssh import generate_ssh_keypair logger = logging.getLogger(__name__) @@ -455,10 +453,7 @@ class BitbucketBuildTrigger(BuildTriggerHandler): raise RepositoryReadException(err_msg) files = set([f['path'] for f in data['files']]) - if 'Dockerfile' in files: - return [''] - - return [] + return ["/" + file_path for file_path in files if self.path_is_dockerfile(os.path.basename(file_path))] def load_dockerfile_contents(self): repository = self._get_repository_client() diff --git a/buildtrigger/githubhandler.py b/buildtrigger/githubhandler.py index a6df8a979..80dd5e2aa 100644 --- a/buildtrigger/githubhandler.py +++ b/buildtrigger/githubhandler.py @@ -1,6 +1,7 @@ import logging import os.path import base64 +import re from calendar import timegm from functools import wraps @@ -348,9 +349,8 @@ class GithubBuildTrigger(BuildTriggerHandler): default_commit = repo.get_branch(branches[0]).commit commit_tree = repo.get_git_tree(default_commit.sha, recursive=True) - return [os.path.dirname(elem.path) for elem in commit_tree.tree - if (elem.type == u'blob' and - os.path.basename(elem.path) == u'Dockerfile')] + return [elem.path for elem in commit_tree.tree + if (elem.type == u'blob' and self.path_is_dockerfile(os.path.basename(elem.path)))] except GithubException as ghe: message = ghe.data.get('message', 'Unable to list contents of repository: %s' % source) if message == 'Branch not found': diff --git a/buildtrigger/gitlabhandler.py b/buildtrigger/gitlabhandler.py index 5d221874b..0bd47c910 100644 --- a/buildtrigger/gitlabhandler.py +++ b/buildtrigger/gitlabhandler.py @@ -1,4 +1,5 @@ import logging +import os from calendar import timegm from functools import wraps @@ -341,11 +342,7 @@ class GitLabBuildTrigger(BuildTriggerHandler): msg = 'Unable to find GitLab repository tree for source: %s' % new_build_source raise RepositoryReadException(msg) - for node in repo_tree: - if node['name'] == 'Dockerfile': - return [''] - - return [] + return ["/"+node['name'] for node in repo_tree if self.path_is_dockerfile(node['name'])] @_catch_timeouts def load_dockerfile_contents(self): diff --git a/buildtrigger/test/test_basehandler.py b/buildtrigger/test/test_basehandler.py new file mode 100644 index 000000000..d8955740a --- /dev/null +++ b/buildtrigger/test/test_basehandler.py @@ -0,0 +1,15 @@ +import pytest + +from buildtrigger.basehandler import BuildTriggerHandler + + +@pytest.mark.parametrize('input,output', [ + ("Dockerfile", True), + ("server.Dockerfile", True), + (u"Dockerfile", True), + (u"server.Dockerfile", True), + ("bad file name", False), + (u"bad file name", False), +]) +def test_path_is_dockerfile(input, output): + assert BuildTriggerHandler.path_is_dockerfile(input) == output diff --git a/buildtrigger/test/test_bitbuckethandler.py b/buildtrigger/test/test_bitbuckethandler.py index 12c653db5..320a18906 100644 --- a/buildtrigger/test/test_bitbuckethandler.py +++ b/buildtrigger/test/test_bitbuckethandler.py @@ -13,12 +13,12 @@ def bitbucket_trigger(): def test_list_build_subdirs(bitbucket_trigger): - assert bitbucket_trigger.list_build_subdirs() == [''] + assert bitbucket_trigger.list_build_subdirs() == ["/Dockerfile"] @pytest.mark.parametrize('subdir, contents', [ - ('', 'hello world'), - ('somesubdir', 'hi universe'), + ('/Dockerfile', 'hello world'), + ('somesubdir/Dockerfile', 'hi universe'), ('unknownpath', None), ]) def test_load_dockerfile_contents(subdir, contents): diff --git a/buildtrigger/test/test_githubhandler.py b/buildtrigger/test/test_githubhandler.py index 5f9a1d786..4ca91ece4 100644 --- a/buildtrigger/test/test_githubhandler.py +++ b/buildtrigger/test/test_githubhandler.py @@ -68,8 +68,8 @@ def test_handle_trigger_request(github_trigger, payload, expected_error, expecte @pytest.mark.parametrize('subdir, contents', [ - ('', 'hello world'), - ('somesubdir', 'hi universe'), + ('/Dockerfile', 'hello world'), + ('somesubdir/Dockerfile', 'hi universe'), ('unknownpath', None), ]) def test_load_dockerfile_contents(subdir, contents): @@ -86,4 +86,4 @@ def test_lookup_user(username, expected_response, github_trigger): def test_list_build_subdirs(github_trigger): - assert github_trigger.list_build_subdirs() == ['', 'somesubdir'] + assert github_trigger.list_build_subdirs() == ['Dockerfile', 'somesubdir/Dockerfile'] diff --git a/buildtrigger/test/test_gitlabhandler.py b/buildtrigger/test/test_gitlabhandler.py index c88c591d6..d20a690be 100644 --- a/buildtrigger/test/test_gitlabhandler.py +++ b/buildtrigger/test/test_gitlabhandler.py @@ -13,12 +13,12 @@ def gitlab_trigger(): def test_list_build_subdirs(gitlab_trigger): - assert gitlab_trigger.list_build_subdirs() == [''] + assert gitlab_trigger.list_build_subdirs() == ['/Dockerfile'] @pytest.mark.parametrize('subdir, contents', [ - ('', 'hello world'), - ('somesubdir', 'hi universe'), + ('/Dockerfile', 'hello world'), + ('somesubdir/Dockerfile', 'hi universe'), ('unknownpath', None), ]) def test_load_dockerfile_contents(subdir, contents): diff --git a/static/js/services/trigger-service.js b/static/js/services/trigger-service.js index 6406fec10..3d8c3d143 100644 --- a/static/js/services/trigger-service.js +++ b/static/js/services/trigger-service.js @@ -208,10 +208,6 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K return '//Dockerfile'; } - if (subdirectory[subdirectory.length - 1] != '/') { - subdirectory = subdirectory + '/'; - } - return '//' + subdirectory.replace(new RegExp('(^\/+|\/+$)'), '') + 'Dockerfile'; };