1# Copyright 2019 Fortinet, Inc.
2#
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation, either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with Ansible.  If not, see <https://www.gnu.org/licenses/>.
15
16# Make coding more python3-ish
17from __future__ import (absolute_import, division, print_function)
18__metaclass__ = type
19
20import os
21import json
22import pytest
23from mock import ANY
24from ansible.module_utils.network.fortios.fortios import FortiOSHandler
25
26try:
27    from ansible.modules.network.fortios import fortios_firewall_vip46
28except ImportError:
29    pytest.skip("Could not load required modules for testing", allow_module_level=True)
30
31
32@pytest.fixture(autouse=True)
33def connection_mock(mocker):
34    connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_vip46.Connection')
35    return connection_class_mock
36
37
38fos_instance = FortiOSHandler(connection_mock)
39
40
41def test_firewall_vip46_creation(mocker):
42    schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
43
44    set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
45    set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
46
47    input_data = {
48        'username': 'admin',
49        'state': 'present',
50        'firewall_vip46': {
51            'arp_reply': 'disable',
52            'color': '4',
53            'comment': 'Comment.',
54            'extip': 'test_value_6',
55            'extport': 'test_value_7',
56            'id': '8',
57            'ldb_method': 'static',
58            'mappedip': 'test_value_10',
59            'mappedport': 'test_value_11',
60            'name': 'default_name_12',
61            'portforward': 'disable',
62            'protocol': 'tcp',
63            'server_type': 'http',
64            'type': 'static-nat',
65            'uuid': 'test_value_17'
66        },
67        'vdom': 'root'}
68
69    is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
70
71    expected_data = {
72        'arp-reply': 'disable',
73        'color': '4',
74        'comment': 'Comment.',
75        'extip': 'test_value_6',
76        'extport': 'test_value_7',
77        'id': '8',
78        'ldb-method': 'static',
79        'mappedip': 'test_value_10',
80        'mappedport': 'test_value_11',
81        'name': 'default_name_12',
82                'portforward': 'disable',
83                'protocol': 'tcp',
84                'server-type': 'http',
85                'type': 'static-nat',
86                'uuid': 'test_value_17'
87    }
88
89    set_method_mock.assert_called_with('firewall', 'vip46', data=expected_data, vdom='root')
90    schema_method_mock.assert_not_called()
91    assert not is_error
92    assert changed
93    assert response['status'] == 'success'
94    assert response['http_status'] == 200
95
96
97def test_firewall_vip46_creation_fails(mocker):
98    schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
99
100    set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
101    set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
102
103    input_data = {
104        'username': 'admin',
105        'state': 'present',
106        'firewall_vip46': {
107            'arp_reply': 'disable',
108            'color': '4',
109            'comment': 'Comment.',
110            'extip': 'test_value_6',
111            'extport': 'test_value_7',
112            'id': '8',
113            'ldb_method': 'static',
114            'mappedip': 'test_value_10',
115            'mappedport': 'test_value_11',
116            'name': 'default_name_12',
117            'portforward': 'disable',
118            'protocol': 'tcp',
119            'server_type': 'http',
120            'type': 'static-nat',
121            'uuid': 'test_value_17'
122        },
123        'vdom': 'root'}
124
125    is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
126
127    expected_data = {
128        'arp-reply': 'disable',
129        'color': '4',
130        'comment': 'Comment.',
131        'extip': 'test_value_6',
132        'extport': 'test_value_7',
133        'id': '8',
134        'ldb-method': 'static',
135        'mappedip': 'test_value_10',
136        'mappedport': 'test_value_11',
137        'name': 'default_name_12',
138                'portforward': 'disable',
139                'protocol': 'tcp',
140                'server-type': 'http',
141                'type': 'static-nat',
142                'uuid': 'test_value_17'
143    }
144
145    set_method_mock.assert_called_with('firewall', 'vip46', data=expected_data, vdom='root')
146    schema_method_mock.assert_not_called()
147    assert is_error
148    assert not changed
149    assert response['status'] == 'error'
150    assert response['http_status'] == 500
151
152
153def test_firewall_vip46_removal(mocker):
154    schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
155
156    delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
157    delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
158
159    input_data = {
160        'username': 'admin',
161        'state': 'absent',
162        'firewall_vip46': {
163            'arp_reply': 'disable',
164            'color': '4',
165            'comment': 'Comment.',
166            'extip': 'test_value_6',
167            'extport': 'test_value_7',
168            'id': '8',
169            'ldb_method': 'static',
170            'mappedip': 'test_value_10',
171            'mappedport': 'test_value_11',
172            'name': 'default_name_12',
173            'portforward': 'disable',
174            'protocol': 'tcp',
175            'server_type': 'http',
176            'type': 'static-nat',
177            'uuid': 'test_value_17'
178        },
179        'vdom': 'root'}
180
181    is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
182
183    delete_method_mock.assert_called_with('firewall', 'vip46', mkey=ANY, vdom='root')
184    schema_method_mock.assert_not_called()
185    assert not is_error
186    assert changed
187    assert response['status'] == 'success'
188    assert response['http_status'] == 200
189
190
191def test_firewall_vip46_deletion_fails(mocker):
192    schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
193
194    delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
195    delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
196
197    input_data = {
198        'username': 'admin',
199        'state': 'absent',
200        'firewall_vip46': {
201            'arp_reply': 'disable',
202            'color': '4',
203            'comment': 'Comment.',
204            'extip': 'test_value_6',
205            'extport': 'test_value_7',
206            'id': '8',
207            'ldb_method': 'static',
208            'mappedip': 'test_value_10',
209            'mappedport': 'test_value_11',
210            'name': 'default_name_12',
211            'portforward': 'disable',
212            'protocol': 'tcp',
213            'server_type': 'http',
214            'type': 'static-nat',
215            'uuid': 'test_value_17'
216        },
217        'vdom': 'root'}
218
219    is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
220
221    delete_method_mock.assert_called_with('firewall', 'vip46', mkey=ANY, vdom='root')
222    schema_method_mock.assert_not_called()
223    assert is_error
224    assert not changed
225    assert response['status'] == 'error'
226    assert response['http_status'] == 500
227
228
229def test_firewall_vip46_idempotent(mocker):
230    schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
231
232    set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
233    set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
234
235    input_data = {
236        'username': 'admin',
237        'state': 'present',
238        'firewall_vip46': {
239            'arp_reply': 'disable',
240            'color': '4',
241            'comment': 'Comment.',
242            'extip': 'test_value_6',
243            'extport': 'test_value_7',
244            'id': '8',
245            'ldb_method': 'static',
246            'mappedip': 'test_value_10',
247            'mappedport': 'test_value_11',
248            'name': 'default_name_12',
249            'portforward': 'disable',
250            'protocol': 'tcp',
251            'server_type': 'http',
252            'type': 'static-nat',
253            'uuid': 'test_value_17'
254        },
255        'vdom': 'root'}
256
257    is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
258
259    expected_data = {
260        'arp-reply': 'disable',
261        'color': '4',
262        'comment': 'Comment.',
263        'extip': 'test_value_6',
264        'extport': 'test_value_7',
265        'id': '8',
266        'ldb-method': 'static',
267        'mappedip': 'test_value_10',
268        'mappedport': 'test_value_11',
269        'name': 'default_name_12',
270                'portforward': 'disable',
271                'protocol': 'tcp',
272                'server-type': 'http',
273                'type': 'static-nat',
274                'uuid': 'test_value_17'
275    }
276
277    set_method_mock.assert_called_with('firewall', 'vip46', data=expected_data, vdom='root')
278    schema_method_mock.assert_not_called()
279    assert not is_error
280    assert not changed
281    assert response['status'] == 'error'
282    assert response['http_status'] == 404
283
284
285def test_firewall_vip46_filter_foreign_attributes(mocker):
286    schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
287
288    set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
289    set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
290
291    input_data = {
292        'username': 'admin',
293        'state': 'present',
294        'firewall_vip46': {
295            'random_attribute_not_valid': 'tag',
296            'arp_reply': 'disable',
297            'color': '4',
298            'comment': 'Comment.',
299            'extip': 'test_value_6',
300            'extport': 'test_value_7',
301            'id': '8',
302            'ldb_method': 'static',
303            'mappedip': 'test_value_10',
304            'mappedport': 'test_value_11',
305            'name': 'default_name_12',
306            'portforward': 'disable',
307            'protocol': 'tcp',
308            'server_type': 'http',
309            'type': 'static-nat',
310            'uuid': 'test_value_17'
311        },
312        'vdom': 'root'}
313
314    is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
315
316    expected_data = {
317        'arp-reply': 'disable',
318        'color': '4',
319        'comment': 'Comment.',
320        'extip': 'test_value_6',
321        'extport': 'test_value_7',
322        'id': '8',
323        'ldb-method': 'static',
324        'mappedip': 'test_value_10',
325        'mappedport': 'test_value_11',
326        'name': 'default_name_12',
327                'portforward': 'disable',
328                'protocol': 'tcp',
329                'server-type': 'http',
330                'type': 'static-nat',
331                'uuid': 'test_value_17'
332    }
333
334    set_method_mock.assert_called_with('firewall', 'vip46', data=expected_data, vdom='root')
335    schema_method_mock.assert_not_called()
336    assert not is_error
337    assert changed
338    assert response['status'] == 'success'
339    assert response['http_status'] == 200
340