From 8cedec381f438a28ac150cf8c5dae5efdcd709d9 Mon Sep 17 00:00:00 2001 From: Bruno Travouillon Date: Sat, 5 Dec 2020 10:18:29 -0500 Subject: [PATCH] nmcli: add connection.zone parameter (#1426) --- .../1426-nmcli-add-zone-parameter.yml | 2 + plugins/modules/net_tools/nmcli.py | 17 +++ .../plugins/modules/net_tools/test_nmcli.py | 100 ++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 changelogs/fragments/1426-nmcli-add-zone-parameter.yml diff --git a/changelogs/fragments/1426-nmcli-add-zone-parameter.yml b/changelogs/fragments/1426-nmcli-add-zone-parameter.yml new file mode 100644 index 0000000000..1d8a619f14 --- /dev/null +++ b/changelogs/fragments/1426-nmcli-add-zone-parameter.yml @@ -0,0 +1,2 @@ +minor_changes: + - nmcli - add ``zone`` parameter (https://github.com/ansible-collections/community.general/issues/949, https://github.com/ansible-collections/community.general/pull/1426). diff --git a/plugins/modules/net_tools/nmcli.py b/plugins/modules/net_tools/nmcli.py index 47013a2620..6f5b827c85 100644 --- a/plugins/modules/net_tools/nmcli.py +++ b/plugins/modules/net_tools/nmcli.py @@ -257,6 +257,12 @@ options: description: - This is used with IPIP/SIT - IPIP/SIT local IP address. type: str + zone: + description: + - The trust level of the connection. + - When updating this property on a currently activated connection, the change takes effect immediately. + type: str + version_added: 2.0.0 ''' EXAMPLES = r''' @@ -538,6 +544,13 @@ EXAMPLES = r''' ip_tunnel_local: 192.168.1.2 ip_tunnel_remote: 192.168.1.5 + - name: Add zone + community.general.nmcli: + type: ethernet + conn_name: my-eth1 + zone: external + state: present + # nmcli exits with status 0 if it succeeds and exits with a status greater # than zero when there is a failure. The following list of status codes may be # returned: @@ -633,6 +646,7 @@ class Nmcli(object): self.ip_tunnel_remote = module.params['ip_tunnel_remote'] self.nmcli_bin = self.module.get_bin_path('nmcli', True) self.dhcp_client_id = module.params['dhcp_client_id'] + self.zone = module.params['zone'] if self.ip4: self.ipv4_method = 'manual' @@ -659,6 +673,7 @@ class Nmcli(object): # Options common to multiple connection types. options = { 'connection.autoconnect': self.autoconnect, + 'connection.zone': self.zone, } # IP address options. @@ -972,6 +987,7 @@ class Nmcli(object): 'mac': self.mac_setting, 'master': 'connection.master', 'slave-type': 'connection.slave-type', + 'zone': 'connection.zone', } changed = False @@ -1077,6 +1093,7 @@ def main(): # general usage mtu=dict(type='int'), mac=dict(type='str'), + zone=dict(type='str'), # bridge specific vars stp=dict(type='bool', default=True), priority=dict(type='int', default=128), diff --git a/tests/unit/plugins/modules/net_tools/test_nmcli.py b/tests/unit/plugins/modules/net_tools/test_nmcli.py index 9619e5dbbb..8d830bcf19 100644 --- a/tests/unit/plugins/modules/net_tools/test_nmcli.py +++ b/tests/unit/plugins/modules/net_tools/test_nmcli.py @@ -126,6 +126,31 @@ ipv6.dns-search: search6.redhat.com ipv6.method: auto """ +TESTCASE_GENERIC_ZONE = [ + { + 'type': 'generic', + 'conn_name': 'non_existent_nw_device', + 'ifname': 'generic_non_existant', + 'ip4': '10.10.10.10/24', + 'gw4': '10.10.10.1', + 'state': 'present', + 'zone': 'external', + '_ansible_check_mode': False, + } +] + +TESTCASE_GENERIC_ZONE_SHOW_OUTPUT = """\ +connection.id: non_existent_nw_device +connection.interface-name: generic_non_existant +connection.autoconnect: yes +connection.zone: external +ipv4.method: manual +ipv4.addresses: 10.10.10.10/24 +ipv4.gateway: 10.10.10.1 +ipv4.never-default: no +ipv6.method: auto +""" + TESTCASE_BOND = [ { 'type': 'bond', @@ -399,6 +424,13 @@ def mocked_generic_connection_dns_search_unchanged(mocker): execute_return=(0, TESTCASE_GENERIC_DNS4_SEARCH_SHOW_OUTPUT, "")) +@pytest.fixture +def mocked_generic_connection_zone_unchanged(mocker): + mocker_set(mocker, + connection_exists=True, + execute_return=(0, TESTCASE_GENERIC_ZONE_SHOW_OUTPUT, "")) + + @pytest.fixture def mocked_bond_connection_unchanged(mocker): mocker_set(mocker, @@ -664,6 +696,74 @@ def test_dns4_none(mocked_connection_exists, capfd): assert results['changed'] +@pytest.mark.parametrize('patch_ansible_module', TESTCASE_GENERIC_ZONE, indirect=['patch_ansible_module']) +def test_generic_connection_create_zone(mocked_generic_connection_create, capfd): + """ + Test : Generic connection created with zone + """ + with pytest.raises(SystemExit): + nmcli.main() + + assert nmcli.Nmcli.execute_command.call_count == 1 + arg_list = nmcli.Nmcli.execute_command.call_args_list + args, kwargs = arg_list[0] + + assert 'connection.zone' in args[0] + + out, err = capfd.readouterr() + results = json.loads(out) + assert not results.get('failed') + assert results['changed'] + + +@pytest.mark.parametrize('patch_ansible_module', TESTCASE_GENERIC_ZONE, indirect=['patch_ansible_module']) +def test_generic_connection_modify_zone(mocked_generic_connection_create, capfd): + """ + Test : Generic connection modified with zone + """ + with pytest.raises(SystemExit): + nmcli.main() + + assert nmcli.Nmcli.execute_command.call_count == 1 + arg_list = nmcli.Nmcli.execute_command.call_args_list + args, kwargs = arg_list[0] + + assert 'connection.zone' in args[0] + + out, err = capfd.readouterr() + results = json.loads(out) + assert not results.get('failed') + assert results['changed'] + + +@pytest.mark.parametrize('patch_ansible_module', TESTCASE_GENERIC_ZONE, indirect=['patch_ansible_module']) +def test_generic_connection_zone_unchanged(mocked_generic_connection_zone_unchanged, capfd): + """ + Test : Generic connection with zone unchanged + """ + with pytest.raises(SystemExit): + nmcli.main() + + out, err = capfd.readouterr() + results = json.loads(out) + assert not results.get('failed') + assert not results['changed'] + + +@pytest.mark.parametrize('patch_ansible_module', TESTCASE_CONNECTION, indirect=['patch_ansible_module']) +def test_zone_none(mocked_connection_exists, capfd): + """ + Test if zone param is None + """ + with pytest.raises(SystemExit): + nmcli.main() + + out, err = capfd.readouterr() + results = json.loads(out) + assert not results.get('failed') + assert results['changed'] + + @pytest.mark.parametrize('patch_ansible_module', TESTCASE_BRIDGE, indirect=['patch_ansible_module']) def test_create_bridge(mocked_generic_connection_create, capfd): """