From 0cafeba626a6e945cd87394a4a928777c5d5173a Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Fri, 4 Dec 2015 18:19:32 +0000 Subject: [PATCH] Order component retrieval to favour user defined Prefer user defined macros over inbuilt entry points, as JJB may accidentally use a name that has already been used by an end-user to define a custom macro. Warn users when they have a macro defined that masks an in-built component to avoid accidentally changing XML generated with new releases. Change-Id: I6cae62d7cc40be6c4a5636a74f151fcce4cdd856 --- jenkins_jobs/registry.py | 32 +++++++++++-------- .../fixtures/mask_internal_component.xml | 19 +++++++++++ .../fixtures/mask_internal_component.yaml | 11 +++++++ 3 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 tests/yamlparser/fixtures/mask_internal_component.xml create mode 100644 tests/yamlparser/fixtures/mask_internal_component.yaml diff --git a/jenkins_jobs/registry.py b/jenkins_jobs/registry.py index 3c06beed8..6dddc567b 100644 --- a/jenkins_jobs/registry.py +++ b/jenkins_jobs/registry.py @@ -223,20 +223,24 @@ class ModuleRegistry(object): logger.debug("Cached entry point group %s = %s", component_list_type, eps) - if name in eps: + # check for macro first + component = parser.data.get(component_type, {}).get(name) + if component: + if name in eps: + logger.warn("You have a macro ('%s') defined for '%s' " + "component type that is masking an inbuilt " + "definition" % (name, component_type)) + + for b in component[component_list_type]: + # 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, + parser, xml_parent, b, component_data) + elif name in eps: func = eps[name].load() func(parser, xml_parent, component_data) else: - # Otherwise, see if it's defined as a macro - component = parser.data.get(component_type, {}).get(name) - if component: - for b in component[component_list_type]: - # 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, - parser, xml_parent, b, component_data) - else: - raise JenkinsJobsException("Unknown entry point or macro '{0}'" - " for component type: '{1}'.". - format(name, component_type)) + raise JenkinsJobsException("Unknown entry point or macro '{0}' " + "for component type: '{1}'.". + format(name, component_type)) diff --git a/tests/yamlparser/fixtures/mask_internal_component.xml b/tests/yamlparser/fixtures/mask_internal_component.xml new file mode 100644 index 000000000..5f648396a --- /dev/null +++ b/tests/yamlparser/fixtures/mask_internal_component.xml @@ -0,0 +1,19 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + true + + + + + bash /opt/bin/run_python.sh + + + + + diff --git a/tests/yamlparser/fixtures/mask_internal_component.yaml b/tests/yamlparser/fixtures/mask_internal_component.yaml new file mode 100644 index 000000000..a5e15a38e --- /dev/null +++ b/tests/yamlparser/fixtures/mask_internal_component.yaml @@ -0,0 +1,11 @@ +- builder: + name: python + builders: + - shell: + bash {file} + +- job: + name: mask-internal-module + builders: + - python: + file: '/opt/bin/run_python.sh'