feat(build runner): added in context, dockerfile_location
this is a new feature meant to allow people to use any file as a dockerfile and any folder as a context directory
This commit is contained in:
parent
90b130fe16
commit
e6d201e0b0
29 changed files with 531 additions and 111 deletions
|
@ -2,17 +2,21 @@
|
|||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from os import path
|
||||
from urllib import quote
|
||||
from urlparse import urlunparse
|
||||
|
||||
from flask import request, url_for
|
||||
|
||||
from app import app
|
||||
from auth.permissions import (UserAdminPermission, AdministerOrganizationPermission,
|
||||
ReadRepositoryPermission, AdministerRepositoryPermission)
|
||||
from buildtrigger.basehandler import BuildTriggerHandler
|
||||
from buildtrigger.triggerutil import (TriggerDeactivationException,
|
||||
TriggerActivationException, EmptyRepositoryException,
|
||||
RepositoryReadException, TriggerStartException)
|
||||
from data import model
|
||||
from data.model.build import update_build_trigger
|
||||
from endpoints.api import (RepositoryParamResource, nickname, resource, require_repo_admin,
|
||||
log_action, request_error, query_param, parse_args, internal_only,
|
||||
validate_json_request, api, path_param, abort,
|
||||
|
@ -20,12 +24,9 @@ from endpoints.api import (RepositoryParamResource, nickname, resource, require_
|
|||
from endpoints.exception import NotFound, Unauthorized, InvalidRequest
|
||||
from endpoints.api.build import build_status_view, trigger_view, RepositoryBuildStatus
|
||||
from endpoints.building import start_build, MaximumBuildsQueuedException
|
||||
from data import model
|
||||
from auth.permissions import (UserAdminPermission, AdministerOrganizationPermission,
|
||||
ReadRepositoryPermission, AdministerRepositoryPermission)
|
||||
from util.names import parse_robot_username
|
||||
from endpoints.exception import NotFound, Unauthorized, InvalidRequest
|
||||
from util.dockerfileparse import parse_dockerfile
|
||||
|
||||
from util.names import parse_robot_username
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -131,19 +132,25 @@ class BuildTriggerSubdirs(RepositoryParamResource):
|
|||
|
||||
try:
|
||||
subdirs = handler.list_build_subdirs()
|
||||
context_map = {}
|
||||
for file in subdirs:
|
||||
context_map = handler.get_parent_directory_mappings(file, context_map)
|
||||
|
||||
return {
|
||||
'subdir': ['/' + subdir for subdir in subdirs],
|
||||
'status': 'success'
|
||||
'dockerfile_paths': ['/' + subdir for subdir in subdirs],
|
||||
'contextMap': context_map,
|
||||
'status': 'success',
|
||||
}
|
||||
except EmptyRepositoryException as exc:
|
||||
return {
|
||||
'status': 'success',
|
||||
'subdir': []
|
||||
'contextMap': {},
|
||||
'dockerfile_paths': [],
|
||||
}
|
||||
except RepositoryReadException as exc:
|
||||
return {
|
||||
'status': 'error',
|
||||
'message': exc.message
|
||||
'message': exc.message,
|
||||
}
|
||||
else:
|
||||
raise Unauthorized()
|
||||
|
@ -235,9 +242,7 @@ class BuildTriggerActivate(RepositoryParamResource):
|
|||
raise request_error(message=exc.message)
|
||||
|
||||
# Save the updated config.
|
||||
trigger.config = json.dumps(final_config)
|
||||
trigger.write_token = write_token
|
||||
trigger.save()
|
||||
update_build_trigger(trigger, final_config, write_token=write_token)
|
||||
|
||||
# Log the trigger setup.
|
||||
repo = model.repository.get_repository(namespace_name, repo_name)
|
||||
|
@ -343,6 +348,15 @@ class BuildTriggerAnalyze(RepositoryParamResource):
|
|||
'message': 'Could not parse the Dockerfile specified'
|
||||
}
|
||||
|
||||
# Check whether the dockerfile_path is correct
|
||||
if new_config_dict.get('context'):
|
||||
if not is_parent(new_config_dict.get('context'), new_config_dict.get('dockerfile_path')):
|
||||
return {
|
||||
'status': 'error',
|
||||
'message': 'Dockerfile, %s, is not child of the context, %s.' %
|
||||
(new_config_dict.get('context'), new_config_dict.get('dockerfile_path'))
|
||||
}
|
||||
|
||||
# Default to the current namespace.
|
||||
base_namespace = namespace_name
|
||||
base_repository = None
|
||||
|
@ -399,6 +413,28 @@ class BuildTriggerAnalyze(RepositoryParamResource):
|
|||
raise NotFound()
|
||||
|
||||
|
||||
def is_parent(context, dockerfile_path):
|
||||
""" This checks whether the context is a parent of the dockerfile_path"""
|
||||
if context == "" or dockerfile_path == "":
|
||||
return False
|
||||
|
||||
normalized_context = path.normpath(context)
|
||||
if normalized_context[len(normalized_context) - 1] != path.sep:
|
||||
normalized_context += path.sep
|
||||
|
||||
if normalized_context[0] != path.sep:
|
||||
normalized_context = path.sep + normalized_context
|
||||
|
||||
normalized_subdir = path.normpath(path.dirname(dockerfile_path))
|
||||
if normalized_subdir[0] != path.sep:
|
||||
normalized_subdir = path.sep + normalized_subdir
|
||||
|
||||
if normalized_subdir[len(normalized_subdir) - 1] != path.sep:
|
||||
normalized_subdir += path.sep
|
||||
|
||||
return normalized_subdir.startswith(normalized_context)
|
||||
|
||||
|
||||
@resource('/v1/repository/<apirepopath:repository>/trigger/<trigger_uuid>/start')
|
||||
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
||||
@path_param('trigger_uuid', 'The UUID of the build trigger')
|
||||
|
@ -418,7 +454,7 @@ class ActivateBuildTrigger(RepositoryParamResource):
|
|||
'description': '(Custom Only) If specified, the ref/SHA1 used to checkout a git repository.'
|
||||
},
|
||||
'refs': {
|
||||
'type': ['object', 'null'],
|
||||
'type': ['object', 'null'],
|
||||
'description': '(SCM Only) If specified, the ref to build.'
|
||||
}
|
||||
},
|
||||
|
@ -467,6 +503,7 @@ class ActivateBuildTrigger(RepositoryParamResource):
|
|||
@path_param('trigger_uuid', 'The UUID of the build trigger')
|
||||
class TriggerBuildList(RepositoryParamResource):
|
||||
""" Resource to represent builds that were activated from the specified trigger. """
|
||||
|
||||
@require_repo_admin
|
||||
@disallow_for_app_repositories
|
||||
@parse_args()
|
||||
|
@ -483,10 +520,12 @@ class TriggerBuildList(RepositoryParamResource):
|
|||
|
||||
FIELD_VALUE_LIMIT = 30
|
||||
|
||||
|
||||
@resource('/v1/repository/<apirepopath:repository>/trigger/<trigger_uuid>/fields/<field_name>')
|
||||
@internal_only
|
||||
class BuildTriggerFieldValues(RepositoryParamResource):
|
||||
""" Custom verb to fetch a values list for a particular field name. """
|
||||
|
||||
@require_repo_admin
|
||||
@disallow_for_app_repositories
|
||||
@nickname('listTriggerFieldValues')
|
||||
|
@ -558,13 +597,13 @@ class BuildTriggerSources(RepositoryParamResource):
|
|||
raise Unauthorized()
|
||||
|
||||
|
||||
|
||||
@resource('/v1/repository/<apirepopath:repository>/trigger/<trigger_uuid>/namespaces')
|
||||
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
||||
@path_param('trigger_uuid', 'The UUID of the build trigger')
|
||||
@internal_only
|
||||
class BuildTriggerSourceNamespaces(RepositoryParamResource):
|
||||
""" Custom verb to fetch the list of namespaces (orgs, projects, etc) for the trigger config. """
|
||||
|
||||
@require_repo_admin
|
||||
@disallow_for_app_repositories
|
||||
@nickname('listTriggerBuildSourceNamespaces')
|
||||
|
|
Reference in a new issue