Fix 'authorization' property one more time
Due to the fact how dispatching works the 'authorization' property handler was not always invoked through Properties.gen_xml(), leading to a bug and an invalid test case: project-with-auth-properties.(yaml/xml) This change pushes the logic for determining if the object is a folder/multi-branch project from Properties.gen_xml() to the authorization() function itself. For that to work the authorization() function needed access to the top-level job object, which is now conditionally passed to each dispatched function as a keyword argument, if the function takes 'job_data' argument. Note that taking this argument is completely optional so no changes were required in other handlers. In the future the same approach could be taken to eliminate the hacks for 'uno-choice' in Parameters.gen_xml(). Additionally ModuleRegistry.dispatch() now merges the top-level job object with any template data before deep-formatting, so that job-level properties are now available in Jinja templates. A very nice use case is in project-with-auth-j2-yaml.yaml test case. Change-Id: I9a49de74055cd9acfdc87dbad1fc454548643e8f
This commit is contained in:
parent
575b0520f1
commit
c0866c56b9
@ -527,7 +527,7 @@ def authenticated_build(registry, xml_parent, data):
|
||||
).text = "hudson.model.Item.Build:authenticated"
|
||||
|
||||
|
||||
def authorization(registry, xml_parent, data):
|
||||
def authorization(registry, xml_parent, data, job_data):
|
||||
"""yaml: authorization
|
||||
Specifies an authorization matrix
|
||||
|
||||
@ -564,8 +564,7 @@ def authorization(registry, xml_parent, data):
|
||||
:language: yaml
|
||||
"""
|
||||
|
||||
# check if it's a folder or a job
|
||||
is_a_folder = data.pop("_is_a_folder", None) if data else False
|
||||
is_a_folder = job_data.get("project-type") in ("folder", "multibranch")
|
||||
|
||||
credentials = "com.cloudbees.plugins.credentials.CredentialsProvider."
|
||||
ownership = "com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin."
|
||||
@ -1434,15 +1433,4 @@ class Properties(jenkins_jobs.modules.base.Base):
|
||||
properties = XML.SubElement(xml_parent, "properties")
|
||||
|
||||
for prop in data.get("properties", []):
|
||||
# Pass a flag for folder permissions to the authorization method
|
||||
if next(iter(prop)) == "authorization":
|
||||
# Only projects are placed in folders
|
||||
if "project-type" in data:
|
||||
if data["project-type"] in ("folder", "multibranch"):
|
||||
prop["authorization"]["_is_a_folder"] = True
|
||||
else:
|
||||
prop["authorization"]["_is_a_folder"] = False
|
||||
else:
|
||||
prop["authorization"]["_is_a_folder"] = False
|
||||
|
||||
self.registry.dispatch("property", properties, prop)
|
||||
self.registry.dispatch("property", properties, prop, job_data=data)
|
||||
|
@ -15,12 +15,15 @@
|
||||
|
||||
# Manage Jenkins plugin module registry.
|
||||
|
||||
import inspect
|
||||
import logging
|
||||
import operator
|
||||
import pkg_resources
|
||||
import re
|
||||
import types
|
||||
|
||||
from six import PY2
|
||||
|
||||
from jenkins_jobs.errors import JenkinsJobsException
|
||||
from jenkins_jobs.formatter import deep_format
|
||||
from jenkins_jobs.local_yaml import Jinja2Loader
|
||||
@ -29,6 +32,8 @@ __all__ = ["ModuleRegistry"]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
getargspec = inspect.getargspec if PY2 else inspect.getfullargspec
|
||||
|
||||
|
||||
class ModuleRegistry(object):
|
||||
_entry_points_cache = {}
|
||||
@ -87,6 +92,14 @@ class ModuleRegistry(object):
|
||||
|
||||
return plugins_info_dict
|
||||
|
||||
@staticmethod
|
||||
def _filter_kwargs(func, **kwargs):
|
||||
arg_spec = getargspec(func)
|
||||
for name in list(kwargs.keys()):
|
||||
if name not in arg_spec.args:
|
||||
del kwargs[name]
|
||||
return kwargs
|
||||
|
||||
def get_plugin_info(self, plugin_name):
|
||||
"""Provide information about plugins within a module's impl of Base.gen_xml.
|
||||
|
||||
@ -141,7 +154,9 @@ class ModuleRegistry(object):
|
||||
|
||||
return component_list_type
|
||||
|
||||
def dispatch(self, component_type, xml_parent, component, template_data={}):
|
||||
def dispatch(
|
||||
self, component_type, xml_parent, component, template_data={}, job_data=None
|
||||
):
|
||||
"""This is a method that you can call from your implementation of
|
||||
Base.gen_xml or component. It allows modules to define a type
|
||||
of component, and benefit from extensibility via Python
|
||||
@ -151,8 +166,10 @@ class ModuleRegistry(object):
|
||||
(e.g., `builder`)
|
||||
:arg YAMLParser parser: the global YAML Parser
|
||||
:arg Element xml_parent: the parent XML element
|
||||
:arg component: component definition
|
||||
:arg dict template_data: values that should be interpolated into
|
||||
the component definition
|
||||
:arg dict job_data: full job definition
|
||||
|
||||
See :py:class:`jenkins_jobs.modules.base.Base` for how to register
|
||||
components of a module.
|
||||
@ -173,13 +190,16 @@ class ModuleRegistry(object):
|
||||
# The component is a singleton dictionary of name: dict(args)
|
||||
name, component_data = next(iter(component.items()))
|
||||
if template_data or isinstance(component_data, Jinja2Loader):
|
||||
paramdict = {}
|
||||
paramdict.update(template_data)
|
||||
paramdict.update(job_data or {})
|
||||
# Template data contains values that should be interpolated
|
||||
# into the component definition. To handle Jinja2 templates
|
||||
# that don't contain any variables, we also deep format those.
|
||||
try:
|
||||
component_data = deep_format(
|
||||
component_data,
|
||||
template_data,
|
||||
paramdict,
|
||||
self.jjb_config.yamlparser["allow_empty_variables"],
|
||||
)
|
||||
except Exception:
|
||||
@ -280,10 +300,13 @@ class ModuleRegistry(object):
|
||||
# Pass component_data in as template data to this function
|
||||
# so that if the macro is invoked with arguments,
|
||||
# the arguments are interpolated into the real defn.
|
||||
self.dispatch(component_type, xml_parent, b, component_data)
|
||||
self.dispatch(
|
||||
component_type, xml_parent, b, component_data, job_data=job_data
|
||||
)
|
||||
elif name in eps:
|
||||
func = eps[name]
|
||||
func(self, xml_parent, component_data)
|
||||
kwargs = self._filter_kwargs(func, job_data=job_data)
|
||||
func(self, xml_parent, component_data, **kwargs)
|
||||
else:
|
||||
raise JenkinsJobsException(
|
||||
"Unknown entry point or macro '{0}' "
|
||||
|
28
tests/yamlparser/fixtures/project-with-auth-j2-yaml.xml
Normal file
28
tests/yamlparser/fixtures/project-with-auth-j2-yaml.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
<actions/>
|
||||
<description><!-- Managed by Jenkins Job Builder --></description>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
||||
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
||||
<concurrentBuild>false</concurrentBuild>
|
||||
<canRoam>true</canRoam>
|
||||
<properties>
|
||||
<hudson.security.AuthorizationMatrixProperty>
|
||||
<inheritanceStrategy class="org.jenkinsci.plugins.matrixauth.inheritance.InheritParentStrategy"/>
|
||||
<permission>hudson.model.Item.Build:john</permission>
|
||||
<permission>hudson.model.Item.Cancel:john</permission>
|
||||
<permission>hudson.model.Item.Read:john</permission>
|
||||
<permission>hudson.model.Item.Build:megan</permission>
|
||||
<permission>hudson.model.Item.Cancel:megan</permission>
|
||||
<permission>hudson.model.Item.Read:megan</permission>
|
||||
<permission>hudson.model.Item.Build:steve</permission>
|
||||
<permission>hudson.model.Item.Cancel:steve</permission>
|
||||
<permission>hudson.model.Item.Read:steve</permission>
|
||||
</hudson.security.AuthorizationMatrixProperty>
|
||||
</properties>
|
||||
<scm class="hudson.scm.NullSCM"/>
|
||||
<builders/>
|
||||
<publishers/>
|
||||
<buildWrappers/>
|
||||
</project>
|
14
tests/yamlparser/fixtures/project-with-auth-j2-yaml.yaml
Normal file
14
tests/yamlparser/fixtures/project-with-auth-j2-yaml.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
- job:
|
||||
name: test
|
||||
authorized_people:
|
||||
- john
|
||||
- megan
|
||||
- steve
|
||||
properties:
|
||||
- authorization: !j2-yaml: |
|
||||
{% for user in authorized_people %}
|
||||
{{ user }}:
|
||||
- job-build
|
||||
- job-cancel
|
||||
- job-read
|
||||
{% endfor %}
|
@ -13,10 +13,10 @@
|
||||
<concurrentBuild>false</concurrentBuild>
|
||||
<canRoam>true</canRoam>
|
||||
<properties>
|
||||
<hudson.security.AuthorizationMatrixProperty>
|
||||
<com.cloudbees.hudson.plugins.folder.properties.AuthorizationMatrixProperty>
|
||||
<inheritanceStrategy class="org.jenkinsci.plugins.matrixauth.inheritance.InheritParentStrategy"/>
|
||||
<permission>hudson.model.Item.Build:auser</permission>
|
||||
</hudson.security.AuthorizationMatrixProperty>
|
||||
</com.cloudbees.hudson.plugins.folder.properties.AuthorizationMatrixProperty>
|
||||
</properties>
|
||||
<scm class="hudson.scm.NullSCM"/>
|
||||
<publishers/>
|
||||
|
Loading…
Reference in New Issue
Block a user