mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Migrate tests/unit/utils/test_templates.py
to pytest
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
This commit is contained in:
parent
32a7c51b40
commit
3f92d3f934
9 changed files with 435 additions and 468 deletions
0
tests/pytests/unit/utils/templates/__init__.py
Normal file
0
tests/pytests/unit/utils/templates/__init__.py
Normal file
9
tests/pytests/unit/utils/templates/conftest.py
Normal file
9
tests/pytests/unit/utils/templates/conftest.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def render_context():
|
||||
return {
|
||||
"opts": {"cachedir": "/D", "__cli": "salt"},
|
||||
"saltenv": None,
|
||||
}
|
47
tests/pytests/unit/utils/templates/test_cheetah.py
Normal file
47
tests/pytests/unit/utils/templates/test_cheetah.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
import pytest
|
||||
from salt.utils.templates import render_cheetah_tmpl
|
||||
|
||||
pytest.importorskip("Cheetah")
|
||||
|
||||
|
||||
def test_render_sanity(render_context):
|
||||
tmpl = """OK"""
|
||||
res = render_cheetah_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_evaluate(render_context):
|
||||
tmpl = """<%="OK"%>"""
|
||||
res = render_cheetah_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_evaluate_xml(render_context):
|
||||
tmpl = """
|
||||
<% if 1: %>
|
||||
OK
|
||||
<% pass %>
|
||||
"""
|
||||
res = render_cheetah_tmpl(tmpl, render_context)
|
||||
stripped = res.strip()
|
||||
assert stripped == "OK"
|
||||
|
||||
|
||||
def test_render_evaluate_text(render_context):
|
||||
tmpl = """
|
||||
#if 1
|
||||
OK
|
||||
#end if
|
||||
"""
|
||||
|
||||
res = render_cheetah_tmpl(tmpl, render_context)
|
||||
stripped = res.strip()
|
||||
assert stripped == "OK"
|
||||
|
||||
|
||||
def test_render_variable(render_context):
|
||||
tmpl = """$var"""
|
||||
|
||||
render_context["var"] = "OK"
|
||||
res = render_cheetah_tmpl(tmpl, render_context)
|
||||
assert res.strip() == "OK"
|
36
tests/pytests/unit/utils/templates/test_genshi.py
Normal file
36
tests/pytests/unit/utils/templates/test_genshi.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
import pytest
|
||||
from salt.utils.templates import render_genshi_tmpl
|
||||
|
||||
pytest.importorskip("genshi")
|
||||
|
||||
|
||||
def test_render_sanity(render_context):
|
||||
tmpl = """<RU>OK</RU>"""
|
||||
res = render_genshi_tmpl(tmpl, render_context)
|
||||
assert res == "<RU>OK</RU>"
|
||||
|
||||
|
||||
def test_render_evaluate(render_context):
|
||||
tmpl = """<RU>${ "OK" }</RU>"""
|
||||
res = render_genshi_tmpl(tmpl, render_context)
|
||||
assert res == "<RU>OK</RU>"
|
||||
|
||||
|
||||
def test_render_evaluate_condition(render_context):
|
||||
tmpl = """<RU xmlns:py="http://genshi.edgewall.org/" py:if="1">OK</RU>"""
|
||||
res = render_genshi_tmpl(tmpl, render_context)
|
||||
assert res == "<RU>OK</RU>"
|
||||
|
||||
|
||||
def test_render_variable(render_context):
|
||||
tmpl = """<RU>$var</RU>"""
|
||||
render_context["var"] = "OK"
|
||||
res = render_genshi_tmpl(tmpl, render_context)
|
||||
assert res == "<RU>OK</RU>"
|
||||
|
||||
|
||||
def test_render_variable_replace(render_context):
|
||||
tmpl = """<RU xmlns:py="http://genshi.edgewall.org/" py:content="var">not ok</RU>"""
|
||||
render_context["var"] = "OK"
|
||||
res = render_genshi_tmpl(tmpl, render_context)
|
||||
assert res == "<RU>OK</RU>"
|
|
@ -1,41 +1,17 @@
|
|||
"""
|
||||
Tests for salt.utils.templates
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
||||
from collections import OrderedDict
|
||||
import pytest
|
||||
from salt.exceptions import SaltRenderError
|
||||
from salt.utils.templates import render_jinja_tmpl
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def minion_opts(tmp_path, minion_opts):
|
||||
minion_opts.update(
|
||||
{
|
||||
"cachedir": str(tmp_path / "jinja-template-cache"),
|
||||
"file_buffer_size": 1048576,
|
||||
"file_client": "local",
|
||||
"file_ignore_regex": None,
|
||||
"file_ignore_glob": None,
|
||||
"file_roots": {"test": [str(tmp_path / "templates")]},
|
||||
"pillar_roots": {"test": [str(tmp_path / "templates")]},
|
||||
"fileserver_backend": ["roots"],
|
||||
"hash_type": "md5",
|
||||
"extension_modules": os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "extmods"
|
||||
),
|
||||
}
|
||||
)
|
||||
return minion_opts
|
||||
from tests.support.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_salt():
|
||||
return {}
|
||||
|
||||
|
||||
def test_jinja_undefined_error_context(minion_opts, local_salt):
|
||||
def test_undefined_error_context(render_context):
|
||||
"""
|
||||
Test that jinja provides both the line number on which the error occurred
|
||||
in the Jinja template, and also several lines of context around the error
|
||||
|
@ -63,5 +39,64 @@ def test_jinja_undefined_error_context(minion_opts, local_salt):
|
|||
with pytest.raises(SaltRenderError, match=match_regex):
|
||||
render_jinja_tmpl(
|
||||
jinja_code,
|
||||
dict(opts=minion_opts, saltenv="test", salt=local_salt),
|
||||
render_context,
|
||||
)
|
||||
|
||||
|
||||
def test_render_sanity(render_context):
|
||||
tmpl = """OK"""
|
||||
res = render_jinja_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_evaluate(render_context):
|
||||
tmpl = """{{ "OK" }}"""
|
||||
res = render_jinja_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_evaluate_multi(render_context):
|
||||
tmpl = """{% if 1 -%}OK{%- endif %}"""
|
||||
res = render_jinja_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_variable(render_context):
|
||||
tmpl = """{{ var }}"""
|
||||
render_context["var"] = "OK"
|
||||
res = render_jinja_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_tojson_sorted(render_context):
|
||||
templ = """thing: {{ var|tojson(sort_keys=True) }}"""
|
||||
expected = """thing: {"x": "xxx", "y": "yyy", "z": "zzz"}"""
|
||||
|
||||
with patch.dict(render_context, {"var": {"z": "zzz", "y": "yyy", "x": "xxx"}}):
|
||||
res = render_jinja_tmpl(templ, render_context)
|
||||
|
||||
assert res == expected
|
||||
|
||||
|
||||
def test_render_tojson_unsorted(render_context):
|
||||
templ = """thing: {{ var|tojson(sort_keys=False) }}"""
|
||||
expected = """thing: {"z": "zzz", "x": "xxx", "y": "yyy"}"""
|
||||
|
||||
# Values must be added to the dict in the expected order. This is
|
||||
# only necessary for older Pythons that don't remember dict order.
|
||||
d = OrderedDict()
|
||||
d["z"] = "zzz"
|
||||
d["x"] = "xxx"
|
||||
d["y"] = "yyy"
|
||||
|
||||
with patch.dict(render_context, {"var": d}):
|
||||
res = render_jinja_tmpl(templ, render_context)
|
||||
|
||||
assert res == expected
|
||||
|
||||
|
||||
def test_render_cve_2021_25283(render_context):
|
||||
tmpl = """{{ [].__class__ }}"""
|
||||
render_context["var"] = "OK"
|
||||
with pytest.raises(SaltRenderError):
|
||||
res = render_jinja_tmpl(tmpl, render_context)
|
||||
|
|
34
tests/pytests/unit/utils/templates/test_mako.py
Normal file
34
tests/pytests/unit/utils/templates/test_mako.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import pytest
|
||||
from salt.utils.templates import render_mako_tmpl
|
||||
|
||||
pytest.importorskip("mako")
|
||||
|
||||
|
||||
def test_render_mako_sanity(render_context):
|
||||
tmpl = """OK"""
|
||||
res = render_mako_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_mako_evaluate(render_context):
|
||||
tmpl = """${ "OK" }"""
|
||||
res = render_mako_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_mako_evaluate_multi(render_context):
|
||||
tmpl = """
|
||||
% if 1:
|
||||
OK
|
||||
% endif
|
||||
"""
|
||||
res = render_mako_tmpl(tmpl, render_context)
|
||||
stripped = res.strip()
|
||||
assert stripped == "OK"
|
||||
|
||||
|
||||
def test_render_mako_variable(render_context):
|
||||
tmpl = """${ var }"""
|
||||
render_context["var"] = "OK"
|
||||
res = render_mako_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
29
tests/pytests/unit/utils/templates/test_wempy.py
Normal file
29
tests/pytests/unit/utils/templates/test_wempy.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
import pytest
|
||||
from salt.utils.templates import render_wempy_tmpl
|
||||
|
||||
pytest.importorskip("wemplate")
|
||||
|
||||
|
||||
def test_render_wempy_sanity(render_context):
|
||||
tmpl = """OK"""
|
||||
res = render_wempy_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_wempy_evaluate(render_context):
|
||||
tmpl = """{{="OK"}}"""
|
||||
res = render_wempy_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_wempy_evaluate_multi(render_context):
|
||||
tmpl = """{{if 1:}}OK{{pass}}"""
|
||||
res = render_wempy_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
||||
|
||||
|
||||
def test_render_wempy_variable(render_context):
|
||||
tmpl = """{{=var}}"""
|
||||
render_context["var"] = "OK"
|
||||
res = render_wempy_tmpl(tmpl, render_context)
|
||||
assert res == "OK"
|
217
tests/pytests/unit/utils/templates/test_wrap_tmpl_func.py
Normal file
217
tests/pytests/unit/utils/templates/test_wrap_tmpl_func.py
Normal file
|
@ -0,0 +1,217 @@
|
|||
"""
|
||||
Unit tests for salt.utils.templates.py
|
||||
"""
|
||||
import logging
|
||||
from pathlib import PurePath, PurePosixPath
|
||||
|
||||
import pytest
|
||||
|
||||
from salt.utils.templates import wrap_tmpl_func, generate_sls_context
|
||||
from tests.support.mock import patch
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MockRender:
|
||||
def __call__(self, tplstr, context, tmplpath=None):
|
||||
self.tplstr = tplstr
|
||||
self.context = context
|
||||
self.tmplpath = tmplpath
|
||||
return tplstr
|
||||
|
||||
|
||||
def _test_generated_sls_context(tmplpath, sls, **expected):
|
||||
"""Generic SLS Context Test"""
|
||||
# DeNormalize tmplpath
|
||||
tmplpath = str(PurePath(PurePosixPath(tmplpath)))
|
||||
if tmplpath.startswith("\\"):
|
||||
tmplpath = "C:{}".format(tmplpath)
|
||||
expected["tplpath"] = tmplpath
|
||||
actual = generate_sls_context(tmplpath, sls)
|
||||
assert {key: actual[key] for key in expected if key in actual} == actual
|
||||
|
||||
|
||||
def test_sls_context_call(tmp_path):
|
||||
"""Check that generate_sls_context is called with proper parameters"""
|
||||
sls = "foo.bar"
|
||||
slsfile = tmp_path / "foo" / "bar.sls"
|
||||
slsfile.parent.mkdir()
|
||||
slsfile.write_text("{{ slspath }}")
|
||||
context = {"opts": {}, "saltenv": "base", "sls": sls}
|
||||
render = MockRender()
|
||||
with patch("salt.utils.templates.generate_sls_context") as generate_sls_context:
|
||||
wrapped = wrap_tmpl_func(render)
|
||||
res = wrapped(str(slsfile), context=context, tmplpath=str(slsfile))
|
||||
generate_sls_context.assert_called_with(str(slsfile), sls)
|
||||
|
||||
|
||||
def test_sls_context_no_call(tmp_path):
|
||||
"""Check that generate_sls_context is not called if sls is not set"""
|
||||
sls = "foo.bar"
|
||||
slsfile = tmp_path / "foo" / "bar.sls"
|
||||
slsfile.parent.mkdir()
|
||||
slsfile.write_text("{{ slspath }}")
|
||||
context = {"opts": {}, "saltenv": "base"}
|
||||
render = MockRender()
|
||||
with patch("salt.utils.templates.generate_sls_context") as generate_sls_context:
|
||||
wrapped = wrap_tmpl_func(render)
|
||||
res = wrapped(str(slsfile), context=context, tmplpath=str(slsfile))
|
||||
generate_sls_context.assert_not_called()
|
||||
|
||||
|
||||
def test_generate_sls_context__top_level():
|
||||
"""generate_sls_context - top_level Use case"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/boo.sls",
|
||||
"boo",
|
||||
tplfile="boo.sls",
|
||||
tpldir=".",
|
||||
tpldot="",
|
||||
slsdotpath="",
|
||||
slscolonpath="",
|
||||
sls_path="",
|
||||
slspath="",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__one_level_init_implicit():
|
||||
"""generate_sls_context - Basic one level with implicit init.sls"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/init.sls",
|
||||
"foo",
|
||||
tplfile="foo/init.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__one_level_init_explicit():
|
||||
"""generate_sls_context - Basic one level with explicit init.sls"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/init.sls",
|
||||
"foo.init",
|
||||
tplfile="foo/init.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__one_level():
|
||||
"""generate_sls_context - Basic one level with name"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/boo.sls",
|
||||
"foo.boo",
|
||||
tplfile="foo/boo.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__one_level_repeating():
|
||||
"""generate_sls_context - Basic one level with name same as dir
|
||||
|
||||
(Issue #56410)
|
||||
"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/foo.sls",
|
||||
"foo.foo",
|
||||
tplfile="foo/foo.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__two_level_init_implicit():
|
||||
"""generate_sls_context - Basic two level with implicit init.sls"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/bar/init.sls",
|
||||
"foo.bar",
|
||||
tplfile="foo/bar/init.sls",
|
||||
tpldir="foo/bar",
|
||||
tpldot="foo.bar",
|
||||
slsdotpath="foo.bar",
|
||||
slscolonpath="foo:bar",
|
||||
sls_path="foo_bar",
|
||||
slspath="foo/bar",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__two_level_init_explicit():
|
||||
"""generate_sls_context - Basic two level with explicit init.sls"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/bar/init.sls",
|
||||
"foo.bar.init",
|
||||
tplfile="foo/bar/init.sls",
|
||||
tpldir="foo/bar",
|
||||
tpldot="foo.bar",
|
||||
slsdotpath="foo.bar",
|
||||
slscolonpath="foo:bar",
|
||||
sls_path="foo_bar",
|
||||
slspath="foo/bar",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__two_level():
|
||||
"""generate_sls_context - Basic two level with name"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/bar/boo.sls",
|
||||
"foo.bar.boo",
|
||||
tplfile="foo/bar/boo.sls",
|
||||
tpldir="foo/bar",
|
||||
tpldot="foo.bar",
|
||||
slsdotpath="foo.bar",
|
||||
slscolonpath="foo:bar",
|
||||
sls_path="foo_bar",
|
||||
slspath="foo/bar",
|
||||
)
|
||||
|
||||
|
||||
def test_generate_sls_context__two_level_repeating():
|
||||
"""generate_sls_context - Basic two level with name same as dir
|
||||
|
||||
(Issue #56410)
|
||||
"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/foo/foo.sls",
|
||||
"foo.foo.foo",
|
||||
tplfile="foo/foo/foo.sls",
|
||||
tpldir="foo/foo",
|
||||
tpldot="foo.foo",
|
||||
slsdotpath="foo.foo",
|
||||
slscolonpath="foo:foo",
|
||||
sls_path="foo_foo",
|
||||
slspath="foo/foo",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_on_windows
|
||||
def test_generate_sls_context__backslash_in_path():
|
||||
"""generate_sls_context - Handle backslash in path on non-windows"""
|
||||
_test_generated_sls_context(
|
||||
"/tmp/foo/foo\\foo.sls",
|
||||
"foo.foo\\foo",
|
||||
tplfile="foo/foo\\foo.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
|
@ -1,440 +0,0 @@
|
|||
"""
|
||||
Unit tests for salt.utils.templates.py
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
from pathlib import PurePath, PurePosixPath
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.utils.files
|
||||
import salt.utils.templates
|
||||
from tests.support.helpers import with_tempdir
|
||||
from tests.support.mock import patch
|
||||
from tests.support.unit import TestCase
|
||||
|
||||
try:
|
||||
import Cheetah as _
|
||||
|
||||
HAS_CHEETAH = True
|
||||
except ImportError:
|
||||
HAS_CHEETAH = False
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RenderTestCase(TestCase):
|
||||
def setUp(self):
|
||||
# Default context for salt.utils.templates.render_*_tmpl to work
|
||||
self.context = {
|
||||
"opts": {"cachedir": "/D", "__cli": "salt"},
|
||||
"saltenv": None,
|
||||
}
|
||||
|
||||
### Tests for Jinja (whitespace-friendly)
|
||||
def test_render_jinja_sanity(self):
|
||||
tmpl = """OK"""
|
||||
res = salt.utils.templates.render_jinja_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
def test_render_jinja_evaluate(self):
|
||||
tmpl = """{{ "OK" }}"""
|
||||
res = salt.utils.templates.render_jinja_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
def test_render_jinja_evaluate_multi(self):
|
||||
tmpl = """{% if 1 -%}OK{%- endif %}"""
|
||||
res = salt.utils.templates.render_jinja_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
def test_render_jinja_variable(self):
|
||||
tmpl = """{{ var }}"""
|
||||
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
res = salt.utils.templates.render_jinja_tmpl(tmpl, ctx)
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
def test_render_jinja_tojson_sorted(self):
|
||||
templ = """thing: {{ var|tojson(sort_keys=True) }}"""
|
||||
expected = """thing: {"x": "xxx", "y": "yyy", "z": "zzz"}"""
|
||||
|
||||
with patch.dict(self.context, {"var": {"z": "zzz", "y": "yyy", "x": "xxx"}}):
|
||||
res = salt.utils.templates.render_jinja_tmpl(templ, self.context)
|
||||
|
||||
assert res == expected
|
||||
|
||||
def test_render_jinja_tojson_unsorted(self):
|
||||
templ = """thing: {{ var|tojson(sort_keys=False) }}"""
|
||||
expected = """thing: {"z": "zzz", "x": "xxx", "y": "yyy"}"""
|
||||
|
||||
# Values must be added to the dict in the expected order. This is
|
||||
# only necessary for older Pythons that don't remember dict order.
|
||||
d = OrderedDict()
|
||||
d["z"] = "zzz"
|
||||
d["x"] = "xxx"
|
||||
d["y"] = "yyy"
|
||||
|
||||
with patch.dict(self.context, {"var": d}):
|
||||
res = salt.utils.templates.render_jinja_tmpl(templ, self.context)
|
||||
|
||||
assert res == expected
|
||||
|
||||
### Tests for mako template
|
||||
def test_render_mako_sanity(self):
|
||||
tmpl = """OK"""
|
||||
res = salt.utils.templates.render_mako_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
def test_render_mako_evaluate(self):
|
||||
tmpl = """${ "OK" }"""
|
||||
res = salt.utils.templates.render_mako_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
def test_render_mako_evaluate_multi(self):
|
||||
tmpl = """
|
||||
% if 1:
|
||||
OK
|
||||
% endif
|
||||
"""
|
||||
res = salt.utils.templates.render_mako_tmpl(tmpl, dict(self.context))
|
||||
stripped = res.strip()
|
||||
self.assertEqual(stripped, "OK")
|
||||
|
||||
def test_render_mako_variable(self):
|
||||
tmpl = """${ var }"""
|
||||
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
res = salt.utils.templates.render_mako_tmpl(tmpl, ctx)
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
### Tests for wempy template
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info > (3,),
|
||||
reason="The wempy module is currently unsupported under Python3",
|
||||
)
|
||||
def test_render_wempy_sanity(self):
|
||||
tmpl = """OK"""
|
||||
res = salt.utils.templates.render_wempy_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info > (3,),
|
||||
reason="The wempy module is currently unsupported under Python3",
|
||||
)
|
||||
def test_render_wempy_evaluate(self):
|
||||
tmpl = """{{="OK"}}"""
|
||||
res = salt.utils.templates.render_wempy_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info > (3,),
|
||||
reason="The wempy module is currently unsupported under Python3",
|
||||
)
|
||||
def test_render_wempy_evaluate_multi(self):
|
||||
tmpl = """{{if 1:}}OK{{pass}}"""
|
||||
res = salt.utils.templates.render_wempy_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info > (3,),
|
||||
reason="The wempy module is currently unsupported under Python3",
|
||||
)
|
||||
def test_render_wempy_variable(self):
|
||||
tmpl = """{{=var}}"""
|
||||
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
res = salt.utils.templates.render_wempy_tmpl(tmpl, ctx)
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
### Tests for genshi template (xml-based)
|
||||
def test_render_genshi_sanity(self):
|
||||
tmpl = """<RU>OK</RU>"""
|
||||
res = salt.utils.templates.render_genshi_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "<RU>OK</RU>")
|
||||
|
||||
def test_render_genshi_evaluate(self):
|
||||
tmpl = """<RU>${ "OK" }</RU>"""
|
||||
res = salt.utils.templates.render_genshi_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "<RU>OK</RU>")
|
||||
|
||||
def test_render_genshi_evaluate_condition(self):
|
||||
tmpl = """<RU xmlns:py="http://genshi.edgewall.org/" py:if="1">OK</RU>"""
|
||||
res = salt.utils.templates.render_genshi_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "<RU>OK</RU>")
|
||||
|
||||
def test_render_genshi_variable(self):
|
||||
tmpl = """<RU>$var</RU>"""
|
||||
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
res = salt.utils.templates.render_genshi_tmpl(tmpl, ctx)
|
||||
self.assertEqual(res, "<RU>OK</RU>")
|
||||
|
||||
def test_render_genshi_variable_replace(self):
|
||||
tmpl = """<RU xmlns:py="http://genshi.edgewall.org/" py:content="var">not ok</RU>"""
|
||||
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
res = salt.utils.templates.render_genshi_tmpl(tmpl, ctx)
|
||||
self.assertEqual(res, "<RU>OK</RU>")
|
||||
|
||||
### Tests for cheetah template (line-oriented and xml-friendly)
|
||||
@pytest.mark.skipif(not HAS_CHEETAH, reason="The Cheetah Python module is missing.")
|
||||
def test_render_cheetah_sanity(self):
|
||||
tmpl = """OK"""
|
||||
res = salt.utils.templates.render_cheetah_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
@pytest.mark.skipif(not HAS_CHEETAH, reason="The Cheetah Python module is missing.")
|
||||
def test_render_cheetah_evaluate(self):
|
||||
tmpl = """<%="OK"%>"""
|
||||
res = salt.utils.templates.render_cheetah_tmpl(tmpl, dict(self.context))
|
||||
self.assertEqual(res, "OK")
|
||||
|
||||
@pytest.mark.skipif(not HAS_CHEETAH, reason="The Cheetah Python module is missing.")
|
||||
def test_render_cheetah_evaluate_xml(self):
|
||||
tmpl = """
|
||||
<% if 1: %>
|
||||
OK
|
||||
<% pass %>
|
||||
"""
|
||||
res = salt.utils.templates.render_cheetah_tmpl(tmpl, dict(self.context))
|
||||
stripped = res.strip()
|
||||
self.assertEqual(stripped, "OK")
|
||||
|
||||
@pytest.mark.skipif(not HAS_CHEETAH, reason="The Cheetah Python module is missing.")
|
||||
def test_render_cheetah_evaluate_text(self):
|
||||
tmpl = """
|
||||
#if 1
|
||||
OK
|
||||
#end if
|
||||
"""
|
||||
|
||||
res = salt.utils.templates.render_cheetah_tmpl(tmpl, dict(self.context))
|
||||
stripped = res.strip()
|
||||
self.assertEqual(stripped, "OK")
|
||||
|
||||
@pytest.mark.skipif(not HAS_CHEETAH, reason="The Cheetah Python module is missing.")
|
||||
def test_render_cheetah_variable(self):
|
||||
tmpl = """$var"""
|
||||
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
res = salt.utils.templates.render_cheetah_tmpl(tmpl, ctx)
|
||||
self.assertEqual(res.strip(), "OK")
|
||||
|
||||
def test_render_jinja_cve_2021_25283(self):
|
||||
tmpl = """{{ [].__class__ }}"""
|
||||
ctx = dict(self.context)
|
||||
ctx["var"] = "OK"
|
||||
with pytest.raises(salt.exceptions.SaltRenderError):
|
||||
res = salt.utils.templates.render_jinja_tmpl(tmpl, ctx)
|
||||
|
||||
|
||||
class MockRender:
|
||||
def __call__(self, tplstr, context, tmplpath=None):
|
||||
self.tplstr = tplstr
|
||||
self.context = context
|
||||
self.tmplpath = tmplpath
|
||||
return tplstr
|
||||
|
||||
|
||||
class WrapRenderTestCase(TestCase):
|
||||
def assertDictContainsAll(self, actual, **expected):
|
||||
"""Make sure dictionary contains at least all expected values"""
|
||||
actual = {key: actual[key] for key in expected if key in actual}
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def _test_generated_sls_context(self, tmplpath, sls, **expected):
|
||||
"""Generic SLS Context Test"""
|
||||
# DeNormalize tmplpath
|
||||
tmplpath = str(PurePath(PurePosixPath(tmplpath)))
|
||||
if tmplpath.startswith("\\"):
|
||||
tmplpath = "C:{}".format(tmplpath)
|
||||
expected["tplpath"] = tmplpath
|
||||
actual = salt.utils.templates.generate_sls_context(tmplpath, sls)
|
||||
self.assertDictContainsAll(actual, **expected)
|
||||
|
||||
@patch("salt.utils.templates.generate_sls_context")
|
||||
@with_tempdir()
|
||||
def test_sls_context_call(self, tempdir, generate_sls_context):
|
||||
"""Check that generate_sls_context is called with proper parameters"""
|
||||
sls = "foo.bar"
|
||||
tmplpath = "/tmp/foo/bar.sls"
|
||||
|
||||
slsfile = os.path.join(tempdir, "foo")
|
||||
with salt.utils.files.fopen(slsfile, "w") as fp:
|
||||
fp.write("{{ slspath }}")
|
||||
context = {"opts": {}, "saltenv": "base", "sls": sls}
|
||||
render = MockRender()
|
||||
wrapped = salt.utils.templates.wrap_tmpl_func(render)
|
||||
res = wrapped(slsfile, context=context, tmplpath=tmplpath)
|
||||
generate_sls_context.assert_called_with(tmplpath, sls)
|
||||
|
||||
@patch("salt.utils.templates.generate_sls_context")
|
||||
@with_tempdir()
|
||||
def test_sls_context_no_call(self, tempdir, generate_sls_context):
|
||||
"""Check that generate_sls_context is not called if sls is not set"""
|
||||
sls = "foo.bar"
|
||||
tmplpath = "/tmp/foo/bar.sls"
|
||||
|
||||
slsfile = os.path.join(tempdir, "foo")
|
||||
with salt.utils.files.fopen(slsfile, "w") as fp:
|
||||
fp.write("{{ slspath }}")
|
||||
context = {"opts": {}, "saltenv": "base"}
|
||||
render = MockRender()
|
||||
wrapped = salt.utils.templates.wrap_tmpl_func(render)
|
||||
res = wrapped(slsfile, context=context, tmplpath=tmplpath)
|
||||
generate_sls_context.assert_not_called()
|
||||
|
||||
def test_generate_sls_context__top_level(self):
|
||||
"""generate_sls_context - top_level Use case"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/boo.sls",
|
||||
"boo",
|
||||
tplfile="boo.sls",
|
||||
tpldir=".",
|
||||
tpldot="",
|
||||
slsdotpath="",
|
||||
slscolonpath="",
|
||||
sls_path="",
|
||||
slspath="",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__one_level_init_implicit(self):
|
||||
"""generate_sls_context - Basic one level with implicit init.sls"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/init.sls",
|
||||
"foo",
|
||||
tplfile="foo/init.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__one_level_init_explicit(self):
|
||||
"""generate_sls_context - Basic one level with explicit init.sls"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/init.sls",
|
||||
"foo.init",
|
||||
tplfile="foo/init.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__one_level(self):
|
||||
"""generate_sls_context - Basic one level with name"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/boo.sls",
|
||||
"foo.boo",
|
||||
tplfile="foo/boo.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__one_level_repeating(self):
|
||||
"""generate_sls_context - Basic one level with name same as dir
|
||||
|
||||
(Issue #56410)
|
||||
"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/foo.sls",
|
||||
"foo.foo",
|
||||
tplfile="foo/foo.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__two_level_init_implicit(self):
|
||||
"""generate_sls_context - Basic two level with implicit init.sls"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/bar/init.sls",
|
||||
"foo.bar",
|
||||
tplfile="foo/bar/init.sls",
|
||||
tpldir="foo/bar",
|
||||
tpldot="foo.bar",
|
||||
slsdotpath="foo.bar",
|
||||
slscolonpath="foo:bar",
|
||||
sls_path="foo_bar",
|
||||
slspath="foo/bar",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__two_level_init_explicit(self):
|
||||
"""generate_sls_context - Basic two level with explicit init.sls"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/bar/init.sls",
|
||||
"foo.bar.init",
|
||||
tplfile="foo/bar/init.sls",
|
||||
tpldir="foo/bar",
|
||||
tpldot="foo.bar",
|
||||
slsdotpath="foo.bar",
|
||||
slscolonpath="foo:bar",
|
||||
sls_path="foo_bar",
|
||||
slspath="foo/bar",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__two_level(self):
|
||||
"""generate_sls_context - Basic two level with name"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/bar/boo.sls",
|
||||
"foo.bar.boo",
|
||||
tplfile="foo/bar/boo.sls",
|
||||
tpldir="foo/bar",
|
||||
tpldot="foo.bar",
|
||||
slsdotpath="foo.bar",
|
||||
slscolonpath="foo:bar",
|
||||
sls_path="foo_bar",
|
||||
slspath="foo/bar",
|
||||
)
|
||||
|
||||
def test_generate_sls_context__two_level_repeating(self):
|
||||
"""generate_sls_context - Basic two level with name same as dir
|
||||
|
||||
(Issue #56410)
|
||||
"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/foo/foo.sls",
|
||||
"foo.foo.foo",
|
||||
tplfile="foo/foo/foo.sls",
|
||||
tpldir="foo/foo",
|
||||
tpldot="foo.foo",
|
||||
slsdotpath="foo.foo",
|
||||
slscolonpath="foo:foo",
|
||||
sls_path="foo_foo",
|
||||
slspath="foo/foo",
|
||||
)
|
||||
|
||||
@pytest.mark.skip_on_windows
|
||||
def test_generate_sls_context__backslash_in_path(self):
|
||||
"""generate_sls_context - Handle backslash in path on non-windows"""
|
||||
self._test_generated_sls_context(
|
||||
"/tmp/foo/foo\\foo.sls",
|
||||
"foo.foo\\foo",
|
||||
tplfile="foo/foo\\foo.sls",
|
||||
tpldir="foo",
|
||||
tpldot="foo",
|
||||
slsdotpath="foo",
|
||||
slscolonpath="foo",
|
||||
sls_path="foo",
|
||||
slspath="foo",
|
||||
)
|
Loading…
Add table
Reference in a new issue