Add support for pull credentials on builds and build triggers

This commit is contained in:
Joseph Schorr 2014-03-27 18:33:13 -04:00
parent 1fc3c922a9
commit 2006917e03
17 changed files with 355 additions and 37 deletions

View file

@ -33,6 +33,13 @@ def get_job_config(build_obj):
def trigger_view(trigger):
def user_view(user):
return {
'name': user.username,
'kind': 'user',
'is_robot': user.robot,
}
if trigger and trigger.uuid:
config_dict = get_trigger_config(trigger)
build_trigger = BuildTrigger.get_trigger_for_service(trigger.service.name)
@ -41,7 +48,8 @@ def trigger_view(trigger):
'config': config_dict,
'id': trigger.uuid,
'connected_user': trigger.connected_user.username,
'is_active': build_trigger.is_active(config_dict)
'is_active': build_trigger.is_active(config_dict),
'pull_user': user_view(trigger.pull_user) if trigger.pull_user else None
}
return None
@ -88,6 +96,29 @@ class RepositoryBuildList(RepositoryParamResource):
'type': 'string',
'description': 'Subdirectory in which the Dockerfile can be found',
},
'pull_credentials': {
'type': 'object',
'description': 'Credentials used by the builder when pulling images',
'required': [
'username',
'password',
'registry'
],
'properties': {
'username': {
'type': 'string',
'description': 'The username for the pull'
},
'password': {
'type': 'string',
'description': 'The password for the pull'
},
'registry': {
'type': 'string',
'description': 'The registry hostname for the pull'
},
}
}
},
},
}
@ -116,6 +147,7 @@ class RepositoryBuildList(RepositoryParamResource):
dockerfile_id = request_json['file_id']
subdir = request_json['subdirectory'] if 'subdirectory' in request_json else ''
pull_credentials = request_json.get('pull_credentials', None)
# Check if the dockerfile resource has already been used. If so, then it
# can only be reused if the user has access to the repository for which it
@ -130,7 +162,8 @@ class RepositoryBuildList(RepositoryParamResource):
repo = model.get_repository(namespace, repository)
display_name = user_files.get_file_checksum(dockerfile_id)
build_request = start_build(repo, dockerfile_id, ['latest'], display_name, subdir, True)
build_request = start_build(repo, dockerfile_id, ['latest'], display_name, subdir, True,
pull_credentials=pull_credentials)
resp = build_status_view(build_request, True)
repo_string = '%s/%s' % (namespace, repository)

View file

@ -15,7 +15,8 @@ from endpoints.common import start_build
from endpoints.trigger import (BuildTrigger as BuildTriggerBase, TriggerDeactivationException,
TriggerActivationException, EmptyRepositoryException)
from data import model
from auth.permissions import UserAdminPermission
from auth.permissions import UserAdminPermission, AdministerOrganizationPermission
from util.names import parse_robot_username
logger = logging.getLogger(__name__)
@ -133,7 +134,19 @@ class BuildTriggerActivate(RepositoryParamResource):
'BuildTriggerActivateRequest': {
'id': 'BuildTriggerActivateRequest',
'type': 'object',
'description': 'Arbitrary json.',
'required': [
'config'
],
'properties': {
'config': {
'type': 'object',
'description': 'Arbitrary json.',
},
'pull_robot': {
'type': 'string',
'description': 'The name of the robot that will be used to pull images.'
}
}
},
}
@ -154,7 +167,27 @@ class BuildTriggerActivate(RepositoryParamResource):
user_permission = UserAdminPermission(trigger.connected_user.username)
if user_permission.can():
new_config_dict = request.get_json()
# Update the pull robot (if any).
pull_robot_name = request.get_json().get('pull_robot', None)
if pull_robot_name:
pull_robot = model.lookup_robot(pull_robot_name)
if not pull_robot:
raise NotFound()
# Make sure the user has administer permissions for the robot's namespace.
(robot_namespace, shortname) = parse_robot_username(pull_robot_name)
if not AdministerOrganizationPermission(robot_namespace).can():
raise Unauthorized()
# Make sure the namespace matches that of the trigger.
if robot_namespace != namespace:
raise Unauthorized()
# Set the pull robot.
trigger.pull_user = pull_robot
# Update the config.
new_config_dict = request.get_json()['config']
token_name = 'Build Trigger: %s' % trigger.service.name
token = model.create_delegate_token(namespace, repository, token_name,
@ -185,6 +218,7 @@ class BuildTriggerActivate(RepositoryParamResource):
log_action('setup_repo_trigger', namespace,
{'repo': repository, 'namespace': namespace,
'trigger_id': trigger.uuid, 'service': trigger.service.name,
'pull_user': trigger.pull_user.username if trigger.pull_user else None,
'config': final_config}, repo=repo)
return trigger_view(trigger)
@ -214,8 +248,10 @@ class ActivateBuildTrigger(RepositoryParamResource):
dockerfile_id, tags, name, subdir = specs
repo = model.get_repository(namespace, repository)
pull_credentials = model.get_pull_credentials(trigger)
build_request = start_build(repo, dockerfile_id, tags, name, subdir, True)
build_request = start_build(repo, dockerfile_id, tags, name, subdir, True,
pull_credentials=pull_credentials)
resp = build_status_view(build_request, True)
repo_string = '%s/%s' % (namespace, repository)

View file

@ -100,7 +100,7 @@ def check_repository_usage(user_or_org, plan_found):
def start_build(repository, dockerfile_id, tags, build_name, subdir, manual,
trigger=None):
trigger=None, pull_credentials=None):
host = urlparse.urlparse(request.url).netloc
repo_path = '%s/%s/%s' % (host, repository.namespace, repository.name)
@ -112,7 +112,9 @@ def start_build(repository, dockerfile_id, tags, build_name, subdir, manual,
'docker_tags': tags,
'repository': repo_path,
'build_subdir': subdir,
'pull_credentials': pull_credentials,
}
build_request = model.create_repository_build(repository, token, job_config,
dockerfile_id, build_name,
trigger)

View file

@ -73,8 +73,10 @@ def build_trigger_webhook(namespace, repository, trigger_uuid):
# This was just a validation request, we don't need to build anything
return make_response('Okay')
pull_credentials = model.get_pull_credentials(trigger)
repo = model.get_repository(namespace, repository)
start_build(repo, dockerfile_id, tags, name, subdir, False, trigger)
start_build(repo, dockerfile_id, tags, name, subdir, False, trigger,
pull_credentials=pull_credentials)
return make_response('Okay')