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_device_ntp import (
20    Parameters, ModuleManager, ArgumentSpec
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        ntp = ['192.168.1.1', '192.168.1.2']
52        args = dict(
53            ntp_servers=ntp,
54            timezone='Arctic/Longyearbyen'
55        )
56
57        p = Parameters(params=args)
58        assert p.ntp_servers == ntp
59        assert p.timezone == 'Arctic/Longyearbyen'
60
61    def test_api_parameters(self):
62        ntp = ['192.168.1.1', '192.168.1.2']
63        args = dict(
64            servers=ntp,
65            timezone='Arctic/Longyearbyen'
66        )
67
68        p = Parameters(params=args)
69        assert p.ntp_servers == ntp
70        assert p.timezone == 'Arctic/Longyearbyen'
71
72
73class TestModuleManager(unittest.TestCase):
74
75    def setUp(self):
76        self.spec = ArgumentSpec()
77        self.p2 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_device_ntp.tmos_version')
78        self.p3 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_device_ntp.send_teem')
79        self.m2 = self.p2.start()
80        self.m2.return_value = '14.1.0'
81        self.m3 = self.p3.start()
82        self.m3.return_value = True
83
84    def tearDown(self):
85        self.p2.stop()
86        self.p3.stop()
87
88    def test_update_ntp_servers(self, *args):
89        ntp = ['10.1.1.1', '10.1.1.2']
90        set_module_args(
91            dict(
92                ntp_servers=ntp,
93                provider=dict(
94                    server='localhost',
95                    password='password',
96                    user='admin'
97                )
98            )
99        )
100
101        # Configure the parameters that would be returned by querying the
102        # remote device
103        current = Parameters(params=load_fixture('load_ntp.json'))
104
105        module = AnsibleModule(
106            argument_spec=self.spec.argument_spec,
107            supports_check_mode=self.spec.supports_check_mode,
108            required_one_of=self.spec.required_one_of
109        )
110        mm = ModuleManager(module=module)
111
112        # Override methods to force specific logic in the module to happen
113        mm.update_on_device = Mock(return_value=True)
114        mm.read_current_from_device = Mock(return_value=current)
115
116        results = mm.exec_module()
117        assert results['changed'] is True
118        assert results['ntp_servers'] == ntp
119
120    def test_update_timezone(self, *args):
121        set_module_args(
122            dict(
123                timezone='Arctic/Longyearbyen',
124                provider=dict(
125                    server='localhost',
126                    password='password',
127                    user='admin'
128                )
129            )
130        )
131
132        # Configure the parameters that would be returned by querying the
133        # remote device
134        current = Parameters(params=load_fixture('load_ntp.json'))
135
136        module = AnsibleModule(
137            argument_spec=self.spec.argument_spec,
138            supports_check_mode=self.spec.supports_check_mode,
139            required_one_of=self.spec.required_one_of
140        )
141        mm = ModuleManager(module=module)
142
143        # Override methods to force specific logic in the module to happen
144        mm.update_on_device = Mock(return_value=True)
145        mm.read_current_from_device = Mock(return_value=current)
146
147        results = mm.exec_module()
148        assert results['changed'] is True
149        assert results['timezone'] == 'Arctic/Longyearbyen'
150
151    def test_update_ntp_servers_and_timezone(self, *args):
152        ntp = ['10.1.1.1', '10.1.1.2']
153        set_module_args(
154            dict(
155                ntp_servers=ntp,
156                timezone='Arctic/Longyearbyen',
157                provider=dict(
158                    server='localhost',
159                    password='password',
160                    user='admin'
161                )
162            )
163        )
164
165        # Configure the parameters that would be returned by querying the
166        # remote device
167        current = Parameters(params=load_fixture('load_ntp.json'))
168
169        module = AnsibleModule(
170            argument_spec=self.spec.argument_spec,
171            supports_check_mode=self.spec.supports_check_mode,
172            required_one_of=self.spec.required_one_of
173        )
174        mm = ModuleManager(module=module)
175
176        # Override methods to force specific logic in the module to happen
177        mm.update_on_device = Mock(return_value=True)
178        mm.read_current_from_device = Mock(return_value=current)
179
180        results = mm.exec_module()
181        assert results['changed'] is True
182        assert results['ntp_servers'] == ntp
183        assert results['timezone'] == 'Arctic/Longyearbyen'
184
185    def test_absent_ntp_servers(self, *args):
186        ntp = []
187        set_module_args(
188            dict(
189                ntp_servers=ntp,
190                timezone='America/Los_Angeles',
191                state='absent',
192                provider=dict(
193                    server='localhost',
194                    password='password',
195                    user='admin'
196                )
197            )
198        )
199
200        # Configure the parameters that would be returned by querying the
201        # remote device
202        current = Parameters(params=load_fixture('load_ntp.json'))
203
204        module = AnsibleModule(
205            argument_spec=self.spec.argument_spec,
206            supports_check_mode=self.spec.supports_check_mode,
207            required_one_of=self.spec.required_one_of
208        )
209        mm = ModuleManager(module=module)
210
211        # Override methods to force specific logic in the module to happen
212        mm.absent_on_device = Mock(return_value=True)
213        mm.read_current_from_device = Mock(return_value=current)
214
215        results = mm.exec_module()
216        assert results['changed'] is True
217        assert results['ntp_servers'] == ntp
218        assert not hasattr(results, 'timezone')
219
220    def test_absent_timezone(self, *args):
221        set_module_args(
222            dict(
223                timezone='',
224                state='absent',
225                provider=dict(
226                    server='localhost',
227                    password='password',
228                    user='admin'
229                )
230            )
231        )
232
233        # Configure the parameters that would be returned by querying the
234        # remote device
235        current = Parameters(params=load_fixture('load_ntp.json'))
236
237        module = AnsibleModule(
238            argument_spec=self.spec.argument_spec,
239            supports_check_mode=self.spec.supports_check_mode,
240            required_one_of=self.spec.required_one_of
241        )
242        mm = ModuleManager(module=module)
243
244        # Override methods to force specific logic in the module to happen
245        mm.absent_on_device = Mock(return_value=True)
246        mm.read_current_from_device = Mock(return_value=current)
247
248        results = mm.exec_module()
249        assert results['changed'] is False
250