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

Move _handle_no_log_values() out of basic.py #48628

Merged
merged 12 commits into from
Mar 4, 2019
53 changes: 7 additions & 46 deletions lib/ansible/module_utils/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@
from ansible.module_utils.pycompat24 import get_exception, literal_eval
from ansible.module_utils.common.parameters import (
handle_aliases,
list_deprecations,
list_no_log_values,
PASS_VARS,
)

Expand All @@ -173,17 +175,12 @@
from ansible.module_utils.common._utils import get_all_subclasses as _get_all_subclasses
from ansible.module_utils.parsing.convert_bool import BOOLEANS, BOOLEANS_FALSE, BOOLEANS_TRUE, boolean


# Note: When getting Sequence from collections, it matches with strings. If
# this matters, make sure to check for strings before checking for sequencetype
SEQUENCETYPE = frozenset, KeysView, Sequence
PASSWORD_MATCH = re.compile(r'^(?:.+[-_\s])?pass(?:[-_\s]?(?:word|phrase|wrd|wd)?)(?:[-_\s].+)?$', re.I)

_NUMBERTYPES = tuple(list(integer_types) + [float])

# Deprecated compat. Only kept in case another module used these names Using
# ansible.module_utils.six is preferred

NUMBERTYPES = _NUMBERTYPES
PASSWORD_MATCH = re.compile(r'^(?:.+[-_\s])?pass(?:[-_\s]?(?:word|phrase|wrd|wd)?)(?:[-_\s].+)?$', re.I)

imap = map

Expand Down Expand Up @@ -336,31 +333,6 @@ def json_dict_bytes_to_unicode(d, encoding='utf-8', errors='surrogate_or_strict'
return d


def return_values(obj):
""" Return native stringified values from datastructures.

For use with removing sensitive values pre-jsonification."""
if isinstance(obj, (text_type, binary_type)):
if obj:
yield to_native(obj, errors='surrogate_or_strict')
return
elif isinstance(obj, SEQUENCETYPE):
for element in obj:
for subelement in return_values(element):
yield subelement
elif isinstance(obj, Mapping):
for element in obj.items():
for subelement in return_values(element[1]):
yield subelement
elif isinstance(obj, (bool, NoneType)):
# This must come before int because bools are also ints
return
elif isinstance(obj, NUMBERTYPES):
yield to_native(obj, nonstring='simplerepr')
else:
raise TypeError('Unknown parameter type: %s, %s' % (type(obj), obj))


def _remove_values_conditions(value, no_log_strings, deferred_removals):
"""
Helper function for :meth:`remove_values`.
Expand Down Expand Up @@ -436,7 +408,7 @@ def _remove_values_conditions(value, no_log_strings, deferred_removals):
deferred_removals.append((value, new_value))
value = new_value

elif isinstance(value, tuple(chain(NUMBERTYPES, (bool, NoneType)))):
elif isinstance(value, tuple(chain(integer_types, (float, bool, NoneType)))):
stringy_value = to_native(value, encoding='utf-8', errors='surrogate_or_strict')
if stringy_value in no_log_strings:
return 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
Expand Down Expand Up @@ -1581,19 +1553,8 @@ def _handle_no_log_values(self, spec=None, param=None):
if param is None:
param = self.params

# Use the argspec to determine which args are no_log
for arg_name, arg_opts in spec.items():
if arg_opts.get('no_log', False):
# Find the value for the no_log'd param
no_log_object = param.get(arg_name, None)
if no_log_object:
self.no_log_values.update(return_values(no_log_object))

if arg_opts.get('removed_in_version') is not None and arg_name in param:
self._deprecations.append({
'msg': "Param '%s' is deprecated. See the module docs for more information" % arg_name,
'version': arg_opts.get('removed_in_version')
})
self.no_log_values.update(list_no_log_values(spec, param))
self._deprecations.extend(list_deprecations(spec, param))

def _check_arguments(self, check_invalid_arguments, spec=None, param=None, legal_inputs=None):
self._syslog_facility = 'LOG_USER'
Expand Down
71 changes: 71 additions & 0 deletions lib/ansible/module_utils/common/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,77 @@
}


def _return_datastructure_name(obj):
""" Return native stringified values from datastructures.

For use with removing sensitive values pre-jsonification."""
if isinstance(obj, (text_type, binary_type)):
if obj:
yield to_native(obj, errors='surrogate_or_strict')
return
elif isinstance(obj, Mapping):
for element in obj.items():
for subelement in _return_datastructure_name(element[1]):
yield subelement
elif is_iterable(obj):
for element in obj:
for subelement in _return_datastructure_name(element):
yield subelement
elif isinstance(obj, (bool, NoneType)):
# This must come before int because bools are also ints
return
elif isinstance(obj, tuple(list(integer_types) + [float])):
yield to_native(obj, nonstring='simplerepr')
else:
raise TypeError('Unknown parameter type: %s, %s' % (type(obj), obj))


def list_no_log_values(argument_spec, params):
"""Return set of no log values

:arg argument_spec: An argument spec dictionary from a module
:arg params: Dictionary of all module parameters

:returns: Set of strings that should be hidden from output::

{'secret_dict_value', 'secret_list_item_one', 'secret_list_item_two', 'secret_string'}
"""

no_log_values = set()
for arg_name, arg_opts in argument_spec.items():
if arg_opts.get('no_log', False):
# Find the value for the no_log'd param
no_log_object = params.get(arg_name, None)

if no_log_object:
no_log_values.update(_return_datastructure_name(no_log_object))

return no_log_values


def list_deprecations(argument_spec, params):
"""Return a list of deprecations

:arg argument_spec: An argument spec dictionary from a module
:arg params: Dictionary of all module parameters

:returns: List of dictionaries containing a message and version in which
the deprecated parameter will be removed, or an empty list::

[{'msg': "Param 'deptest' is deprecated. See the module docs for more information", 'version': '2.9'}]
"""

deprecations = []
for arg_name, arg_opts in argument_spec.items():
if arg_opts.get('removed_in_version') is not None and arg_name in params:
deprecations.append({
'msg': "Param '%s' is deprecated. See the module docs for more information" % arg_name,
'version': arg_opts.get('removed_in_version')
})

return deprecations


def handle_aliases(argument_spec, params):
"""Return a two item tuple. The first is a dictionary of aliases, the second is
a list of legal inputs."""
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/aireos/aireos.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command

Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/aruba/aruba.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import re

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command

Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/asa/asa.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, EntityCollection
from ansible.module_utils.connection import exec_command
from ansible.module_utils.connection import Connection, ConnectionError
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/cnos/cnos.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
HAS_LIB = False
from distutils.cmd import Command
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, EntityCollection
from ansible.module_utils.connection import Connection, exec_command
from ansible.module_utils.connection import ConnectionError
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/dellos10/dellos10.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import re

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command
from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/dellos6/dellos6.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import re

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command
from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine, ignore_line
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/dellos9/dellos9.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import re

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command
from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/enos/enos.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
# Lenovo Networking

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, EntityCollection
from ansible.module_utils.connection import Connection, exec_command
from ansible.module_utils.connection import ConnectionError
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/eos/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import time

from ansible.module_utils._text import to_text, to_native
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.network.common.config import NetworkConfig, dumps
from ansible.module_utils.network.common.utils import to_list, ComplexList
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/exos/exos.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#
import json
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list
from ansible.module_utils.connection import Connection

Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/ironware/ironware.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
__metaclass__ = type

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, EntityCollection
from ansible.module_utils.connection import Connection, exec_command

Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/junos/junos.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from contextlib import contextmanager
from copy import deepcopy

from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.network.common.netconf import NetconfConnection
from ansible.module_utils._text import to_text
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/nxos/nxos.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import re

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values, get_timestamp
from ansible.module_utils.basic import env_fallback, get_timestamp
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.common._collections_compat import Mapping
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/routeros/routeros.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#
import json
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import Connection, ConnectionError

Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/sros/sros.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import re

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command

Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/module_utils/network/vyos/vyos.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import json

from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.connection import Connection, ConnectionError

_DEVICE_CONFIGS = {}
Expand Down
1 change: 1 addition & 0 deletions test/units/executor/module_common/test_recursive_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
('common', '_collections_compat'),
('common', 'collections'),
('common', 'file'),
('common', 'collections'),
('common', 'parameters'),
('common', 'process'),
('common', 'sys_info'),
Expand Down
9 changes: 5 additions & 4 deletions test/units/module_utils/basic/test_no_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

from units.compat import unittest

from ansible.module_utils.basic import return_values, remove_values
from ansible.module_utils.basic import remove_values
from ansible.module_utils.common.parameters import _return_datastructure_name


class TestReturnValues(unittest.TestCase):
Expand Down Expand Up @@ -40,12 +41,12 @@ class TestReturnValues(unittest.TestCase):
('Toshio くらとみ', frozenset(['Toshio くらとみ'])),
)

def test_return_values(self):
def test_return_datastructure_name(self):
for data, expected in self.dataset:
self.assertEquals(frozenset(return_values(data)), expected)
self.assertEquals(frozenset(_return_datastructure_name(data)), expected)

def test_unknown_type(self):
self.assertRaises(TypeError, frozenset, return_values(object()))
self.assertRaises(TypeError, frozenset, _return_datastructure_name(object()))


class TestRemoveValues(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type

import pytest

from ansible.module_utils.common.parameters import list_deprecations


@pytest.fixture
def params():
return {
'name': 'bob',
'dest': '/etc/hosts',
'state': 'present',
'value': 5,
}


def test_list_deprecations():
argument_spec = {
'old': {'type': 'str', 'removed_in_version': '2.5'}
}

params = {
'name': 'rod',
'old': 'option',
}
result = list_deprecations(argument_spec, params)
for item in result:
assert item['msg'] == "Param 'old' is deprecated. See the module docs for more information"
assert item['version'] == '2.5'