This scraps the old tests and writes an entirely new test class with
over a dozen new tests, covering all the new functionality added in the
file.patch state rewrite.
This is a full rewrite. Previously, this state required the user to
provide the hash of the patched file, but this is no longer necessary as
the state is now able to check whether or not the patch will apply
cleanly without actually making any changes. The following is a summary
of the changes made in this rewrite:
- The `hash` and `dry_run_first` arguments are now ignored and generate
a warning in the state return if used.
- The path being patched can now be a directory or a file, instead of
just a file.
- The patch file is now downloaded by calling `file.managed`. This
expands the potential file sources to include remote files (with all
the hash verification features provided by `file.managed`), and also
adds templating support.
- Instead of blindly running the `file.patch` remote-execution function
and then checking that the patched result matches a pre-provided
result, the state will run a non-dry-run `file.patch` with all patch
output redirected to a temp file. This does 2 things: 1) It keeps any
changes from being made, and 2) creates a reject file (which is not
done when `--dry-run` is used with `patch`). This initial `file.patch`
will tell us whether or not the patch would apply cleanly. If it does
not, then we attempt to reverse-apply the rejected hunks using
`--dry-run`, and if they apply cleanly then we know that the patch has
already been applied and can exit with a `True` result. This means
that we only actually attempt to apply the patch if we know if will
apply cleanly, and prevents us from leaving the file(s) being patched
in a partially-patched state, improving greatly the idempotence of the
state.
prepare test case:
# echo '{% import_yaml "a.yaml" as a with context %}' > a.sls
# echo 'a: {{ "now"|strftime }}' > a.yaml
remove 'import salt.utils.daeutils' from salt/utils/templates.py, then run
# salt-call state.sls a
[CRITICAL] Rendering SLS 'base:a' failed: Traceback (most recent call last):
File "/usr/lib64/python2.7/site-packages/salt/utils/templates.py", line 169, in render_tmpl
output = render_str(tmplstr, context, tmplpath)
File "/usr/lib64/python2.7/site-packages/salt/utils/templates.py", line 395, in render_jinja_tmpl
line, out = _get_jinja_error(trace, context=decoded_context)
File "/usr/lib64/python2.7/site-packages/salt/utils/templates.py", line 248, in _get_jinja_error
line = _get_jinja_error_line(trace)
File "/usr/lib64/python2.7/site-packages/salt/utils/templates.py", line 231, in _get_jinja_error_line
return _get_jinja_error_slug(tb_data)[1]
TypeError: 'NoneType' object has no attribute '__getitem__'
after apply the patch:
# salt-call state.sls a
Traceback (most recent call last):
File "/usr/lib64/python2.7/site-packages/salt/utils/templates.py", line 169, in render_tmpl
output = render_str(tmplstr, context, tmplpath)
File "/usr/lib64/python2.7/site-packages/salt/utils/templates.py", line 402, in render_jinja_tmpl
tmplstr)
SaltRenderError: Jinja syntax error: no filter named 'strftime'
/var/cache/salt/minion/files/base/a.yaml(1):
---
a: {{ "now"|strftime }} <======================
---
[CRITICAL] Rendering SLS 'base:a' failed: Jinja syntax error: no filter named 'strftime'
/var/cache/salt/minion/files/base/a.yaml(1):
---
a: {{ "now"|strftime }} <======================
---
which shows accurate information for debug.
The commit ba7d00f5 change _cpv_to_cp inner implementation, but the
original parameter cpv is not changed, its format is `<p>-<v>`, and
`dep_getkey` need format for `=<p>-<v>` if `cpv` with version, so it cause
`InvalidAtom` exception and actually return cpv itself. So I add the
original implementation back to fix this problem and still keep
`dep_getkey` if the cpv format will be fixed in the future