Merge "Add job_builder option to load extra modules for jinja2 filters"
This commit is contained in:
commit
6bb50811b4
@ -72,6 +72,14 @@ job_builder section
|
|||||||
``--jobs-only`` or ``--views-only`` CLI options.
|
``--jobs-only`` or ``--views-only`` CLI options.
|
||||||
(Valid options: jobs, views, all)
|
(Valid options: jobs, views, all)
|
||||||
|
|
||||||
|
**filter_modules**
|
||||||
|
(Optional) A space-separated set of strings which of names of additional
|
||||||
|
modules to load Jinja2 filters from when templating YAML objects. Note
|
||||||
|
that the modules must be in the Python path. To learn about writing
|
||||||
|
custom Jinja2 filters, please see the `Jinja2 Documentation`__
|
||||||
|
|
||||||
|
__ https://jinja.palletsprojects.com/en/latest/api/#writing-filters
|
||||||
|
|
||||||
jenkins section
|
jenkins section
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ exclude=.*
|
|||||||
allow_duplicates=False
|
allow_duplicates=False
|
||||||
allow_empty_variables=False
|
allow_empty_variables=False
|
||||||
retain_anchors=False
|
retain_anchors=False
|
||||||
|
filter_modules=
|
||||||
|
|
||||||
# other named sections could be used in addition to the implicit [jenkins]
|
# other named sections could be used in addition to the implicit [jenkins]
|
||||||
# if you have multiple jenkins servers.
|
# if you have multiple jenkins servers.
|
||||||
@ -302,6 +303,17 @@ class JJBConfig(object):
|
|||||||
path = config.get("job_builder", "include_path").split(":")
|
path = config.get("job_builder", "include_path").split(":")
|
||||||
self.yamlparser["include_path"] = path
|
self.yamlparser["include_path"] = path
|
||||||
|
|
||||||
|
# Extra modules to load for jinja2 filters
|
||||||
|
filter_modules = []
|
||||||
|
if (
|
||||||
|
config
|
||||||
|
and config.has_section("job_builder")
|
||||||
|
and config.has_option("job_builder", "filter_modules")
|
||||||
|
and config.get("job_builder", "filter_modules")
|
||||||
|
):
|
||||||
|
filter_modules = config.get("job_builder", "filter_modules").split(" ")
|
||||||
|
self.yamlparser["filter_modules"] = filter_modules
|
||||||
|
|
||||||
# allow duplicates?
|
# allow duplicates?
|
||||||
allow_duplicates = False
|
allow_duplicates = False
|
||||||
if config and config.has_option("job_builder", "allow_duplicates"):
|
if config and config.has_option("job_builder", "allow_duplicates"):
|
||||||
|
@ -170,6 +170,7 @@ Examples:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
import sys
|
import sys
|
||||||
@ -221,6 +222,7 @@ class BaseYamlObject(metaclass=abc.ABCMeta):
|
|||||||
if loader.source_dir:
|
if loader.source_dir:
|
||||||
# Loaded from a file, find includes beside it too.
|
# Loaded from a file, find includes beside it too.
|
||||||
self._search_path.append(loader.source_dir)
|
self._search_path.append(loader.source_dir)
|
||||||
|
self._filter_modules = jjb_config.yamlparser["filter_modules"].copy()
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
self._pos = pos
|
self._pos = pos
|
||||||
allow_empty = jjb_config.yamlparser["allow_empty_variables"]
|
allow_empty = jjb_config.yamlparser["allow_empty_variables"]
|
||||||
@ -255,10 +257,15 @@ class BaseYamlObject(metaclass=abc.ABCMeta):
|
|||||||
class J2BaseYamlObject(BaseYamlObject):
|
class J2BaseYamlObject(BaseYamlObject):
|
||||||
def __init__(self, jjb_config, loader, pos):
|
def __init__(self, jjb_config, loader, pos):
|
||||||
super().__init__(jjb_config, loader, pos)
|
super().__init__(jjb_config, loader, pos)
|
||||||
|
self._filters = {}
|
||||||
|
for module_name in self._filter_modules:
|
||||||
|
module = importlib.import_module(module_name)
|
||||||
|
self._filters.update(module.FILTERS)
|
||||||
self._jinja2_env = jinja2.Environment(
|
self._jinja2_env = jinja2.Environment(
|
||||||
loader=jinja2.FileSystemLoader(self._search_path),
|
loader=jinja2.FileSystemLoader(self._search_path),
|
||||||
undefined=jinja2.StrictUndefined,
|
undefined=jinja2.StrictUndefined,
|
||||||
)
|
)
|
||||||
|
self._jinja2_env.filters.update(self._filters)
|
||||||
|
|
||||||
def _render_template(self, pos, template_text, template, params):
|
def _render_template(self, pos, template_text, template, params):
|
||||||
try:
|
try:
|
||||||
|
2
tests/cmd/fixtures/cmd-003.conf
Normal file
2
tests/cmd/fixtures/cmd-003.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[job_builder]
|
||||||
|
filter_modules=my_filter my_other_filter
|
@ -175,3 +175,17 @@ def test_update_timeout_set(mocker, fixtures_dir):
|
|||||||
|
|
||||||
jjb_config = jenkins_mock.call_args[0][0]
|
jjb_config = jenkins_mock.call_args[0][0]
|
||||||
assert jjb_config.jenkins["timeout"] == 0.2
|
assert jjb_config.jenkins["timeout"] == 0.2
|
||||||
|
|
||||||
|
|
||||||
|
def test_filter_modules_set(mocker, fixtures_dir):
|
||||||
|
"""
|
||||||
|
Check that customs filters modules are set.
|
||||||
|
|
||||||
|
Test that the filter_modules option is a non-empty list.
|
||||||
|
"""
|
||||||
|
config_file = fixtures_dir / "cmd-003.conf"
|
||||||
|
args = ["--conf", str(config_file), "test", "foo"]
|
||||||
|
jenkins_jobs = entry.JenkinsJobs(args)
|
||||||
|
|
||||||
|
jjb_config = jenkins_jobs.jjb_config
|
||||||
|
assert jjb_config.yamlparser["filter_modules"] == ["my_filter", "my_other_filter"]
|
||||||
|
2
tests/yamlparser/job_fixtures/filter_modules.conf
Normal file
2
tests/yamlparser/job_fixtures/filter_modules.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[job_builder]
|
||||||
|
filter_modules=myfilter
|
19
tests/yamlparser/job_fixtures/filter_modules.xml
Normal file
19
tests/yamlparser/job_fixtures/filter_modules.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?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>
|
||||||
|
<hudson.tasks.Shell>
|
||||||
|
<command>my_filter says "hello"</command>
|
||||||
|
</hudson.tasks.Shell>
|
||||||
|
</builders>
|
||||||
|
<publishers/>
|
||||||
|
<buildWrappers/>
|
||||||
|
</project>
|
11
tests/yamlparser/job_fixtures/filter_modules.yaml
Normal file
11
tests/yamlparser/job_fixtures/filter_modules.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
- project:
|
||||||
|
name: filter_modules
|
||||||
|
jobs:
|
||||||
|
- 'filter_modules'
|
||||||
|
|
||||||
|
- job-template:
|
||||||
|
name: 'filter_modules'
|
||||||
|
builders:
|
||||||
|
- shell:
|
||||||
|
!j2: |
|
||||||
|
{{"hello"|my_filter}}
|
17
tests/yamlparser/job_fixtures/myfilter/__init__.py
Normal file
17
tests/yamlparser/job_fixtures/myfilter/__init__.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Example custom jinja2 filter
|
||||||
|
"""
|
||||||
|
|
||||||
|
import jinja2
|
||||||
|
|
||||||
|
|
||||||
|
@jinja2.pass_environment
|
||||||
|
def do_my_filter(env, data, skip_list_wrap=False):
|
||||||
|
return 'my_filter says "{}"'.format(data)
|
||||||
|
|
||||||
|
|
||||||
|
FILTERS = {
|
||||||
|
"my_filter": do_my_filter,
|
||||||
|
}
|
@ -18,6 +18,7 @@
|
|||||||
import os
|
import os
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -36,6 +37,9 @@ def scenario(request):
|
|||||||
|
|
||||||
|
|
||||||
def test_yaml_snippet(scenario, check_job):
|
def test_yaml_snippet(scenario, check_job):
|
||||||
|
old_path = sys.path
|
||||||
|
if str(fixtures_dir) not in sys.path:
|
||||||
|
sys.path.append(str(fixtures_dir))
|
||||||
# Some tests using config with 'include_path' expect JJB root to be current directory.
|
# Some tests using config with 'include_path' expect JJB root to be current directory.
|
||||||
os.chdir(Path(__file__).parent / "../..")
|
os.chdir(Path(__file__).parent / "../..")
|
||||||
if scenario.name.startswith("deprecated-"):
|
if scenario.name.startswith("deprecated-"):
|
||||||
@ -44,3 +48,4 @@ def test_yaml_snippet(scenario, check_job):
|
|||||||
assert "is deprecated" in str(record[0].message)
|
assert "is deprecated" in str(record[0].message)
|
||||||
else:
|
else:
|
||||||
check_job()
|
check_job()
|
||||||
|
sys.path = old_path
|
||||||
|
Loading…
x
Reference in New Issue
Block a user