1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2017 F5 Networks Inc.
4# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
6from __future__ import (absolute_import, division, print_function)
7__metaclass__ = type
8
9import os
10import json
11import pytest
12import sys
13
14if sys.version_info < (2, 7):
15    pytestmark = pytest.mark.skip("F5 Ansible modules require Python >= 2.7")
16
17from ansible.module_utils.basic import AnsibleModule
18
19from ansible_collections.f5networks.f5_modules.plugins.modules.bigip_provision import (
20    ModuleParameters, ModuleManager, ArgumentSpec, ApiParameters
21)
22from ansible_collections.f5networks.f5_modules.tests.unit.compat import unittest
23from ansible_collections.f5networks.f5_modules.tests.unit.compat.mock import Mock, patch
24from ansible_collections.f5networks.f5_modules.tests.unit.modules.utils import set_module_args
25
26
27fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
28fixture_data = {}
29
30
31def load_fixture(name):
32    path = os.path.join(fixture_path, name)
33
34    if path in fixture_data:
35        return fixture_data[path]
36
37    with open(path) as f:
38        data = f.read()
39
40    try:
41        data = json.loads(data)
42    except Exception:
43        pass
44
45    fixture_data[path] = data
46    return data
47
48
49class TestParameters(unittest.TestCase):
50    def test_module_parameters(self):
51        args = dict(
52            module='gtm',
53            level='nominal',
54        )
55        p = ModuleParameters(params=args)
56        assert p.module == 'gtm'
57        assert p.level == 'nominal'
58
59    def test_api_parameters(self):
60        args = load_fixture('load_sys_provision_default.json')
61        p = ApiParameters(params=args)
62        assert p.level == 'dedicated'
63        assert p.memory == 'medium'
64        assert p.module == 'urldb'
65
66    def test_module_parameters_level_minimum(self):
67        args = dict(
68            level='minimum',
69        )
70        p = ModuleParameters(params=args)
71        assert p.level == 'minimum'
72
73    def test_module_parameters_level_nominal(self):
74        args = dict(
75            level='nominal',
76        )
77        p = ModuleParameters(params=args)
78        assert p.level == 'nominal'
79
80    def test_module_parameters_level_dedicated(self):
81        args = dict(
82            level='dedicated',
83        )
84        p = ModuleParameters(params=args)
85        assert p.level == 'dedicated'
86
87    def test_module_parameters_memory_small(self):
88        args = dict(
89            module='mgmt',
90            memory='small',
91        )
92        p = ModuleParameters(params=args)
93        assert p.memory == 0
94
95    def test_module_parameters_memory_medium(self):
96        args = dict(
97            module='mgmt',
98            memory='medium',
99        )
100        p = ModuleParameters(params=args)
101        assert p.memory == 200
102
103    def test_module_parameters_memory_large(self):
104        args = dict(
105            module='mgmt',
106            memory='large',
107        )
108        p = ModuleParameters(params=args)
109        assert p.memory == 500
110
111    def test_module_parameters_memory_700(self):
112        args = dict(
113            module='mgmt',
114            memory=700,
115        )
116        p = ModuleParameters(params=args)
117        assert p.memory == 700
118
119    def test_module_parameters_mod_afm(self):
120        args = dict(
121            module='afm',
122        )
123        p = ModuleParameters(params=args)
124        assert p.module == 'afm'
125
126    def test_module_parameters_mod_am(self):
127        args = dict(
128            module='am',
129        )
130        p = ModuleParameters(params=args)
131        assert p.module == 'am'
132
133    def test_module_parameters_mod_sam(self):
134        args = dict(
135            module='sam',
136        )
137        p = ModuleParameters(params=args)
138        assert p.module == 'sam'
139
140    def test_module_parameters_mod_asm(self):
141        args = dict(
142            module='asm',
143        )
144        p = ModuleParameters(params=args)
145        assert p.module == 'asm'
146
147    def test_module_parameters_mod_avr(self):
148        args = dict(
149            module='avr',
150        )
151        p = ModuleParameters(params=args)
152        assert p.module == 'avr'
153
154    def test_module_parameters_mod_fps(self):
155        args = dict(
156            module='fps',
157        )
158        p = ModuleParameters(params=args)
159        assert p.module == 'fps'
160
161    def test_module_parameters_mod_gtm(self):
162        args = dict(
163            module='gtm',
164        )
165        p = ModuleParameters(params=args)
166        assert p.module == 'gtm'
167
168    def test_module_parameters_mod_lc(self):
169        args = dict(
170            module='lc',
171        )
172        p = ModuleParameters(params=args)
173        assert p.module == 'lc'
174
175    def test_module_parameters_mod_pem(self):
176        args = dict(
177            module='pem',
178        )
179        p = ModuleParameters(params=args)
180        assert p.module == 'pem'
181
182    def test_module_parameters_mod_swg(self):
183        args = dict(
184            module='swg',
185        )
186        p = ModuleParameters(params=args)
187        assert p.module == 'swg'
188
189    def test_module_parameters_mod_ilx(self):
190        args = dict(
191            module='ilx',
192        )
193        p = ModuleParameters(params=args)
194        assert p.module == 'ilx'
195
196    def test_module_parameters_mod_apm(self):
197        args = dict(
198            module='apm',
199        )
200        p = ModuleParameters(params=args)
201        assert p.module == 'apm'
202
203    def test_module_parameters_mod_mgmt(self):
204        args = dict(
205            module='mgmt',
206        )
207        p = ModuleParameters(params=args)
208        assert p.module == 'mgmt'
209
210    def test_module_parameters_mod_sslo(self):
211        args = dict(
212            module='sslo',
213        )
214        p = ModuleParameters(params=args)
215        assert p.module == 'sslo'
216
217    def test_module_parameters_mod_urldb(self):
218        args = dict(
219            module='urldb',
220        )
221        p = ModuleParameters(params=args)
222        assert p.module == 'urldb'
223
224
225class TestManager(unittest.TestCase):
226
227    def setUp(self):
228        self.spec = ArgumentSpec()
229        self.patcher1 = patch('time.sleep')
230        self.patcher1.start()
231        self.p2 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_provision.tmos_version')
232        self.p3 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_provision.send_teem')
233        self.m2 = self.p2.start()
234        self.m2.return_value = '14.1.0'
235        self.m3 = self.p3.start()
236        self.m3.return_value = True
237
238    def tearDown(self):
239        self.p2.stop()
240        self.p3.stop()
241        self.patcher1.stop()
242
243    def test_provision_one_module_default_level(self, *args):
244        # Configure the arguments that would be sent to the Ansible module
245        set_module_args(dict(
246            module='gtm',
247            provider=dict(
248                server='localhost',
249                password='password',
250                user='admin'
251            )
252        ))
253
254        # Configure the parameters that would be returned by querying the
255        # remote device
256        current = ModuleParameters(
257            dict(
258                module='gtm',
259                level='none'
260            )
261        )
262        module = AnsibleModule(
263            argument_spec=self.spec.argument_spec,
264            supports_check_mode=self.spec.supports_check_mode,
265        )
266        mm = ModuleManager(module=module)
267
268        # Override methods to force specific logic in the module to happen
269        mm.update_on_device = Mock(return_value=True)
270        mm.read_current_from_device = Mock(return_value=current)
271        mm.reboot_device = Mock(return_value=True)
272        mm.save_on_device = Mock(return_value=True)
273
274        # this forced sleeping can cause these tests to take 15
275        # or more seconds to run. This is deliberate.
276        mm._is_mprov_running_on_device = Mock(side_effect=[True, False, False, False, False])
277        mm._is_rest_available = Mock(side_effect=[False, False, True, True, True])
278
279        results = mm.exec_module()
280
281        assert results['changed'] is True
282        assert results['level'] == 'nominal'
283
284    def test_provision_all_modules(self, *args):
285        modules = [
286            'afm', 'am', 'sam', 'asm', 'avr', 'fps',
287            'gtm', 'lc', 'ltm', 'pem', 'swg', 'ilx',
288            'apm', 'mgmt', 'sslo', 'urldb',
289        ]
290
291        for module in modules:
292            # Configure the arguments that would be sent to the Ansible module
293            set_module_args(dict(
294                module=module,
295                provider=dict(
296                    server='localhost',
297                    password='password',
298                    user='admin'
299                )
300            ))
301
302            with patch('ansible.module_utils.basic.AnsibleModule.fail_json') as mo:
303                AnsibleModule(
304                    argument_spec=self.spec.argument_spec,
305                    supports_check_mode=self.spec.supports_check_mode,
306                )
307                mo.assert_not_called()
308