Skip to content

Commit 3d3e726

Browse files
committed
Update interface so that interface can only be applied to one zone.
1 parent 4236141 commit 3d3e726

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

library/firewall_lib.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,41 @@
179179
HAS_FIREWALLD = False
180180

181181

182+
def handle_interface_permanent(
183+
zone, item, fw_zone, fw_settings, fw, fw_offline, module
184+
):
185+
if fw_offline:
186+
iface_zone_objs = []
187+
for zone in fw.config.get_zones():
188+
old_zone_obj = fw.config.get_zone(zone)
189+
if item in old_zone_obj.interfaces:
190+
iface_zone_objs.append(old_zone_obj)
191+
if len(iface_zone_objs) > 1:
192+
module.fail_json(
193+
msg="ERROR: interface {0} is in {1} zone XML files, can only be in one".format(
194+
item, len(iface_zone_objs)
195+
)
196+
)
197+
old_zone_obj = iface_zone_objs[0]
198+
if old_zone_obj.name != zone:
199+
old_zone_settings = FirewallClientZoneSettings(
200+
fw.config.get_zone_config(old_zone_obj)
201+
)
202+
old_zone_settings.removeInterface(item)
203+
fw.config.set_zone_config(old_zone_obj, old_zone_settings.settings)
204+
fw_settings.addInterface(item)
205+
fw.config.set_zone_config(fw_zone, fw_settings.settings)
206+
else:
207+
old_zone_name = fw.config().getZoneOfInterface(item)
208+
if old_zone_name != zone:
209+
if old_zone_name:
210+
old_zone_obj = fw.config().getZoneByName(old_zone_name)
211+
old_zone_settings = old_zone_obj.getSettings()
212+
old_zone_settings.removeInterface(item)
213+
old_zone_obj.update(old_zone_settings)
214+
fw_settings.addInterface(item)
215+
216+
182217
def parse_port(module, item):
183218
_port, _protocol = item.split("/")
184219
if _protocol is None:
@@ -683,7 +718,9 @@ def exception_handler(exception_message):
683718
changed = True
684719
if permanent and not fw_settings.queryInterface(item):
685720
if not module.check_mode:
686-
fw_settings.addInterface(item)
721+
handle_interface_permanent(
722+
zone, item, fw_zone, fw_settings, fw, fw_offline, module
723+
)
687724
changed = True
688725
elif state == "disabled":
689726
if runtime and fw.queryInterface(zone, item):

tests/unit/test_firewall_lib.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@
179179
"enabled": {
180180
"expected": {
181181
"runtime": [call("default", "eth2")],
182-
"permanent": [call("eth2")],
183182
}
184183
},
185184
"disabled": {
@@ -263,6 +262,64 @@ def __call__(self, **kwargs):
263262
return am
264263

265264

265+
class FirewallInterfaceTests(unittest.TestCase):
266+
"""class to test Firewall interface tests"""
267+
268+
@patch("firewall_lib.FirewallClientZoneSettings", create=True)
269+
@patch("firewall_lib.FirewallClient", create=True)
270+
@patch("firewall_lib.HAS_FIREWALLD", True)
271+
@patch("firewall_lib.FW_VERSION", "0.3.8", create=True)
272+
def test_handle_interface_offline_true(self, zone_settings, firewall_class):
273+
module = Mock()
274+
zone = "dmz"
275+
item = "eth2"
276+
fw = firewall_class.return_value
277+
fw_config = Mock()
278+
fw.config.return_value = fw_config
279+
fw_zone = Mock()
280+
fw.config.getZoneByName.return_value = fw_zone
281+
fw_settings = Mock()
282+
fw.config.getZoneByName.getSettings.return_value = fw_settings
283+
fw_offline = True
284+
fw.config.get_zones.return_value = ["dmz"]
285+
fw_zone_two = Mock()
286+
fw.config.get_zone.return_value = fw_zone_two
287+
fw_zone_two.interfaces = ["eth2"]
288+
289+
firewall_lib.handle_interface_permanent(
290+
zone, item, fw_zone, fw_settings, fw, fw_offline, module
291+
)
292+
called_mock = getattr(fw_settings, "addInterface")
293+
assert [call("eth2")] == called_mock.call_args_list
294+
295+
@patch("firewall_lib.FirewallClientZoneSettings", create=True)
296+
@patch("firewall_lib.FirewallClient", create=True)
297+
@patch("firewall_lib.HAS_FIREWALLD", True)
298+
@patch("firewall_lib.FW_VERSION", "0.3.8", create=True)
299+
def test_handle_interface_offline_false(self, zone_settings, firewall_class):
300+
module = Mock()
301+
zone = "dmz"
302+
item = "eth2"
303+
fw = firewall_class.return_value
304+
fw_config = Mock()
305+
fw.config.return_value = fw_config
306+
fw_zone = Mock()
307+
fw.config.getZoneByName.return_value = fw_zone
308+
fw_settings = Mock()
309+
fw.config.getZoneByName.getSettings.return_value = fw_settings
310+
fw_offline = False
311+
fw.config.get_zones.return_value = ["dmz"]
312+
fw_zone_two = Mock()
313+
fw.config.get_zone.return_value = fw_zone_two
314+
fw_zone_two.interfaces = ["eth2"]
315+
316+
firewall_lib.handle_interface_permanent(
317+
zone, item, fw_zone, fw_settings, fw, fw_offline, module
318+
)
319+
called_mock = getattr(fw_settings, "addInterface")
320+
assert [call("eth2")] == called_mock.call_args_list
321+
322+
266323
class FirewallLibParsers(unittest.TestCase):
267324
"""test param to profile conversion and vice versa"""
268325

0 commit comments

Comments
 (0)