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_gtm_wide_ip import (
20    ApiParameters, ModuleParameters, ModuleManager, ArgumentSpec
21)
22from ansible_collections.f5networks.f5_modules.plugins.module_utils.common import F5ModuleError
23from ansible_collections.f5networks.f5_modules.tests.unit.compat import unittest
24from ansible_collections.f5networks.f5_modules.tests.unit.compat.mock import Mock, patch
25from ansible_collections.f5networks.f5_modules.tests.unit.modules.utils import set_module_args
26
27
28fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
29fixture_data = {}
30
31
32def load_fixture(name):
33    path = os.path.join(fixture_path, name)
34
35    if path in fixture_data:
36        return fixture_data[path]
37
38    with open(path) as f:
39        data = f.read()
40
41    try:
42        data = json.loads(data)
43    except Exception:
44        pass
45
46    fixture_data[path] = data
47    return data
48
49
50class TestParameters(unittest.TestCase):
51    def test_module_parameters(self):
52        args = dict(
53            name='foo.baz.bar',
54            pool_lb_method='round-robin',
55        )
56        p = ModuleParameters(params=args)
57        assert p.name == 'foo.baz.bar'
58        assert p.pool_lb_method == 'round-robin'
59
60    def test_module_pools(self):
61        args = dict(
62            pools=[
63                dict(
64                    name='foo',
65                    ratio='100'
66                )
67            ]
68        )
69        p = ModuleParameters(params=args)
70        assert len(p.pools) == 1
71
72    def test_api_parameters(self):
73        args = dict(
74            name='foo.baz.bar',
75            poolLbMode='round-robin'
76        )
77        p = ApiParameters(params=args)
78        assert p.name == 'foo.baz.bar'
79        assert p.pool_lb_method == 'round-robin'
80
81    def test_module_not_fqdn_name(self):
82        args = dict(
83            name='foo',
84            lb_method='round-robin'
85        )
86        with pytest.raises(F5ModuleError) as excinfo:
87            p = ModuleParameters(params=args)
88            assert p.name == 'foo'
89        assert 'The provided name must be a valid FQDN' in str(excinfo.value)
90
91
92class TestModuleManager(unittest.TestCase):
93    def setUp(self):
94        self.spec = ArgumentSpec()
95        self.p1 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_gtm_wide_ip.module_provisioned')
96        self.m1 = self.p1.start()
97        self.m1.return_value = True
98        self.p2 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_gtm_wide_ip.tmos_version')
99        self.p3 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_gtm_wide_ip.send_teem')
100        self.m2 = self.p2.start()
101        self.m2.return_value = '14.1.0'
102        self.m3 = self.p3.start()
103        self.m3.return_value = True
104
105    def tearDown(self):
106        self.p1.stop()
107        self.p2.stop()
108        self.p3.stop()
109
110    def test_create_wideip(self, *args):
111        set_module_args(dict(
112            name='foo.baz.bar',
113            lb_method='round-robin',
114            type='a',
115            provider=dict(
116                server='localhost',
117                password='password',
118                user='admin'
119            )
120        ))
121
122        module = AnsibleModule(
123            argument_spec=self.spec.argument_spec,
124            supports_check_mode=self.spec.supports_check_mode
125        )
126
127        # Override methods in the specific type of manager
128        mm = ModuleManager(module=module)
129        mm.exists = Mock(return_value=False)
130        mm.create_on_device = Mock(return_value=True)
131
132        results = mm.exec_module()
133
134        assert results['changed'] is True
135        assert results['name'] == 'foo.baz.bar'
136        assert results['state'] == 'present'
137        assert results['lb_method'] == 'round-robin'
138
139    def test_create_wideip_with_pool(self, *args):
140        set_module_args(dict(
141            name='foo.baz.bar',
142            lb_method='round-robin',
143            type='a',
144            pools=[
145                dict(
146                    name='baz',
147                    ratio=10,
148                ),
149                dict(
150                    name='maz',
151                    ratio=10,
152                    order=1
153                ),
154                dict(
155                    name='vaz',
156                    ratio=11,
157                    order=2
158                )
159            ],
160            provider=dict(
161                server='localhost',
162                password='password',
163                user='admin'
164            )
165        ))
166
167        module = AnsibleModule(
168            argument_spec=self.spec.argument_spec,
169            supports_check_mode=self.spec.supports_check_mode
170        )
171
172        # Override methods in the specific type of manager
173        mm = ModuleManager(module=module)
174        mm.exists = Mock(return_value=False)
175        mm.create_on_device = Mock(return_value=True)
176
177        results = mm.exec_module()
178
179        assert results['changed'] is True
180        assert results['name'] == 'foo.baz.bar'
181        assert results['state'] == 'present'
182        assert results['lb_method'] == 'round-robin'
183