Merge "Add playbook_context zuul variable"
This commit is contained in:
@@ -422,6 +422,30 @@ class KubeFwd(object):
|
||||
pass
|
||||
|
||||
|
||||
class JobDirPlaybookRole(object):
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.link_src = None
|
||||
self.link_target = None
|
||||
self.role_path = None
|
||||
self.checkout_description = None
|
||||
self.checkout = None
|
||||
|
||||
def toDict(self, jobdir_root=None):
|
||||
# This is serialized to the zuul.playbook_context variable
|
||||
if jobdir_root:
|
||||
strip = len(jobdir_root) + 1
|
||||
else:
|
||||
strip = 0
|
||||
return dict(
|
||||
link_name=self.link_name[strip:],
|
||||
link_target=self.link_target[strip:],
|
||||
role_path=self.role_path[strip:],
|
||||
checkout_description=self.checkout_description,
|
||||
checkout=self.checkout,
|
||||
)
|
||||
|
||||
|
||||
class JobDirPlaybook(object):
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
@@ -445,8 +469,25 @@ class JobDirPlaybook(object):
|
||||
count = len(self.roles)
|
||||
root = os.path.join(self.root, 'role_%i' % (count,))
|
||||
os.makedirs(root)
|
||||
self.roles.append(root)
|
||||
return root
|
||||
role_info = JobDirPlaybookRole(root)
|
||||
self.roles.append(role_info)
|
||||
return role_info
|
||||
|
||||
|
||||
class JobDirProject(object):
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.canonical_name = None
|
||||
self.checkout = None
|
||||
self.commit = None
|
||||
|
||||
def toDict(self):
|
||||
# This is serialized to the zuul.playbook_context variable
|
||||
return dict(
|
||||
canonical_name=self.canonical_name,
|
||||
checkout=self.checkout,
|
||||
commit=self.commit,
|
||||
)
|
||||
|
||||
|
||||
class JobDir(object):
|
||||
@@ -594,10 +635,8 @@ class JobDir(object):
|
||||
job_output.write("{now} | Job console starting...\n".format(
|
||||
now=datetime.datetime.now()
|
||||
))
|
||||
self.trusted_projects = []
|
||||
self.trusted_project_index = {}
|
||||
self.untrusted_projects = []
|
||||
self.untrusted_project_index = {}
|
||||
self.trusted_projects = {}
|
||||
self.untrusted_projects = {}
|
||||
|
||||
# Create a JobDirPlaybook for the Ansible setup run. This
|
||||
# doesn't use an actual playbook, but it lets us use the same
|
||||
@@ -623,12 +662,14 @@ class JobDir(object):
|
||||
count = len(self.trusted_projects)
|
||||
root = os.path.join(self.trusted_root, 'project_%i' % (count,))
|
||||
os.makedirs(root)
|
||||
self.trusted_projects.append(root)
|
||||
self.trusted_project_index[(canonical_name, branch)] = root
|
||||
return root
|
||||
project_info = JobDirProject(root)
|
||||
project_info.canonical_name = canonical_name
|
||||
project_info.checkout = branch
|
||||
self.trusted_projects[(canonical_name, branch)] = project_info
|
||||
return project_info
|
||||
|
||||
def getTrustedProject(self, canonical_name, branch):
|
||||
return self.trusted_project_index.get((canonical_name, branch))
|
||||
return self.trusted_projects.get((canonical_name, branch))
|
||||
|
||||
def addUntrustedProject(self, canonical_name, branch):
|
||||
# Similar to trusted projects, but these hold checkouts of
|
||||
@@ -640,12 +681,14 @@ class JobDir(object):
|
||||
count = len(self.untrusted_projects)
|
||||
root = os.path.join(self.untrusted_root, 'project_%i' % (count,))
|
||||
os.makedirs(root)
|
||||
self.untrusted_projects.append(root)
|
||||
self.untrusted_project_index[(canonical_name, branch)] = root
|
||||
return root
|
||||
project_info = JobDirProject(root)
|
||||
project_info.canonical_name = canonical_name
|
||||
project_info.checkout = branch
|
||||
self.untrusted_projects[(canonical_name, branch)] = project_info
|
||||
return project_info
|
||||
|
||||
def getUntrustedProject(self, canonical_name, branch):
|
||||
return self.untrusted_project_index.get((canonical_name, branch))
|
||||
return self.untrusted_projects.get((canonical_name, branch))
|
||||
|
||||
def addPrePlaybook(self):
|
||||
count = len(self.pre_playbooks)
|
||||
@@ -1356,12 +1399,14 @@ class AnsibleJob(object):
|
||||
self.log.info("Checking out %s %s %s",
|
||||
project['canonical_name'], selected_desc,
|
||||
selected_ref)
|
||||
repo.checkout(selected_ref)
|
||||
commit = repo.checkout(selected_ref)
|
||||
|
||||
# Update the inventory variables to indicate the ref we
|
||||
# checked out
|
||||
p = args['zuul']['projects'][project['canonical_name']]
|
||||
p['checkout'] = selected_ref
|
||||
p['checkout_description'] = selected_desc
|
||||
p['commit'] = commit.hexsha
|
||||
|
||||
# Set the URL of the origin remote for each repo to a bogus
|
||||
# value. Keeping the remote allows tools to use it to determine
|
||||
@@ -2049,43 +2094,44 @@ class AnsibleJob(object):
|
||||
return ret
|
||||
|
||||
def checkoutTrustedProject(self, project, branch, args):
|
||||
root = self.jobdir.getTrustedProject(project.canonical_name,
|
||||
branch)
|
||||
if not root:
|
||||
root = self.jobdir.addTrustedProject(project.canonical_name,
|
||||
branch)
|
||||
pi = self.jobdir.getTrustedProject(project.canonical_name,
|
||||
branch)
|
||||
if not pi:
|
||||
pi = self.jobdir.addTrustedProject(project.canonical_name,
|
||||
branch)
|
||||
self.log.debug("Cloning %s@%s into new trusted space %s",
|
||||
project, branch, root)
|
||||
project, branch, pi.root)
|
||||
# We always use the golang scheme for playbook checkouts
|
||||
# (so that the path indicates the canonical repo name for
|
||||
# easy debugging; there are no concerns with collisions
|
||||
# since we only have one repo in the working dir).
|
||||
merger = self.executor_server._getMerger(
|
||||
root,
|
||||
pi.root,
|
||||
self.executor_server.merge_root,
|
||||
logger=self.log,
|
||||
scheme=zuul.model.SCHEME_GOLANG)
|
||||
merger.checkoutBranch(
|
||||
commit = merger.checkoutBranch(
|
||||
project.connection_name, project.name,
|
||||
branch,
|
||||
repo_state=self.repo_state,
|
||||
process_worker=self.executor_server.process_worker,
|
||||
zuul_event_id=self.zuul_event_id)
|
||||
pi.commit = commit.hexsha
|
||||
else:
|
||||
self.log.debug("Using existing repo %s@%s in trusted space %s",
|
||||
project, branch, root)
|
||||
project, branch, pi.root)
|
||||
|
||||
path = os.path.join(root,
|
||||
path = os.path.join(pi.root,
|
||||
project.canonical_hostname,
|
||||
project.name)
|
||||
return path
|
||||
|
||||
def checkoutUntrustedProject(self, project, branch, args):
|
||||
root = self.jobdir.getUntrustedProject(project.canonical_name,
|
||||
branch)
|
||||
if not root:
|
||||
root = self.jobdir.addUntrustedProject(project.canonical_name,
|
||||
branch)
|
||||
pi = self.jobdir.getUntrustedProject(project.canonical_name,
|
||||
branch)
|
||||
if not pi:
|
||||
pi = self.jobdir.addUntrustedProject(project.canonical_name,
|
||||
branch)
|
||||
# If the project is in the dependency chain, clone from
|
||||
# there so we pick up any speculative changes, otherwise,
|
||||
# clone from the cache.
|
||||
@@ -2101,7 +2147,7 @@ class AnsibleJob(object):
|
||||
# We already have this repo prepared
|
||||
self.log.debug("Found workdir repo for untrusted project")
|
||||
merger = self.executor_server._getMerger(
|
||||
root,
|
||||
pi.root,
|
||||
self.jobdir.src_root,
|
||||
logger=self.log,
|
||||
scheme=zuul.model.SCHEME_GOLANG,
|
||||
@@ -2111,7 +2157,7 @@ class AnsibleJob(object):
|
||||
repo_state = None
|
||||
if merger is None:
|
||||
merger = self.executor_server._getMerger(
|
||||
root,
|
||||
pi.root,
|
||||
self.executor_server.merge_root,
|
||||
logger=self.log,
|
||||
scheme=zuul.model.SCHEME_GOLANG)
|
||||
@@ -2122,17 +2168,18 @@ class AnsibleJob(object):
|
||||
repo_state = self.repo_state
|
||||
|
||||
self.log.debug("Cloning %s@%s into new untrusted space %s",
|
||||
project, branch, root)
|
||||
merger.checkoutBranch(
|
||||
project, branch, pi.root)
|
||||
commit = merger.checkoutBranch(
|
||||
project.connection_name, project.name,
|
||||
branch, repo_state=repo_state,
|
||||
process_worker=self.executor_server.process_worker,
|
||||
zuul_event_id=self.zuul_event_id)
|
||||
pi.commit = commit.hexsha
|
||||
else:
|
||||
self.log.debug("Using existing repo %s@%s in trusted space %s",
|
||||
project, branch, root)
|
||||
project, branch, pi.root)
|
||||
|
||||
path = os.path.join(root,
|
||||
path = os.path.join(pi.root,
|
||||
project.canonical_hostname,
|
||||
project.name)
|
||||
return path
|
||||
@@ -2173,8 +2220,8 @@ class AnsibleJob(object):
|
||||
|
||||
def prepareRole(self, jobdir_playbook, role, args):
|
||||
if role['type'] == 'zuul':
|
||||
root = jobdir_playbook.addRole()
|
||||
self.prepareZuulRole(jobdir_playbook, role, args, root)
|
||||
role_info = jobdir_playbook.addRole()
|
||||
self.prepareZuulRole(jobdir_playbook, role, args, role_info)
|
||||
|
||||
def findRole(self, path, trusted=False):
|
||||
d = os.path.join(path, 'tasks')
|
||||
@@ -2197,7 +2244,7 @@ class AnsibleJob(object):
|
||||
# It is neither a bare role, nor a collection of roles
|
||||
raise RoleNotFoundError("Unable to find role in %s" % (path,))
|
||||
|
||||
def prepareZuulRole(self, jobdir_playbook, role, args, root):
|
||||
def prepareZuulRole(self, jobdir_playbook, role, args, role_info):
|
||||
self.log.debug("Prepare zuul role for %s" % (role,))
|
||||
# Check out the role repo if needed
|
||||
source = self.executor_server.connections.getSource(
|
||||
@@ -2214,6 +2261,8 @@ class AnsibleJob(object):
|
||||
branch = jobdir_playbook.branch
|
||||
self.log.debug("Role project is playbook project, "
|
||||
"using playbook branch %s", branch)
|
||||
role_info.checkout_description = 'playbook branch'
|
||||
role_info.checkout = branch
|
||||
else:
|
||||
# Find if the project is one of the job-specified projects.
|
||||
# If it is, we can honor the project checkout-override options.
|
||||
@@ -2233,6 +2282,8 @@ class AnsibleJob(object):
|
||||
args_project.get('override_checkout'),
|
||||
role['project_default_branch'])
|
||||
self.log.debug("Role using %s %s", selected_desc, branch)
|
||||
role_info.checkout_description = selected_desc
|
||||
role_info.checkout = branch
|
||||
|
||||
if not jobdir_playbook.trusted:
|
||||
path = self.checkoutUntrustedProject(project, branch, args)
|
||||
@@ -2242,12 +2293,14 @@ class AnsibleJob(object):
|
||||
# The name of the symlink is the requested name of the role
|
||||
# (which may be the repo name or may be something else; this
|
||||
# can come into play if this is a bare role).
|
||||
link = os.path.join(root, name)
|
||||
link = os.path.join(role_info.root, name)
|
||||
link = os.path.realpath(link)
|
||||
if not link.startswith(os.path.realpath(root)):
|
||||
if not link.startswith(os.path.realpath(role_info.root)):
|
||||
raise ExecutorError("Invalid role name %s" % name)
|
||||
os.symlink(path, link)
|
||||
|
||||
role_info.link_name = link
|
||||
role_info.link_target = path
|
||||
try:
|
||||
role_path = self.findRole(link, trusted=jobdir_playbook.trusted)
|
||||
except RoleNotFoundError:
|
||||
@@ -2263,7 +2316,8 @@ class AnsibleJob(object):
|
||||
raise
|
||||
if role_path is None:
|
||||
# In the case of a bare role, add the containing directory
|
||||
role_path = root
|
||||
role_path = role_info.root
|
||||
role_info.role_path = role_path
|
||||
self.log.debug("Adding role path %s", role_path)
|
||||
jobdir_playbook.roles_path.append(role_path)
|
||||
|
||||
@@ -2411,6 +2465,27 @@ class AnsibleJob(object):
|
||||
result_data_file=self.jobdir.result_data_file,
|
||||
inventory_file=self.jobdir.inventory)
|
||||
|
||||
# Add playbook_context info
|
||||
zuul_vars['playbook_context'] = dict(
|
||||
playbook_projects={},
|
||||
playbooks=[],
|
||||
)
|
||||
strip = len(self.jobdir.root) + 1
|
||||
for pi in self.jobdir.trusted_projects.values():
|
||||
root = os.path.join(pi.root[strip:], pi.canonical_name)
|
||||
zuul_vars['playbook_context']['playbook_projects'][
|
||||
root] = pi.toDict()
|
||||
for pi in self.jobdir.untrusted_projects.values():
|
||||
root = os.path.join(pi.root[strip:], pi.canonical_name)
|
||||
zuul_vars['playbook_context']['playbook_projects'][
|
||||
root] = pi.toDict()
|
||||
for pb in self.jobdir.playbooks:
|
||||
zuul_vars['playbook_context']['playbooks'].append(dict(
|
||||
path=pb.path[strip:],
|
||||
roles=[ri.toDict(self.jobdir.root) for ri in pb.roles
|
||||
if ri.role_path is not None],
|
||||
))
|
||||
|
||||
with open(self.jobdir.zuul_vars, 'w') as zuul_vars_yaml:
|
||||
zuul_vars_yaml.write(
|
||||
yaml.safe_dump({'zuul': zuul_vars}, default_flow_style=False))
|
||||
|
||||
Reference in New Issue
Block a user