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_snat_pool import (
20    ModuleParameters, ApiParameters, 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        args = dict(
52            name='my-snat-pool',
53            state='present',
54            members=['10.10.10.10', '20.20.20.20'],
55            description='A SNAT pool description',
56            partition='Common'
57        )
58        p = ModuleParameters(params=args)
59        assert p.name == 'my-snat-pool'
60        assert p.state == 'present'
61        assert p.description == 'A SNAT pool description'
62        assert len(p.members) == 2
63        assert '/Common/10.10.10.10' in p.members
64        assert '/Common/20.20.20.20' in p.members
65
66    def test_api_parameters(self):
67        args = dict(
68            members=['/Common/10.10.10.10', '/foo/20.20.20.20']
69        )
70        p = ApiParameters(params=args)
71        assert len(p.members) == 2
72        assert '/Common/10.10.10.10' in p.members
73        assert '/foo/20.20.20.20' in p.members
74
75
76class TestManager(unittest.TestCase):
77    def setUp(self):
78        self.spec = ArgumentSpec()
79        self.p2 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_snat_pool.tmos_version')
80        self.p3 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_snat_pool.send_teem')
81        self.m2 = self.p2.start()
82        self.m2.return_value = '14.1.0'
83        self.m3 = self.p3.start()
84        self.m3.return_value = True
85
86    def tearDown(self):
87        self.p2.stop()
88        self.p3.stop()
89
90    def test_create_snat_pool(self, *args):
91        set_module_args(dict(
92            name='my-snat-pool',
93            state='present',
94            members=['10.10.10.10', '20.20.20.20'],
95            provider=dict(
96                server='localhost',
97                password='password',
98                user='admin'
99            )
100        ))
101
102        module = AnsibleModule(
103            argument_spec=self.spec.argument_spec,
104            supports_check_mode=self.spec.supports_check_mode,
105            required_if=self.spec.required_if
106        )
107        mm = ModuleManager(module=module)
108
109        # Override methods to force specific logic in the module to happen
110        mm.exists = Mock(side_effect=[False, True])
111        mm.create_on_device = Mock(return_value=True)
112
113        results = mm.exec_module()
114
115        assert results['changed'] is True
116        assert len(results['members']) == 2
117        assert '/Common/10.10.10.10' in results['members']
118        assert '/Common/20.20.20.20' in results['members']
119
120    def test_create_snat_pool_idempotent(self, *args):
121        set_module_args(dict(
122            name='asdasd',
123            state='present',
124            members=['1.1.1.1', '2.2.2.2'],
125            provider=dict(
126                server='localhost',
127                password='password',
128                user='admin'
129            )
130        ))
131
132        current = ApiParameters(params=load_fixture('load_ltm_snatpool.json'))
133
134        module = AnsibleModule(
135            argument_spec=self.spec.argument_spec,
136            supports_check_mode=self.spec.supports_check_mode,
137            required_if=self.spec.required_if
138        )
139        mm = ModuleManager(module=module)
140
141        # Override methods to force specific logic in the module to happen
142        mm.exists = Mock(side_effect=[True, True])
143        mm.read_current_from_device = Mock(return_value=current)
144
145        results = mm.exec_module()
146
147        assert results['changed'] is False
148
149    def test_update_snat_pool(self, *args):
150        set_module_args(dict(
151            name='asdasd',
152            state='present',
153            members=['30.30.30.30'],
154            provider=dict(
155                server='localhost',
156                password='password',
157                user='admin'
158            )
159        ))
160
161        current = ApiParameters(params=load_fixture('load_ltm_snatpool.json'))
162
163        module = AnsibleModule(
164            argument_spec=self.spec.argument_spec,
165            supports_check_mode=self.spec.supports_check_mode,
166            required_if=self.spec.required_if
167        )
168        mm = ModuleManager(module=module)
169
170        # Override methods to force specific logic in the module to happen
171        mm.read_current_from_device = Mock(return_value=current)
172        mm.update_on_device = Mock(return_value=True)
173        mm.exists = Mock(return_value=True)
174        mm.create_on_device = Mock(return_value=True)
175
176        results = mm.exec_module()
177
178        assert results['changed'] is True
179        assert len(results['members']) == 1
180        assert '/Common/30.30.30.30' in results['members']
181