diff --git a/jenkins_jobs/local_yaml.py b/jenkins_jobs/local_yaml.py index c49393d65..493dac079 100644 --- a/jenkins_jobs/local_yaml.py +++ b/jenkins_jobs/local_yaml.py @@ -18,6 +18,52 @@ """Custom application specific yamls tags are supported to provide enhancements when reading yaml configuration. +Action Tags +^^^^^^^^^^^ + +These allow manipulation of data being stored in one layout in the source +yaml for convenience and/or clarity, to another format to be processed by +the targeted module instead of requiring all modules in JJB being capable +of supporting multiple input formats. + +The tag ``!join:`` will treat the first element of the following list as +the delimiter to use, when joining the remaining elements into a string +and returning a single string to be consumed by the specified module option. + +This allows users to maintain elements of data in a list structure for ease +of review/maintenance, and have the yaml parser convert it to a string for +consumption as any argument for modules. The main expected use case is to +allow for generic plugin data such as shell properties to be populated from +a list construct which the yaml parser converts to a single string, instead +of trying to support this within the module code which would require a +templating engine similar to Jinja. + +Generic Example: + + .. literalinclude:: /../../tests/localyaml/fixtures/joinlists.yaml + + +Environment Inject: + + .. literalinclude:: /../../tests/yamlparser/fixtures/string_join.yaml + + +While this mechanism can also be used items where delimiters are supported by +the module, that should be considered a bug that the existing code doesn't +handle being provided a list and delimiter to perform the correct conversion +for you. Should you discover a module that takes arguments with delimiters and +the existing JJB codebase does not handle accepting lists, then this can be +used as a temporary solution in place of using very long strings: + +Extended Params Example: + + .. literalinclude:: + /../../tests/parameters/fixtures/extended-choice-param-full.yaml + + +Inclusion Tags +^^^^^^^^^^^^^^ + These allow inclusion of arbitrary files as a method of having blocks of data managed separately to the yaml job configurations. A specific usage of this is inlining scripts contained in separate files, although such tags may also be @@ -327,6 +373,25 @@ class J2String(BaseYAMLObject): return Jinja2Loader(node.value, loader.search_path) +class YamlListJoin(BaseYAMLObject): + yaml_tag = u'!join:' + + @classmethod + def from_yaml(cls, loader, node): + if isinstance(node, yaml.SequenceNode): + delimiter = node.value[0].value + if not isinstance(node.value[1], yaml.SequenceNode): + raise yaml.constructor.ConstructorError( + None, None, "expected sequence node for join data, but " + "found %s" % node.value[1].id, node.start_mark) + + return delimiter.join((v.value for v in node.value[1].value)) + else: + raise yaml.constructor.ConstructorError( + None, None, "expected sequence node, but found %s" % node.id, + node.start_mark) + + class YamlInclude(BaseYAMLObject): yaml_tag = u'!include:' diff --git a/tests/localyaml/fixtures/joinlists.json b/tests/localyaml/fixtures/joinlists.json new file mode 100644 index 000000000..8702d17f7 --- /dev/null +++ b/tests/localyaml/fixtures/joinlists.json @@ -0,0 +1,8 @@ +[ + { + "string-with-comma": "item1,item2,item3" + }, + { + "string-with-space": "item1 item2 item3" + } +] diff --git a/tests/localyaml/fixtures/joinlists.yaml b/tests/localyaml/fixtures/joinlists.yaml new file mode 100644 index 000000000..c970df50d --- /dev/null +++ b/tests/localyaml/fixtures/joinlists.yaml @@ -0,0 +1,13 @@ +- string-with-comma: !join: + - ',' + - + - item1 + - item2 + - item3 + +- string-with-space: !join: + - ' ' + - + - item1 + - item2 + - item3 diff --git a/tests/parameters/fixtures/extended-choice-param-full.xml b/tests/parameters/fixtures/extended-choice-param-full.xml index f3716a90c..40560c999 100644 --- a/tests/parameters/fixtures/extended-choice-param-full.xml +++ b/tests/parameters/fixtures/extended-choice-param-full.xml @@ -22,6 +22,44 @@ + + OPTIONS_CHECKBOX + + OptionA,OptionB,OptionC + 2 + , + false + + + PT_CHECKBOX + + + + + + + + + + + MULTISELECTOPTIONS + Available options + foo|bar|select + 2 + | + true + foo + + PT_MULTI_SELECT + + key + + + + + + + diff --git a/tests/parameters/fixtures/extended-choice-param-full.yaml b/tests/parameters/fixtures/extended-choice-param-full.yaml index 9d2b0d37f..55a1f5ee6 100644 --- a/tests/parameters/fixtures/extended-choice-param-full.yaml +++ b/tests/parameters/fixtures/extended-choice-param-full.yaml @@ -12,3 +12,28 @@ parameters: default-value: foo default-property-file: /home/property.prop default-property-key: fookey + - extended-choice: + name: OPTIONS_CHECKBOX + type: checkbox + value: !join: + - ',' + - + - OptionA + - OptionB + - OptionC + visible-items: 2 + - extended-choice: + name: MULTISELECTOPTIONS + description: "Available options" + property-key: key + quote-value: true + type: multi-select + value: !join: + - '|' + - + - foo + - bar + - select + visible-items: 2 + multi-select-delimiter: '|' + default-value: foo diff --git a/tests/yamlparser/fixtures/string_join.xml b/tests/yamlparser/fixtures/string_join.xml new file mode 100644 index 000000000..2abfaa2d7 --- /dev/null +++ b/tests/yamlparser/fixtures/string_join.xml @@ -0,0 +1,69 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + true + + + + FILE_LIST=/path/to/file1,/path/to/file2,/path/to/file3,/path/to/file4,/path/to/file5,/path/to/file6,/path/to/file7,/path/to/file8,/path/to/file9,/path/to/file10,/path/to/file11,/path/to/file12,/path/to/file13,/path/to/file14,/path/to/file15,/path/to/file16,/path/to/file17,/path/to/file18,/path/to/file19,/path/to/file20 + + false + + true + true + true + false + + + + + + echo "Template name: string-join-data-{name}" +echo "Data to be processed:" +echo "${INPUT_DATA}" + + + + + + + + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + true + + + + FILE_LIST=/another/different/path/to/file1,/another/different/path/to/file2,/another/different/path/to/file3,/another/different/path/to/file4,/another/different/path/to/file5,/another/different/path/to/file6,/another/different/path/to/file7,/another/different/path/to/file8,/another/different/path/to/file9,/another/different/path/to/file10,/another/different/path/to/file11,/another/different/path/to/file12,/another/different/path/to/file13,/another/different/path/to/file14,/another/different/path/to/file15,/another/different/path/to/file16,/another/different/path/to/file17,/another/different/path/to/file18,/another/different/path/to/file19,/another/different/path/to/file20 + + false + + true + true + true + false + + + + + + echo "Template name: string-join-data-{name}" +echo "Data to be processed:" +echo "${INPUT_DATA}" + + + + + + diff --git a/tests/yamlparser/fixtures/string_join.yaml b/tests/yamlparser/fixtures/string_join.yaml new file mode 100644 index 000000000..0288d4b21 --- /dev/null +++ b/tests/yamlparser/fixtures/string_join.yaml @@ -0,0 +1,66 @@ +- project: + name: string_join_example + jobs: + - 'string-join-data-{name}': + name: set1 + files: !join: + - ',' + - + - /path/to/file1 + - /path/to/file2 + - /path/to/file3 + - /path/to/file4 + - /path/to/file5 + - /path/to/file6 + - /path/to/file7 + - /path/to/file8 + - /path/to/file9 + - /path/to/file10 + - /path/to/file11 + - /path/to/file12 + - /path/to/file13 + - /path/to/file14 + - /path/to/file15 + - /path/to/file16 + - /path/to/file17 + - /path/to/file18 + - /path/to/file19 + - /path/to/file20 + - 'string-join-data-{name}': + name: set2 + files: !join: + - ',' + - + - /another/different/path/to/file1 + - /another/different/path/to/file2 + - /another/different/path/to/file3 + - /another/different/path/to/file4 + - /another/different/path/to/file5 + - /another/different/path/to/file6 + - /another/different/path/to/file7 + - /another/different/path/to/file8 + - /another/different/path/to/file9 + - /another/different/path/to/file10 + - /another/different/path/to/file11 + - /another/different/path/to/file12 + - /another/different/path/to/file13 + - /another/different/path/to/file14 + - /another/different/path/to/file15 + - /another/different/path/to/file16 + - /another/different/path/to/file17 + - /another/different/path/to/file18 + - /another/different/path/to/file19 + - /another/different/path/to/file20 + +- job-template: + name: 'string-join-data-{name}' + properties: + - inject: + keep-system-variables: true + properties-content: | + FILE_LIST={files} + builders: + - shell: | + echo "Template name: {template-name}" + echo "Data to be processed:" + echo "${{INPUT_DATA}}"