1# -*- coding: utf-8 -*-
2# Copyright (c) 2019 Ansible Project
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
5from __future__ import absolute_import, division, print_function
6__metaclass__ = type
7
8import pytest
9
10from ansible.module_utils.common.parameters import list_no_log_values
11
12
13@pytest.fixture
14def argument_spec():
15    # Allow extra specs to be passed to the fixture, which will be added to the output
16    def _argument_spec(extra_opts=None):
17        spec = {
18            'secret': {'type': 'str', 'no_log': True},
19            'other_secret': {'type': 'str', 'no_log': True},
20            'state': {'type': 'str'},
21            'value': {'type': 'int'},
22        }
23
24        if extra_opts:
25            spec.update(extra_opts)
26
27        return spec
28
29    return _argument_spec
30
31
32@pytest.fixture
33def module_parameters():
34    # Allow extra parameters to be passed to the fixture, which will be added to the output
35    def _module_parameters(extra_params=None):
36        params = {
37            'secret': 'under',
38            'other_secret': 'makeshift',
39            'state': 'present',
40            'value': 5,
41        }
42
43        if extra_params:
44            params.update(extra_params)
45
46        return params
47
48    return _module_parameters
49
50
51def test_list_no_log_values_no_secrets(module_parameters):
52    argument_spec = {
53        'other_secret': {'type': 'str', 'no_log': False},
54        'state': {'type': 'str'},
55        'value': {'type': 'int'},
56    }
57    expected = set()
58    assert expected == list_no_log_values(argument_spec, module_parameters)
59
60
61def test_list_no_log_values(argument_spec, module_parameters):
62    expected = set(('under', 'makeshift'))
63    assert expected == list_no_log_values(argument_spec(), module_parameters())
64
65
66@pytest.mark.parametrize('extra_params', [
67    {'subopt1': 1},
68    {'subopt1': 3.14159},
69    {'subopt1': ['one', 'two']},
70    {'subopt1': ('one', 'two')},
71])
72def test_list_no_log_values_invalid_suboptions(argument_spec, module_parameters, extra_params):
73    extra_opts = {
74        'subopt1': {
75            'type': 'dict',
76            'options': {
77                'sub_1_1': {},
78            }
79        }
80    }
81
82    with pytest.raises(TypeError, match=r"(Value '.*?' in the sub parameter field '.*?' must by a dict, not '.*?')"
83                                        r"|(dictionary requested, could not parse JSON or key=value)"):
84        list_no_log_values(argument_spec(extra_opts), module_parameters(extra_params))
85
86
87def test_list_no_log_values_suboptions(argument_spec, module_parameters):
88    extra_opts = {
89        'subopt1': {
90            'type': 'dict',
91            'options': {
92                'sub_1_1': {'no_log': True},
93                'sub_1_2': {'type': 'list'},
94            }
95        }
96    }
97
98    extra_params = {
99        'subopt1': {
100            'sub_1_1': 'bagel',
101            'sub_1_2': ['pebble'],
102        }
103    }
104
105    expected = set(('under', 'makeshift', 'bagel'))
106    assert expected == list_no_log_values(argument_spec(extra_opts), module_parameters(extra_params))
107
108
109def test_list_no_log_values_sub_suboptions(argument_spec, module_parameters):
110    extra_opts = {
111        'sub_level_1': {
112            'type': 'dict',
113            'options': {
114                'l1_1': {'no_log': True},
115                'l1_2': {},
116                'l1_3': {
117                    'type': 'dict',
118                    'options': {
119                        'l2_1': {'no_log': True},
120                        'l2_2': {},
121                    }
122                }
123            }
124        }
125    }
126
127    extra_params = {
128        'sub_level_1': {
129            'l1_1': 'saucy',
130            'l1_2': 'napped',
131            'l1_3': {
132                'l2_1': 'corporate',
133                'l2_2': 'tinsmith',
134            }
135        }
136    }
137
138    expected = set(('under', 'makeshift', 'saucy', 'corporate'))
139    assert expected == list_no_log_values(argument_spec(extra_opts), module_parameters(extra_params))
140
141
142def test_list_no_log_values_suboptions_list(argument_spec, module_parameters):
143    extra_opts = {
144        'subopt1': {
145            'type': 'list',
146            'elements': 'dict',
147            'options': {
148                'sub_1_1': {'no_log': True},
149                'sub_1_2': {},
150            }
151        }
152    }
153
154    extra_params = {
155        'subopt1': [
156            {
157                'sub_1_1': ['playroom', 'luxury'],
158                'sub_1_2': 'deuce',
159            },
160            {
161                'sub_1_2': ['squishier', 'finished'],
162            }
163        ]
164    }
165
166    expected = set(('under', 'makeshift', 'playroom', 'luxury'))
167    assert expected == list_no_log_values(argument_spec(extra_opts), module_parameters(extra_params))
168
169
170def test_list_no_log_values_sub_suboptions_list(argument_spec, module_parameters):
171    extra_opts = {
172        'subopt1': {
173            'type': 'list',
174            'elements': 'dict',
175            'options': {
176                'sub_1_1': {'no_log': True},
177                'sub_1_2': {},
178                'subopt2': {
179                    'type': 'list',
180                    'elements': 'dict',
181                    'options': {
182                        'sub_2_1': {'no_log': True, 'type': 'list'},
183                        'sub_2_2': {},
184                    }
185                }
186            }
187        }
188    }
189
190    extra_params = {
191        'subopt1': {
192            'sub_1_1': ['playroom', 'luxury'],
193            'sub_1_2': 'deuce',
194            'subopt2': [
195                {
196                    'sub_2_1': ['basis', 'gave'],
197                    'sub_2_2': 'liquid',
198                },
199                {
200                    'sub_2_1': ['composure', 'thumping']
201                },
202            ]
203        }
204    }
205
206    expected = set(('under', 'makeshift', 'playroom', 'luxury', 'basis', 'gave', 'composure', 'thumping'))
207    assert expected == list_no_log_values(argument_spec(extra_opts), module_parameters(extra_params))
208
209
210@pytest.mark.parametrize('extra_params, expected', (
211    ({'subopt_dict': 'dict_subopt1=rekindle-scandal,dict_subopt2=subgroupavenge'}, ('rekindle-scandal',)),
212    ({'subopt_dict': 'dict_subopt1=aversion-mutable dict_subopt2=subgroupavenge'}, ('aversion-mutable',)),
213    ({'subopt_dict': ['dict_subopt1=blip-marine,dict_subopt2=subgroupavenge', 'dict_subopt1=tipping,dict_subopt2=hardening']}, ('blip-marine', 'tipping')),
214))
215def test_string_suboptions_as_string(argument_spec, module_parameters, extra_params, expected):
216    extra_opts = {
217        'subopt_dict': {
218            'type': 'dict',
219            'options': {
220                'dict_subopt1': {'no_log': True},
221                'dict_subopt2': {},
222            },
223        },
224    }
225
226    result = set(('under', 'makeshift'))
227    result.update(expected)
228    assert result == list_no_log_values(argument_spec(extra_opts), module_parameters(extra_params))
229