Compare commits

..

12 Commits

Author SHA1 Message Date
a1683d3dab New release v2.12.6 (#77864) 2022-05-23 11:46:35 -04:00
04ab182ef9 Update Ansible release version to v2.12.6rc1.post0. (#77813) 2022-05-16 15:04:47 -04:00
01cbef9476 New release v2.12.6rc1 (#77810) 2022-05-16 13:34:35 -04:00
48689b63e4 update version switcher to include 2.13 (#77786) (#77796)
(cherry picked from commit f5642cea28)
2022-05-13 15:04:36 -07:00
092d298b5c fix SELinux facts tests (#77708)
* make the pre-flight sniffing more robust to different failure conditions (was failing on Ubuntu 22.04 VMs)
* remove skip aliases (the test needs to function everywhere to assert that the selinux facts bits behave properly when it's N/A)

(cherry picked from commit 4ff10fcd31)
2022-05-10 16:40:42 -05:00
a9f17d0532 dont rely on path to set config defs for plugins (#77659) (#77695)
(cherry picked from commit a3cc6a581e)
2022-05-10 16:40:33 -05:00
4bde2d8a97 [stable-2.12] arg_spec - Return aliases in validation result and update aliases (#77576) (#77602)
* [stable-2.12] arg_spec - Return aliases in validation result and update aliases (#77576)

When looking up the `no_log` setting for a parameter that is an alias in
`AnsibleModule._log_invocation()`, the alias value will always be an
empty dictionary since `self.aliases` on the `AnsibleModule` instance is
never updated after initialization. Since the `no_log` setting is on the
canonical parameter not the alias, an incorrect warning is issued if the
parameter matches `PASSWORD_MATCH`.

This PR returns the aliases dictionary as an attribute of the
`ValidationResult` and updates the `aliases` attribute on the
`AnsibleModule` instance.
(cherry picked from commit 1b947eaf92)

Co-authored-by: Sam Doran <github@samdoran.com>

* Rewrite test comprehension for Python 2.6

* No need for list inside the dict constructor
2022-05-10 16:40:19 -05:00
625a99aa32 Prevent losing unsafe from lookups (#77609) (#77651)
This patch fixes a bug which under certain conditions results in data
returned from lookups not being marked as unsafe.

Each time Templar.do_template is invoked a new AnsibleContext is
created and stored effectively at two places:
1) as an instance variable in templar_obj.cur_context
2) as a local variable called new_context in do_template method of Templar

Due to custom functionality in Ansible's Context that allows for nested
templating it is possible that during resolving variable's value
template/do_template method is called recursively again, again creating
a new context. At that point the problem manifests itself because as
mentioned in 1) above the context is overwriten on the templar object
which means that any subsequent calls to _lookup will use the new
context to mark it as unsafe which is now different to the local
new_context which is used for testing for unsafe property.

The solution to the problem appears to be to restore the original
context inside do_template and also to eliminate the local variable
new_context to prevent problems in the future.

It appears that we don't have a better way of storing the context other
than as some form of global variable and so this appears to be the
"best" solution possible at this point. Hopefully data tagging will be
the solution here.

For more examples see unit and integration tests included in this patch.

Fixes #77535

(cherry picked from commit 3980eb8c09)
2022-05-09 14:57:55 -05:00
013be12888 varaiblemanager, more efficienet vars file reads (#77570) (#77595)
(cherry picked from commit 2c2a204dc6)
2022-05-09 14:57:35 -05:00
b667639c2c Update Ansible release version to v2.12.5.post0. (#77633) 2022-04-25 12:42:54 -04:00
b104478f17 New release v2.12.5 (#77628) 2022-04-25 10:34:11 -04:00
3ea4cdaddf Update Ansible release version to v2.12.5rc1.post0. (#77559) 2022-04-18 14:51:46 -07:00
24 changed files with 209 additions and 23 deletions

View File

@ -5,13 +5,31 @@ ansible-core 2.12 "Dazed and Confused" Release Notes
.. contents:: Topics
v2.12.5rc1
==========
v2.12.6
=======
Release Summary
---------------
| Release Date: 2022-04-18
| Release Date: 2022-05-23
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__
Bugfixes
--------
- Prevent losing unsafe on results returned from lookups (https://github.com/ansible/ansible/issues/77535)
- arg_spec - Fix incorrect ``no_log`` warning when a parameter alias is used (https://github.com/ansible/ansible/pull/77576)
- plugin loader will now load config data for plugin by name instead of by file to avoid issues with the same file being loaded under different names (fqcn + short name).
- variablemanager, more efficient read of vars files
v2.12.5
=======
Release Summary
---------------
| Release Date: 2022-04-25
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__

View File

@ -1392,6 +1392,17 @@ releases:
- nativejinjaunsafetext-yaml-representer.yml
- v2.12.4rc1_summary.yaml
release_date: '2022-03-21'
2.12.5:
changes:
release_summary: '| Release Date: 2022-04-25
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__
'
codename: Dazed and Confused
fragments:
- v2.12.5_summary.yaml
release_date: '2022-04-25'
2.12.5rc1:
changes:
bugfixes:
@ -1431,3 +1442,37 @@ releases:
- v2.12.5rc1_summary.yaml
- winrm-kinit-path.yml
release_date: '2022-04-18'
2.12.6:
changes:
release_summary: '| Release Date: 2022-05-23
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__
'
codename: Dazed and Confused
fragments:
- v2.12.6_summary.yaml
release_date: '2022-05-23'
2.12.6rc1:
changes:
bugfixes:
- Prevent losing unsafe on results returned from lookups (https://github.com/ansible/ansible/issues/77535)
- arg_spec - Fix incorrect ``no_log`` warning when a parameter alias is used
(https://github.com/ansible/ansible/pull/77576)
- plugin loader will now load config data for plugin by name instead of by file
to avoid issues with the same file being loaded under different names (fqcn
+ short name).
- variablemanager, more efficient read of vars files
release_summary: '| Release Date: 2022-05-16
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__
'
codename: Dazed and Confused
fragments:
- 77535-prevent-losing-unsafe-lookups.yml
- 77576-arg_spec-no_log-aliases.yml
- config_load_by_name.yml
- v2.12.6rc1_summary.yaml
- vm_more_efficient.yml
release_date: '2022-05-16'

View File

@ -0,0 +1,2 @@
bugfixes:
- Prevent losing unsafe on results returned from lookups (https://github.com/ansible/ansible/issues/77535)

View File

@ -0,0 +1,2 @@
bugfixes:
- arg_spec - Fix incorrect ``no_log`` warning when a parameter alias is used (https://github.com/ansible/ansible/pull/77576)

View File

@ -0,0 +1,2 @@
bugfixes:
- plugin loader will now load config data for plugin by name instead of by file to avoid issues with the same file being loaded under different names (fqcn + short name).

View File

@ -0,0 +1,3 @@
release_summary: |
| Release Date: 2022-04-25
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__

View File

@ -0,0 +1,3 @@
release_summary: |
| Release Date: 2022-05-23
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__

View File

@ -0,0 +1,3 @@
release_summary: |
| Release Date: 2022-05-16
| `Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`__

View File

@ -0,0 +1,2 @@
bugfixes:
- variablemanager, more efficient read of vars files

View File

@ -173,9 +173,9 @@ html_context = {
'github_root_dir': 'devel/lib/ansible',
'github_cli_version': 'devel/lib/ansible/cli/',
'current_version': version,
'latest_version': '2.12',
'latest_version': '2.13',
# list specifically out of order to make latest work
'available_versions': ('2.12', '2.11', '2.10', 'devel',),
'available_versions': ('2.13', '2.12', '2.11', 'devel',),
}
# Add extra CSS styles to the resulting HTML pages

View File

@ -508,6 +508,7 @@ class AnsibleModule(object):
self.validation_result = self.validator.validate(self.params)
self.params.update(self.validation_result.validated_parameters)
self.no_log_values.update(self.validation_result._no_log_values)
self.aliases.update(self.validation_result._aliases)
try:
error = self.validation_result.errors[0]

View File

@ -61,6 +61,7 @@ class ValidationResult:
self._validated_parameters = deepcopy(parameters)
self._deprecations = []
self._warnings = []
self._aliases = {}
self.errors = AnsibleValidationErrorMultiple()
"""
:class:`~ansible.module_utils.errors.AnsibleValidationErrorMultiple` containing all
@ -180,12 +181,11 @@ class ArgumentSpecValidator:
alias_warnings = []
alias_deprecations = []
try:
aliases = _handle_aliases(self.argument_spec, result._validated_parameters, alias_warnings, alias_deprecations)
result._aliases.update(_handle_aliases(self.argument_spec, result._validated_parameters, alias_warnings, alias_deprecations))
except (TypeError, ValueError) as e:
aliases = {}
result.errors.append(AliasError(to_native(e)))
legal_inputs = _get_legal_inputs(self.argument_spec, result._validated_parameters, aliases)
legal_inputs = _get_legal_inputs(self.argument_spec, result._validated_parameters, result._aliases)
for option, alias in alias_warnings:
result._warnings.append({'option': option, 'alias': alias})

View File

@ -395,7 +395,7 @@ class PluginLoader:
type_name = get_plugin_class(self.class_name)
# if type name != 'module_doc_fragment':
if type_name in C.CONFIGURABLE_PLUGINS:
if type_name in C.CONFIGURABLE_PLUGINS and not C.config.get_configuration_definition(type_name, name):
dstring = AnsibleLoader(getattr(module, 'DOCUMENTATION', ''), file_name=path).get_single_data()
if dstring:
add_fragments(dstring, path, fragment_loader=fragment_loader, is_module=(type_name == 'module'))
@ -825,10 +825,12 @@ class PluginLoader:
if path not in self._module_cache:
self._module_cache[path] = self._load_module_source(name, path)
self._load_config_defs(name, self._module_cache[path], path)
found_in_cache = False
self._load_config_defs(name, self._module_cache[path], path)
obj = getattr(self._module_cache[path], self.class_name)
if self.base_class:
# The import path is hardcoded and should be the right place,
# so we are not expecting an ImportError.
@ -955,15 +957,18 @@ class PluginLoader:
else:
full_name = basename
module = self._load_module_source(full_name, path)
self._load_config_defs(basename, module, path)
except Exception as e:
display.warning("Skipping plugin (%s) as it seems to be invalid: %s" % (path, to_text(e)))
continue
self._module_cache[path] = module
found_in_cache = False
else:
module = self._module_cache[path]
self._load_config_defs(basename, module, path)
try:
obj = getattr(self._module_cache[path], self.class_name)
obj = getattr(module, self.class_name)
except AttributeError as e:
display.warning("Skipping plugin (%s) as it seems to be invalid: %s" % (path, to_text(e)))
continue

View File

@ -19,6 +19,6 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__version__ = '2.12.5rc1'
__version__ = '2.12.6'
__author__ = 'Ansible, Inc.'
__codename__ = 'Dazed and Confused'

View File

@ -1146,15 +1146,19 @@ class Templar:
jvars = AnsibleJ2Vars(self, t.globals)
self.cur_context = new_context = t.new_context(jvars, shared=True)
rf = t.root_render_func(new_context)
# In case this is a recursive call to do_template we need to
# save/restore cur_context to prevent overriding __UNSAFE__.
cached_context = self.cur_context
self.cur_context = t.new_context(jvars, shared=True)
rf = t.root_render_func(self.cur_context)
try:
if self.jinja2_native:
res = ansible_native_concat(rf)
else:
res = j2_concat(rf)
unsafe = getattr(new_context, 'unsafe', False)
unsafe = getattr(self.cur_context, 'unsafe', False)
if unsafe:
res = wrap_var(res)
except TypeError as te:
@ -1165,6 +1169,8 @@ class Templar:
else:
display.debug("failing because of a type error, template data is: %s" % to_text(data))
raise AnsibleError("Unexpected templating type error occurred on (%s): %s" % (to_native(data), to_native(te)))
finally:
self.cur_context = cached_context
if self.jinja2_native and not isinstance(res, string_types):
return res

View File

@ -357,8 +357,7 @@ class VariableManager:
try:
play_search_stack = play.get_search_path()
found_file = real_file = self._loader.path_dwim_relative_stack(play_search_stack, 'vars', vars_file)
decrypted_file = self._loader.get_real_file(found_file)
data = preprocess_vars(self._loader.load_from_file(decrypted_file, unsafe=True))
data = preprocess_vars(self._loader.load_from_file(found_file, unsafe=True, cache=False))
if data is not None:
for item in data:
all_vars = _combine_and_track(all_vars, item, "play vars_files from '%s'" % vars_file)

View File

@ -1,5 +1 @@
shippable/posix/group1
skip/osx
skip/macos
skip/freebsd
skip/docker

View File

@ -18,11 +18,12 @@
- name: check selinux policy type
shell: grep '^SELINUXTYPE=' /etc/selinux/config | cut -d'=' -f2
ignore_errors: yes
register: r
- set_fact:
selinux_policytype: "{{ r.stdout_lines[0] }}"
when: r.changed
when: r is success and r.stdout_lines
- assert:
that:

View File

@ -22,3 +22,6 @@ do
exit 1
fi
done
# test config loading
ansible-playbook use_coll_name.yml -i ../../inventory -e 'ansible_connection=ansible.builtin.ssh' "$@"

View File

@ -0,0 +1,7 @@
- name: ensure configuration is loaded when we use FQCN and have already loaded using 'short namne' (which is case will all builtin connection plugins)
hosts: all
gather_facts: false
tasks:
- name: relies on extra var being passed in with connection and fqcn
ping:
ignore_unreachable: True

View File

@ -17,3 +17,48 @@
that:
- this_always_safe == imunsafe
- imunsafe == this_was_unsafe.strip()
- hosts: localhost
gather_facts: false
vars:
output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}"
tasks:
- set_fact:
unsafe_foo: "{{ lookup('list', var0) }}"
vars:
var0: "{{ var1 }}"
var1:
- unsafe
- assert:
that:
- "{{ unsafe_foo[0] | type_debug == 'AnsibleUnsafeText' }}"
- block:
- copy:
dest: "{{ file_name }}"
content: !unsafe "{{ i_should_not_be_templated }}"
- set_fact:
file_content: "{{ lookup('file', file_name) }}"
- assert:
that:
- not file_content is contains('unsafe')
- set_fact:
file_content: "{{ lookup('file', file_name_tmpl) }}"
vars:
file_name_tmpl: "{{ file_name }}"
- assert:
that:
- not file_content is contains('unsafe')
vars:
file_name: "{{ output_dir }}/unsafe_file"
i_should_not_be_templated: unsafe
always:
- file:
dest: "{{ file_name }}"
state: absent

View File

@ -709,3 +709,16 @@ def test_no_log_none(stdin, capfd):
# makes it into am.no_log_values. Instead we can check for the warning
# emitted by am._log_invocation.
assert len(get_warning_messages()) > 0
@pytest.mark.parametrize("stdin", [{"pass": "testing"}], indirect=["stdin"])
def test_no_log_alias(stdin, capfd):
"""Given module parameters that use an alias for a parameter that matches
PASSWORD_MATCH and has no_log=True set, a warning should not be issued.
"""
arg_spec = {
"other_pass": {"no_log": True, "aliases": ["pass"]},
}
am = basic.AnsibleModule(arg_spec)
assert len(get_warning_messages()) == 0

View File

@ -95,6 +95,11 @@ def test_aliases(arg_spec, parameters, expected, deprecation, warning):
assert isinstance(result, ValidationResult)
assert result.validated_parameters == expected
assert result.error_messages == []
assert result._aliases == dict(
(alias, param)
for param, value in arg_spec.items()
for alias in value.get("aliases", [])
)
if deprecation:
assert deprecation == result._deprecations[0]

View File

@ -444,3 +444,28 @@ class TestAnsibleContext(BaseTemplar, unittest.TestCase):
def test_is_unsafe(self):
context = self._context()
self.assertFalse(context._is_unsafe(AnsibleUndefined()))
def test_unsafe_lookup():
res = Templar(
None,
variables={
'var0': '{{ var1 }}',
'var1': ['unsafe'],
}
).template('{{ lookup("list", var0) }}')
assert getattr(res[0], '__UNSAFE__', False)
def test_unsafe_lookup_no_conversion():
res = Templar(
None,
variables={
'var0': '{{ var1 }}',
'var1': ['unsafe'],
}
).template(
'{{ lookup("list", var0) }}',
convert_data=False,
)
assert getattr(res, '__UNSAFE__', False)