saltstack / saltstack/salt

[BUG] py renderer does not follow simple renderer API

Open
#62,524 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug needs-triage Renderers
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.