[BUG] py renderer does not follow simple renderer API
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 15.7k
- Forks
- 5.6k
- Avg merge
- 2d 44m
- Merged PRs (30d)
- 80
Description
Description
According to https://docs.saltproject.io/en/latest/ref/renderers/index.html#writing-renderers
the renderer should take the first positional arg data yet the first thing that the py renderer does is ignore all of that and expect a tmplpath, causing it to fail when compile_template is passed input_data without a path to a template on disk:
https://github.com/saltstack/salt/blob/master/salt/renderers/py.py#L119
def render(template, saltenv="base", sls="", tmplpath=None, **kws):
"""
Render the python module's components
:rtype: string
"""
template = tmplpath
if not os.path.isfile(template):
raise SaltRenderError("Template {} is not a file!".format(template))
Setup
Pick any Salt release or commit from the last 5 years and run the code below
Steps to Reproduce the behavior
(Include debug logs if possible and relevant)
import copy, salt.config, salt.loader, salt.template
opts = copy.deepcopy(salt.config.DEFAULT_MINION_OPTS)
mods = salt.loader.minion_mods(opts)
renderers = salt.loader.render(opts, mods)
def_renderer = "jinja|yaml"
content = """#!py
def run():
return {"yes": False}
"""
ret = salt.template.compile_template(
":string:",
renderers,
def_renderer,
opts["renderer_blacklist"],
opts["renderer_whitelist"],
input_data=content,
)
print(ret.read() if salt.utils.stringio.is_readable(ret) else ret)
Which results in
Python 3.10.6 (main, Aug 3 2022, 17:39:45) [GCC 12.1.1 20220730] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import copy, salt.config, salt.loader, salt.template
/usr/lib/python3.10/site-packages/_distutils_hack/__init__.py:30: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")
>>> opts = copy.deepcopy(salt.config.DEFAULT_MINION_OPTS)
>>> mods = salt.loader.minion_mods(opts)
>>> renderers = salt.loader.render(opts, mods)
>>> def_renderer = "jinja|yaml"
>>>
>>> content = """#!py
... def run():
... return {"yes": False}
... """
>>> ret = salt.template.compile_template(
... ":string:",
... renderers,
... def_renderer,
... opts["renderer_blacklist"],
... opts["renderer_whitelist"],
... input_data=content,
... )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/frebib/stash/ops/saltstack/salt/template.py", line 99, in compile_template
ret = render(input_data, saltenv, sls, **render_kwargs)
File "/home/frebib/stash/ops/saltstack/salt/loader/lazy.py", line 149, in __call__
return self.loader.run(run_func, *args, **kwargs)
File "/home/frebib/stash/ops/saltstack/salt/loader/lazy.py", line 1228, in run
return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
File "/home/frebib/stash/ops/saltstack/salt/loader/lazy.py", line 1243, in _run_as
return _func_or_method(*args, **kwargs)
File "/home/frebib/stash/ops/saltstack/salt/renderers/py.py", line 127, in render
raise SaltRenderError("Template {} is not a file!".format(template))
salt.exceptions.SaltRenderError: Template :string: is not a file!
Expected behavior
The py renderer respects the renderer API(!!) and renders the data it's given
Additional context
This probably highlights a design flaw in either compile_template or the renderer API. Should renderers be allowed to accept both template files and input data? I haven't checked any other renderers, but py could not be alone here. jinja and yaml both work as I would expect, at least.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read salt/renderers/py.py, especially render(), alongside salt/template.py at compile_template where input_data is passed to the renderer. Run the supplied reproduction to confirm the current failure. Done means the py renderer follows the documented first-positional-argument API and the example renders its input data instead of treating it as a file path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100