Allow use of aliases defined previously inside included files
Anchors and aliases were expanded internally within JJB's yaml loading calls so they were limited to individual documents. Now, included files will have access to aliases of anchors already defined at previously processed files. Example: - default: name: default-timeout-wrapper timeout: &timeout fail: true elastic-percentage: 150 elastic-default-timeout: 90 type: elastic - wrapper: !include include002_1.yaml.inc Previously was not possible to use '*timeout' alias inside include002_1.yaml.inc file Closes-Story: 2000173 Change-Id: Ic031ddbb0310bd11748183fbde9502735c3b7169
This commit is contained in:
parent
6c6370bbff
commit
1191dcfccf
@ -319,9 +319,8 @@ For example:
|
||||
|
||||
|
||||
The `anchors and aliases`_ are expanded internally within JJB's yaml loading
|
||||
calls, and are limited to individual documents. That means you use the same
|
||||
anchor name in separate files without collisions, but also means that you must
|
||||
define the anchor in the same file that you intend to reference it.
|
||||
calls and are not limited to individual documents. That means you can't use
|
||||
the same anchor name in included files without collisions.
|
||||
|
||||
A simple example can be seen in the specs `full length example`_ with the
|
||||
following being more representative of usage within JJB:
|
||||
|
@ -129,7 +129,31 @@ class OrderedConstructor(BaseConstructor):
|
||||
data.update(mapping)
|
||||
|
||||
|
||||
class LocalLoader(OrderedConstructor, yaml.Loader):
|
||||
class LocalAnchorLoader(yaml.Loader):
|
||||
"""Subclass for yaml.Loader which keeps Alias between calls"""
|
||||
anchors = {}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LocalAnchorLoader, self).__init__(*args, **kwargs)
|
||||
self.anchors = LocalAnchorLoader.anchors
|
||||
|
||||
@classmethod
|
||||
def reset_anchors(cls):
|
||||
cls.anchors = {}
|
||||
|
||||
# override the default composer to skip resetting the anchors at the
|
||||
# end of the current document
|
||||
def compose_document(self):
|
||||
# Drop the DOCUMENT-START event.
|
||||
self.get_event()
|
||||
# Compose the root node.
|
||||
node = self.compose_node(None, None)
|
||||
# Drop the DOCUMENT-END event.
|
||||
self.get_event()
|
||||
return node
|
||||
|
||||
|
||||
class LocalLoader(OrderedConstructor, LocalAnchorLoader):
|
||||
"""Subclass for yaml.Loader which handles the local tags 'include',
|
||||
'include-raw' and 'include-raw-escaped' to specify a file to include data
|
||||
from and whether to parse it as additional yaml, treat it as a data blob
|
||||
@ -228,4 +252,5 @@ class LocalLoader(OrderedConstructor, yaml.Loader):
|
||||
|
||||
|
||||
def load(stream, **kwargs):
|
||||
LocalAnchorLoader.reset_anchors()
|
||||
return yaml.load(stream, functools.partial(LocalLoader, **kwargs))
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
import os
|
||||
from testtools import ExpectedException
|
||||
from testtools.matchers import MismatchError
|
||||
from testtools import TestCase
|
||||
from testscenarios.testcase import TestWithScenarios
|
||||
from yaml.composer import ComposerError
|
||||
|
||||
from jenkins_jobs import builder
|
||||
from tests.base import get_scenarios, JsonTestCase, YamlTestCase
|
||||
@ -40,7 +40,8 @@ class TestCaseLocalYamlInclude(TestWithScenarios, TestCase, JsonTestCase):
|
||||
def test_yaml_snippet(self):
|
||||
|
||||
if os.path.basename(self.in_filename).startswith("exception_"):
|
||||
with ExpectedException(MismatchError):
|
||||
with ExpectedException(ComposerError,
|
||||
"^found duplicate anchor .*"):
|
||||
super(TestCaseLocalYamlInclude, self).test_yaml_snippet()
|
||||
else:
|
||||
super(TestCaseLocalYamlInclude, self).test_yaml_snippet()
|
||||
|
24
tests/yamlparser/fixtures/include002.xml
Normal file
24
tests/yamlparser/fixtures/include002.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?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/>
|
||||
<scm class="hudson.scm.NullSCM"/>
|
||||
<builders/>
|
||||
<publishers/>
|
||||
<buildWrappers>
|
||||
<hudson.plugins.build__timeout.BuildTimeoutWrapper>
|
||||
<timeoutMinutes>3</timeoutMinutes>
|
||||
<failBuild>true</failBuild>
|
||||
<writingDescription>false</writingDescription>
|
||||
<timeoutPercentage>150</timeoutPercentage>
|
||||
<timeoutMinutesElasticDefault>90</timeoutMinutesElasticDefault>
|
||||
<timeoutType>elastic</timeoutType>
|
||||
</hudson.plugins.build__timeout.BuildTimeoutWrapper>
|
||||
</buildWrappers>
|
||||
</project>
|
16
tests/yamlparser/fixtures/include002.yaml
Normal file
16
tests/yamlparser/fixtures/include002.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
# vim: sw=4 ts=4 et
|
||||
- default:
|
||||
name: default-timeout-wrapper
|
||||
timeout: &timeout
|
||||
fail: true
|
||||
elastic-percentage: 150
|
||||
elastic-default-timeout: 90
|
||||
type: elastic
|
||||
|
||||
# include that uses timeout alias
|
||||
- wrapper: !include include002_1.yaml.inc
|
||||
|
||||
- job:
|
||||
name: test-job-1
|
||||
wrappers:
|
||||
!include include002.yaml.inc
|
1
tests/yamlparser/fixtures/include002.yaml.inc
Normal file
1
tests/yamlparser/fixtures/include002.yaml.inc
Normal file
@ -0,0 +1 @@
|
||||
- timeout-wrapper
|
3
tests/yamlparser/fixtures/include002_1.yaml.inc
Normal file
3
tests/yamlparser/fixtures/include002_1.yaml.inc
Normal file
@ -0,0 +1,3 @@
|
||||
name: timeout-wrapper
|
||||
wrappers:
|
||||
- timeout: *timeout
|
Loading…
Reference in New Issue
Block a user