diff --git a/doc/source/definition.rst b/doc/source/definition.rst
index 848f7198b..dc04ab680 100644
--- a/doc/source/definition.rst
+++ b/doc/source/definition.rst
@@ -261,6 +261,14 @@ For example:
.. literalinclude:: /../../tests/yamlparser/fixtures/yaml_anchor.yaml
+JJB also supports interpolation of parameters within parameters. This allows a
+little more flexibility when ordering template jobs as components in different
+projects and job groups.
+
+For example:
+
+.. literalinclude:: /../../tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml
+
Custom Yaml Tags
----------------
diff --git a/jenkins_jobs/builder.py b/jenkins_jobs/builder.py
index 2b006ea7a..280b70b11 100644
--- a/jenkins_jobs/builder.py
+++ b/jenkins_jobs/builder.py
@@ -209,12 +209,21 @@ class YamlParser(object):
return job
return self.applyDefaults(job)
- def applyDefaults(self, data):
+ def applyDefaults(self, data, override_dict=None):
+ if override_dict is None:
+ override_dict = {}
+
whichdefaults = data.get('defaults', 'global')
- defaults = self.data.get('defaults', {}).get(whichdefaults, {})
+ defaults = copy.deepcopy(self.data.get('defaults',
+ {}).get(whichdefaults, {}))
if defaults == {} and whichdefaults != 'global':
raise JenkinsJobsException("Unknown defaults set: '{0}'"
.format(whichdefaults))
+
+ for key in override_dict.keys():
+ if key in defaults.keys():
+ defaults[key] = override_dict[key]
+
newdata = {}
newdata.update(defaults)
newdata.update(data)
@@ -325,8 +334,11 @@ class YamlParser(object):
def expandYamlForTemplateJob(self, project, template, jobs_filter=None):
dimensions = []
+ # reject keys that are not useful during yaml expansion
+ for k in ['jobs']:
+ project.pop(k)
for (k, v) in project.items():
- if type(v) == list and k not in ['jobs']:
+ if type(v) == list:
dimensions.append(zip([k] * len(v), v))
# XXX somewhat hackish to ensure we actually have a single
# pass through the loop
@@ -335,7 +347,7 @@ class YamlParser(object):
checksums = set([])
for values in itertools.product(*dimensions):
params = copy.deepcopy(project)
- params = self.applyDefaults(params)
+ params = self.applyDefaults(params, template)
expanded_values = {}
for (k, v) in values:
@@ -347,6 +359,7 @@ class YamlParser(object):
expanded_values[k] = v
params.update(expanded_values)
+ params = deep_format(params, params)
expanded = deep_format(template, params)
# Keep track of the resulting expansions to avoid
diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation001.xml b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.xml
new file mode 100644
index 000000000..75c2046cc
--- /dev/null
+++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.xml
@@ -0,0 +1,16 @@
+
+
+
+ <!-- Managed by Jenkins Job Builder -->
+ false
+ experimental_foo
+ false
+ false
+ false
+ true
+
+
+
+
+
+
diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation001.yaml b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.yaml
new file mode 100644
index 000000000..c7fc1a56b
--- /dev/null
+++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.yaml
@@ -0,0 +1,13 @@
+- job-template:
+ name: '{value-stream}_{pipeline-type}'
+ display-name: '{value-stream}_{pipeline-type}'
+
+- project:
+ name: derp
+ jobs:
+ - '{value-stream}_{pipeline-type}':
+ pipeline-type: 'foo'
+
+- defaults:
+ name: 'global'
+ value-stream: 'experimental'
diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation002.xml b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.xml
new file mode 100644
index 000000000..bdab430fe
--- /dev/null
+++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.xml
@@ -0,0 +1,127 @@
+
+
+
+ <!-- Managed by Jenkins Job Builder -->
+ false
+ experimental p2 bar
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ ALWAYS
+ false
+
+
+
+
+
+
+
+
+
+
+ <!-- Managed by Jenkins Job Builder -->
+ false
+ experimental p2 foo
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+ false
+
+
+ experimental_p2_bar
+ ALWAYS
+ false
+
+
+
+
+
+
+
+
+
+
+ <!-- Managed by Jenkins Job Builder -->
+ false
+ production p1 bar
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+ false
+
+
+ production_p1_foo
+ ALWAYS
+ false
+
+
+
+
+
+
+
+
+
+
+ <!-- Managed by Jenkins Job Builder -->
+ false
+ production p1 foo
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ ALWAYS
+ false
+
+
+
+
+
+
diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml
new file mode 100644
index 000000000..380fbd9aa
--- /dev/null
+++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml
@@ -0,0 +1,47 @@
+- job-template:
+ name: '{value-stream}_{project-id}_foo'
+ display-name: '{value-stream} {project-id} foo'
+ publishers:
+ - trigger-parameterized-builds:
+ - project: '{downstream}'
+ current-parameters: False
+ condition: ALWAYS
+ git-revision: True
+
+- job-template:
+ name: '{value-stream}_{project-id}_bar'
+ display-name: '{value-stream} {project-id} bar'
+ publishers:
+ - trigger-parameterized-builds:
+ - project: '{downstream}'
+ current-parameters: False
+ condition: ALWAYS
+ git-revision: True
+
+- job-group:
+ name: 'pipeline2'
+ project-id: 'p2'
+ jobs:
+ - '{value-stream}_{project-id}_foo':
+ downstream: '{value-stream}_{project-id}_bar'
+ - '{value-stream}_{project-id}_bar':
+
+- job-group:
+ name: 'pipeline1'
+ project-id: 'p1'
+ jobs:
+ - '{value-stream}_{project-id}_bar':
+ downstream: '{value-stream}_{project-id}_foo'
+ - '{value-stream}_{project-id}_foo':
+
+- project:
+ name: derp
+ jobs:
+ - 'pipeline1':
+ value-stream: 'production'
+ - 'pipeline2':
+ value-stream: 'experimental'
+
+- defaults:
+ name: 'global'
+ downstream: ''