Repository: saltstack/salt
Pull request: Fix renderers not getting the correct salt functions
### What does this PR do?
Gives the renderers access to the correct function sets via the wrapper that is passed in.

**_NOTE: This reverts the fix from https://github.com/saltstack/salt/pull/61634, but this is definitely a bigger issue._**

### What issues does this PR fix or reference?
Fixes: https://github.com/saltstack/salt/issues/62620 https://github.com/saltstack/salt/issues/62610 et. al.

### Previous Behavior
Jinja variable 'salt.utils.templates.AliasedLoader object' has no attribute 'pkg'

### New Behavior
No error, jinja (and other renderers) now have access to the correct set of functions

### Merge requirements satisfied?
**[NOTICE] Bug fixes or features added to Salt require tests.**
<!-- Please review the [test documentation](https://docs.saltproject.io/en/master/topics/tutorials/writing_tests.html) for details on how to implement tests into Salt's test suite. -->
- [ ] Docs
- [ ] Changelog - https://docs.saltproject.io/en/master/topics/development/changelog.html
- [x] Tests written/updated

### Commits signed with GPG?
Yes

Problem statement:
[BUG] 3005 breaks user.info in state files when using salt-ssh
**Description**
we use the `user.info` execution module to find a user's home dir in a lot of templates. it appears to be broken in v3005:
```
[ERROR   ] Rendering exception occurred
Traceback (most recent call last):
  File "/home/tessa/.local/share/virtualenvs/salt-MPl0_fNV/lib/python3.10/site-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/home/tessa/.local/share/virtualenvs/salt-MPl0_fNV/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/home/tessa/.local/share/virtualenvs/salt-MPl0_fNV/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
  File "/home/tessa/.local/share/virtualenvs/salt-MPl0_fNV/lib/python3.10/site-packages/jinja2/sandbox.py", line 391, in call
    if not __self.is_safe_callable(__obj):
  File "/home/tessa/.local/share/virtualenvs/salt-MPl0_fNV/lib/python3.10/site-packages/jinja2/sandbox.py", line 275, in is_safe_callable
    getattr(obj, "unsafe_callable", False) or getattr(obj, "alters_data", False)
jinja2.exceptions.UndefinedError: 'salt.utils.templates.AliasedLoader object' has no attribute 'user.info'
```

**Setup**
make a state that uses `user.info`.

- [X] on-prem machine
- [X] VM running on a cloud service, please be explicit and add details

**Steps to Reproduce the behavior**
execute existing state that worked fine in 3004 with jinja templating using `user.info`. watch it break horribly.

we've tested on Arch inside of pipenv, as well as Debian 11, Ubuntu 20.04 and Ubuntu 22.04 using the official repo packages, they all break.

example template:
```
{{ salt['user.info']('someuser').home }}
```

**Expected behavior**
works the same as 3004.

**Versions Report**
<details><summary>salt --versions-report</summary>
(Provided by running salt --versions-report. Please also mention any differences in master/minion versions.) 

```yaml
Salt Version:
          Salt: 3005
 
Dependency Versions:
          cffi: Not Installed
      cherrypy: Not Installed
      dateutil: Not Installed
     docker-py: Not Installed
         gitdb: Not Installed
     gitpython: Not Installed
        Jinja2: 3.1.2
       libgit2: Not Installed
      M2Crypto: Not Installed
          Mako: Not Installed
       msgpack: 1.0.4
  msgpack-pure: Not Installed
  mysql-python: Not Installed
     pycparser: Not Installed
      pycrypto: Not Installed
  pycryptodome: 3.15.0
        pygit2: Not Installed
        Python: 3.10.6 (main, Aug  3 2022, 17:39:45) [GCC 12.1.1 20220730]
  python-gnupg: Not Installed
        PyYAML: 6.0
         PyZMQ: 20.0.0
         smmap: Not Installed
       timelib: Not Installed
       Tornado: 4.5.3
           ZMQ: 4.3.4
 
System Versions:
          dist: endeavouros rolling rolling
        locale: utf-8
       machine: x86_64
       release: 5.15.61-1-lts
        system: Linux
       version: EndeavourOS rolling rolling```
</details>

Hints from issue discussion:
i do not seem to be able to recreate the issue. can you log into one of the machines you are having the issue on and run user.info through salt-call with -l debug and see if there is something blocking it from loading? 

```
root@salt00:/srv/salt/tests# salt -C 'home* or salt00* or ipa* or media*' slsutil.renderer salt://tests/user.sls default_renderer=jinja
home.wolfnet.bad4.us:
    /home/whytewolf
    3005
    bullseye
salt00:
    /home/whytewolf
    3005
    jammy
ipa.wolfnet.bad4.us:
    /home/whytewolf
    3005
    CentOS Linux 7 (Core)
media.wolfnet.bad4.us:
    /home/whytewolf
    3005
    CentOS Linux 7 (Core)
```

```
{{ salt['user.info']('whytewolf').home }}
{{ salt["test.version"]()}}
{{ salt["grains.get"]("lsb_distrib_codename") }}
```
Did you possibly make the same mistake as I did?
[#62551 (comment)](https://github.com/saltstack/salt/issues/62551#issuecomment-1231550587)
@OrangeDog I don't have any custom state modules, so that shouldn't be the issue.

@whytewolf I seem to have missed a crucial detail, which is that this is all being run through `salt-ssh`, so there's no salt on the target hosts. this may be Yet Another Salt-SSH Bug, as it doesn't seem to be properly qa'd whenever there's a new salt release. I can run `salt-ssh hostname user.info` and that works fine, so the bug seems specific to Jinja as well.

as well, it looks like the bug is specific to jinja *in state files*, not in files being templated by a state. so this `test.sls` is broken, but the file it templates (if the templated portion of the state is replaced with a static string) works:

```yaml
{{ salt['user.info']('ubuntu').home }}/test.file:
  file.managed:
    - source: salt://test/test.file
    - template: jinja
```
`test.file`:
```jinja
{{ salt['user.info']('ubuntu') }}
```

https://github.com/saltstack/salt/issues/62636
It's not a Jinja failure.  It's a state module loader failure.  The same problem is apparent in the `pyobjects` renderer, which does not use Jinja at all.
https://github.com/saltstack/salt/pull/62635 fixes this issue.

Commit message: make sure wrapper isn't None first :)

Patch to review:
diff --git a/changelog/62610.fixed b/changelog/62610.fixed
new file mode 100644
index 000000000000..54c8bee35718
--- /dev/null
+++ b/changelog/62610.fixed
@@ -0,0 +1 @@
+Renderers now have access to the correct set of salt functions.
\ No newline at end of file
diff --git a/changelog/62620.fixed b/changelog/62620.fixed
new file mode 100644
index 000000000000..54c8bee35718
--- /dev/null
+++ b/changelog/62620.fixed
@@ -0,0 +1 @@
+Renderers now have access to the correct set of salt functions.
\ No newline at end of file
diff --git a/salt/client/ssh/state.py b/salt/client/ssh/state.py
index 96118688f99c..dc0c04d00315 100644
--- a/salt/client/ssh/state.py
+++ b/salt/client/ssh/state.py
@@ -41,13 +41,15 @@ def load_modules(self, data=None, proxy=None):
         Load up the modules for remote compilation via ssh
         """
         self.functions = salt.loader.ssh_wrapper(self.opts, None, context=self.context)
+        if self.wrapper is not None:
+            self.wrapper.wfuncs = self.functions
         self.utils = salt.loader.utils(self.opts)
         self.serializers = salt.loader.serializers(self.opts)
         locals_ = salt.loader.minion_mods(self.opts, utils=self.utils)
         self.states = salt.loader.states(
             self.opts, locals_, self.utils, self.serializers
         )
-        self.rend = salt.loader.render(self.opts, self.functions)
+        self.rend = salt.loader.render(self.opts, self.wrapper)
 
     def check_refresh(self, data, ret):
         """
diff --git a/tests/pytests/integration/ssh/test_jinja_mods.py b/tests/pytests/integration/ssh/test_jinja_mods.py
new file mode 100644
index 000000000000..d730af16d029
--- /dev/null
+++ b/tests/pytests/integration/ssh/test_jinja_mods.py
@@ -0,0 +1,30 @@
+import pytest
+from saltfactories.utils.functional import StateResult
+
+pytestmark = [
+    pytest.mark.skip_on_windows(reason="salt-ssh not available on Windows"),
+]
+
+
+@pytest.mark.slow_test
+def test_echo(salt_ssh_cli, base_env_state_tree_root_dir):
+    """
+    verify salt-ssh can use imported map files in states
+    """
+    name = "echo"
+    echo = "hello"
+    state_file = """
+    ssh_test_echo:
+      test.show_notification:
+        - text: {{{{ salt['test.echo']('{echo}') }}}}
+    """.format(
+        echo=echo
+    )
+    state_tempfile = pytest.helpers.temp_file(
+        "{}.sls".format(name), state_file, base_env_state_tree_root_dir
+    )
+
+    with state_tempfile:
+        ret = salt_ssh_cli.run("state.apply", name)
+        result = StateResult(ret.data)
+        assert result.comment == echo


Code review comments:
diff_hunk: @@ -41,13 +41,15 @@ def load_modules(self, data=None, proxy=None):
         Load up the modules for remote compilation via ssh
         """
         self.functions = salt.loader.ssh_wrapper(self.opts, None, context=self.context)
+        if self.wrapper is not None:
+            self.wrapper.wfuncs = self.functions
         self.utils = salt.loader.utils(self.opts)
         self.serializers = salt.loader.serializers(self.opts)
         locals_ = salt.loader.minion_mods(self.opts, utils=self.utils)
         self.states = salt.loader.states(
             self.opts, locals_, self.utils, self.serializers
         )
-        self.rend = salt.loader.render(self.opts, self.functions)
+        self.rend = salt.loader.render(self.opts, self.wrapper)
path: salt/client/ssh/state.py
text: @user1:
This fixes my latest comment in this PR.

@author:
Yes, however this reverts the fix in https://github.com/saltstack/salt/pull/61634.  This is likely what we will end up doing for now and revisiting the issue associated with the aforementioned PR later, but just so you are aware.