Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Jinja template cache loading #62043

Merged

Conversation

nicholasmhughes
Copy link
Collaborator

What does this PR do?

This PR fixes an issue where Jinja templates can be loaded from the cache despite being removed from the Salt filesystem. See issue for more details.

What issues does this PR fix or reference?

Fixes: #62042

Previous Behavior

Salt would load cached Jinja templates if the files were removed from the Salt filesystem.

New Behavior

If a file is cached but no longer present on the Salt filesystem, it will not be loaded.

Merge requirements satisfied?

[NOTICE] Bug fixes or features added to Salt require tests.

Commits signed with GPG?

Yes

Please review Salt's Contributing Guide for best practices.

See GitHub's page on GPG signing for more information about signing commits with GPG.

@nicholasmhughes nicholasmhughes requested a review from a team as a code owner May 9, 2022 21:43
@nicholasmhughes nicholasmhughes requested review from dwoz and removed request for a team May 9, 2022 21:43
@nicholasmhughes
Copy link
Collaborator Author

re-run pr-amazon-2-x86_64-py3-pytest

@nicholasmhughes
Copy link
Collaborator Author

re-run pr-fedora-35-x86_64-py3-pytest

@nicholasmhughes
Copy link
Collaborator Author

re-run pr-centos-7-x86_64-py3-pytest

@nicholasmhughes
Copy link
Collaborator Author

re-run pr-freebsd-130-amd64-py3-pytest

@nicholasmhughes
Copy link
Collaborator Author

re-run pr-macosx-catalina-x86_64-py3-pytest

salt/utils/jinja.py Outdated Show resolved Hide resolved
@waynew
Copy link
Contributor

waynew commented May 12, 2022

Well. That's fun. Looks like it's still failing for both freebsd & mac :suspect:

@nicholasmhughes
Copy link
Collaborator Author

re-run pr-amazon-2-x86_64-py3-pytest

@nicholasmhughes
Copy link
Collaborator Author

@waynew I had to build a FreeBSD box... but I was able to clear those last two checks.

@nicholasmhughes nicholasmhughes added the Phosphorus v3005.0 Release code name and version label May 14, 2022
@Ch3LL
Copy link
Contributor

Ch3LL commented May 18, 2022

@waynew can you re-review please

@saltstack saltstack deleted a comment from github-actions bot May 23, 2022
Copy link
Contributor

@waynew waynew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Pretty sure that I poked at this locally last time I reviewed. LGTM

@garethgreenaway garethgreenaway merged commit 4e91f38 into saltstack:master May 24, 2022
@nicholasmhughes nicholasmhughes deleted the fix-jinja-include-cache branch May 24, 2022 02:30
@myii
Copy link
Contributor

myii commented May 24, 2022

Unfortunately, this PR appears to have resulted in a regression when working with Jinja relative imports, at least across all Linux platforms:

local:
    Data failed to compile:
----------
    Rendering SLS 'base:test_jinja.grains' failed: Jinja error: ./grains.jinja
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/dist-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 "/usr/local/lib/python3.7/dist-packages/salt/utils/jinja.py", line 219, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: ./grains.jinja
; line 1
---
{%- from "./grains.jinja" import grains with context %}    <======================
test_jinja/grains/cmd.run:
  cmd.run:
    - name: pwd
[...]

I'm a bit short of time at the moment but I'll try to debug further when I get a chance.

@Ch3LL
Copy link
Contributor

Ch3LL commented May 24, 2022

@nicholasmhughes can you investigate ^

@myii
Copy link
Contributor

myii commented May 24, 2022

OK, this seems to confirm that the regression has been introduced by the merge of this PR.

I've rerun the pipeline without this PR's commits and all passing fine again (all four states are using Jinja relative imports):

local:
----------
          ID: test_jinja/grains/cmd.run
    Function: cmd.run
        Name: pwd
      Result: True
     Comment: Command "pwd" run
     Started: 14:14:49.481086
    Duration: 6.682 ms
     Changes:   
              ----------
              pid:
                  145
              retcode:
                  0
              stderr:
              stdout:
                  /root
Summary for local
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:   6.682 ms
local:
----------
          ID: test_jinja/opts/cmd.run
    Function: cmd.run
        Name: pwd
      Result: True
     Comment: Command "pwd" run
     Started: 14:14:51.407127
    Duration: 6.81 ms
     Changes:   
              ----------
              pid:
                  175
              retcode:
                  0
              stderr:
              stdout:
                  /root
Summary for local
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:   6.810 ms
local:
----------
          ID: test_jinja/pillar/cmd.run
    Function: cmd.run
        Name: pwd
      Result: True
     Comment: Command "pwd" run
     Started: 14:14:53.373170
    Duration: 6.791 ms
     Changes:   
              ----------
              pid:
                  205
              retcode:
                  0
              stderr:
              stdout:
                  /root
Summary for local
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:   6.791 ms
local:
----------
          ID: test_jinja/salt/cmd.run
    Function: cmd.run
        Name: pwd
      Result: True
     Comment: Command "pwd" run
     Started: 14:14:55.344258
    Duration: 6.793 ms
     Changes:   
              ----------
              pid:
                  235
              retcode:
                  0
              stderr:
              stdout:
                  /root
Summary for local
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:   6.793 ms

@myii
Copy link
Contributor

myii commented May 24, 2022

The following bisect should help (b3dacf1):

b3dacf1188a6507dc01efa6ab7d480a82c11f6b6 is the first bad commit
commit b3dacf1188a6507dc01efa6ab7d480a82c11f6b6
...
...

    handle local paths properly

 salt/utils/jinja.py | 3 +++
 1 file changed, 3 insertions(+)

I.e.

salt/salt/utils/jinja.py

Lines 178 to 180 in 4e91f38

# local file clients should pass the dot-expanded relative path
if environment.globals.get("opts", {}).get("file_client") == "local":
_template = os.path.relpath(_template, base_path)

@nicholasmhughes
Copy link
Collaborator Author

@myii , I was able to reproduce in an operational environment. I installed Salt from the master branch today on a fresh Debian 10 machine using the bootstrap script.

curl -L https://bootstrap.saltproject.io | sudo sh -s -- -M git master

Versions Report:

Salt Version:
          Salt: 3005+0na.b18281e
 
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.3
  msgpack-pure: Not Installed
  mysql-python: Not Installed
     pycparser: Not Installed
      pycrypto: 2.6.1
  pycryptodome: 3.14.1
        pygit2: Not Installed
        Python: 3.7.3 (default, Jan 22 2021, 20:04:44)
  python-gnupg: Not Installed
        PyYAML: 6.0
         PyZMQ: 22.3.0
         smmap: Not Installed
       timelib: Not Installed
       Tornado: 4.5.3
           ZMQ: 4.3.4
 
System Versions:
          dist: debian 10 buster
        locale: UTF-8
       machine: x86_64
       release: 4.19.0-18-amd64
        system: Linux
       version: Debian GNU/Linux 10 buster

And then pulled down the test files the pipeline is running onto the master:

root@d10-saltgit-01:/srv# pwd
/srv

root@d10-saltgit-01:/srv# git clone https://gitlab.com/saltstack-formulas/infrastructure/salt-image-builder.git
Cloning into 'salt-image-builder'...
remote: Enumerating objects: 4012, done.
remote: Counting objects: 100% (714/714), done.
remote: Compressing objects: 100% (162/162), done.
remote: Total 4012 (delta 579), reused 662 (delta 544), pack-reused 3298
Receiving objects: 100% (4012/4012), 2.48 MiB | 6.01 MiB/s, done.
Resolving deltas: 100% (3144/3144), done.

root@d10-saltgit-01:/srv# mkdir salt

root@d10-saltgit-01:/srv# cp -r salt-image-builder/test/test_jinja /srv/salt/

root@d10-saltgit-01:/srv# ll salt/test_jinja
total 48
-rw-r--r-- 1 root root  45 May 27 20:37 grains.jinja
-rw-r--r-- 1 root root 111 May 27 20:37 grains.sls
-rw-r--r-- 1 root root  41 May 27 20:37 grains.yaml
-rw-r--r-- 1 root root  41 May 27 20:37 opts.jinja
-rw-r--r-- 1 root root 105 May 27 20:37 opts.sls
-rw-r--r-- 1 root root  40 May 27 20:37 opts.yaml
-rw-r--r-- 1 root root  45 May 27 20:37 pillar.jinja
-rw-r--r-- 1 root root 111 May 27 20:37 pillar.sls
-rw-r--r-- 1 root root  45 May 27 20:37 pillar.yaml
-rw-r--r-- 1 root root  41 May 27 20:37 salt.jinja
-rw-r--r-- 1 root root 105 May 27 20:37 salt.sls
-rw-r--r-- 1 root root  49 May 27 20:37 salt.yaml

"Normal" runs work, but local doesn't:

root@d10-saltgit-01:/srv# salt-call state.apply test_jinja.grains
local:
----------
          ID: test_jinja/grains/cmd.run
    Function: cmd.run
        Name: pwd
      Result: True
     Comment: Command "pwd" run
     Started: 21:13:51.801142
    Duration: 3.235 ms
     Changes:   
              ----------
              pid:
                  15193
              retcode:
                  0
              stderr:
              stdout:
                  /root

Summary for local
------------
Succeeded: 1 (changed=1)
Failed:    0
------------
Total states run:     1
Total run time:   3.235 ms

root@d10-saltgit-01:/srv# salt-call --local state.apply test_jinja.grains
[ERROR   ] Rendering exception occurred
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/dist-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 "/usr/local/lib/python3.7/dist-packages/salt/utils/jinja.py", line 219, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: ./grains.jinja

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 216, in render_tmpl
    output = render_str(tmplstr, context, tmplpath)
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 514, in render_jinja_tmpl
    "Jinja error: {}{}".format(exc, out), line, tmplstr, trace=tracestr
salt.exceptions.SaltRenderError: Jinja error: ./grains.jinja
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/dist-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 "/usr/local/lib/python3.7/dist-packages/salt/utils/jinja.py", line 219, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: ./grains.jinja

; line 1

---
{%- from "./grains.jinja" import grains with context %}    <======================

test_jinja/grains/cmd.run:
  cmd.run:
    - name: pwd

[...]
---
[CRITICAL] Rendering SLS 'base:test_jinja.grains' failed: Jinja error: ./grains.jinja
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/dist-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 "/usr/local/lib/python3.7/dist-packages/salt/utils/jinja.py", line 219, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: ./grains.jinja

; line 1

---
{%- from "./grains.jinja" import grains with context %}    <======================

test_jinja/grains/cmd.run:
  cmd.run:
    - name: pwd

[...]
---
local:
    Data failed to compile:
----------
    Rendering SLS 'base:test_jinja.grains' failed: Jinja error: ./grains.jinja
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/salt/utils/templates.py", line 469, in render_jinja_tmpl
    output = template.render(**decoded_context)
  File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/dist-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 "/usr/local/lib/python3.7/dist-packages/salt/utils/jinja.py", line 219, in get_source
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: ./grains.jinja

; line 1

---
{%- from "./grains.jinja" import grains with context %}    <======================

test_jinja/grains/cmd.run:
  cmd.run:
    - name: pwd

[...]
---

The lines in question were actually added to satisfy an existing test... which seems to have absolute paths in local mode. Changing that logic to check for an absolute path seems to solve the problem for both cases. I'll put in a PR presently.

marmarek added a commit to marmarek/salt that referenced this pull request Nov 17, 2022
This makes it detect cases where remote/local paths gets confused (like
in saltstack#60003 or saltstack#62043). Without using a container, remote paths works
locally too, so tests do not detect an issue.

Rename test_ssh_setup.py to test_ssh_setup_and_state.py to match its new
content.
pytest.mark.skip_on_windows is dropped as test_ssh_setup.py already has
necessary mark (dockerd present).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Phosphorus v3005.0 Release code name and version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] removed Jinja templates can still be loaded from cache
5 participants