1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

nmcli: manage dummy connections (#3132)

* manage dummy connections

* add issue reference in changelog fragment

* Update changelogs/fragments/3132-nmcli-dummy.yaml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* resolve test conflicts

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
This commit is contained in:
Reto Kupferschmid 2021-08-05 14:25:42 +02:00 committed by GitHub
parent 75688cb632
commit 3dba697e33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 2 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- nmcli - add ``dummy`` interface support (https://github.com/ansible-collections/community.general/issues/724).

View file

@ -51,10 +51,11 @@ options:
type: type:
description: description:
- This is the type of device or network connection that you wish to create or modify. - This is the type of device or network connection that you wish to create or modify.
- Type C(dummy) is added in community.general 3.5.0.
- Type C(generic) is added in Ansible 2.5. - Type C(generic) is added in Ansible 2.5.
- Type C(infiniband) is added in community.general 2.0.0. - Type C(infiniband) is added in community.general 2.0.0.
type: str type: str
choices: [ bond, bond-slave, bridge, bridge-slave, ethernet, generic, infiniband, ipip, sit, team, team-slave, vlan, vxlan, wifi ] choices: [ bond, bond-slave, bridge, bridge-slave, dummy, ethernet, generic, infiniband, ipip, sit, team, team-slave, vlan, vxlan, wifi ]
mode: mode:
description: description:
- This is the type of device or network connection that you wish to create for a bond or bridge. - This is the type of device or network connection that you wish to create for a bond or bridge.
@ -775,6 +776,8 @@ class Nmcli(object):
if self.method4: if self.method4:
self.ipv4_method = self.method4 self.ipv4_method = self.method4
elif self.type == 'dummy' and not self.ip4:
self.ipv4_method = 'disabled'
elif self.ip4: elif self.ip4:
self.ipv4_method = 'manual' self.ipv4_method = 'manual'
else: else:
@ -782,6 +785,8 @@ class Nmcli(object):
if self.method6: if self.method6:
self.ipv6_method = self.method6 self.ipv6_method = self.method6
elif self.type == 'dummy' and not self.ip6:
self.ipv6_method = 'disabled'
elif self.ip6: elif self.ip6:
self.ipv6_method = 'manual' self.ipv6_method = 'manual'
else: else:
@ -938,6 +943,7 @@ class Nmcli(object):
return self.type in ( return self.type in (
'bond', 'bond',
'bridge', 'bridge',
'dummy',
'ethernet', 'ethernet',
'generic', 'generic',
'infiniband', 'infiniband',
@ -956,6 +962,7 @@ class Nmcli(object):
@property @property
def mtu_conn_type(self): def mtu_conn_type(self):
return self.type in ( return self.type in (
'dummy',
'ethernet', 'ethernet',
'team-slave', 'team-slave',
) )
@ -1092,7 +1099,7 @@ class Nmcli(object):
@property @property
def create_connection_up(self): def create_connection_up(self):
if self.type in ('bond', 'ethernet', 'infiniband', 'wifi'): if self.type in ('bond', 'dummy', 'ethernet', 'infiniband', 'wifi'):
if (self.mtu is not None) or (self.dns4 is not None) or (self.dns6 is not None): if (self.mtu is not None) or (self.dns4 is not None) or (self.dns6 is not None):
return True return True
elif self.type == 'team': elif self.type == 'team':
@ -1218,6 +1225,7 @@ def main():
'bond-slave', 'bond-slave',
'bridge', 'bridge',
'bridge-slave', 'bridge-slave',
'dummy',
'ethernet', 'ethernet',
'generic', 'generic',
'infiniband', 'infiniband',

View file

@ -74,6 +74,12 @@ TESTCASE_CONNECTION = [
'state': 'absent', 'state': 'absent',
'_ansible_check_mode': True, '_ansible_check_mode': True,
}, },
{
'type': 'dummy',
'conn_name': 'non_existent_nw_device',
'state': 'absent',
'_ansible_check_mode': True,
},
] ]
TESTCASE_GENERIC = [ TESTCASE_GENERIC = [
@ -485,6 +491,40 @@ TESTCASE_WIRELESS = [
} }
] ]
TESTCASE_DUMMY_STATIC = [
{
'type': 'dummy',
'conn_name': 'non_existent_nw_device',
'ifname': 'dummy_non_existant',
'ip4': '10.10.10.10/24',
'gw4': '10.10.10.1',
'dns4': ['1.1.1.1', '8.8.8.8'],
'ip6': '2001:db8::1/128',
'state': 'present',
'_ansible_check_mode': False,
}
]
TESTCASE_DUMMY_STATIC_SHOW_OUTPUT = """\
connection.id: non_existent_nw_device
connection.interface-name: dummy_non_existant
connection.autoconnect: yes
802-3-ethernet.mtu: auto
ipv4.method: manual
ipv4.addresses: 10.10.10.10/24
ipv4.gateway: 10.10.10.1
ipv4.ignore-auto-dns: no
ipv4.ignore-auto-routes: no
ipv4.never-default: no
ipv4.may-fail: yes
ipv4.dns: 1.1.1.1,8.8.8.8
ipv6.method: auto
ipv6.ignore-auto-dns: no
ipv6.ignore-auto-routes: no
ipv6.method: manual
ipv6.addresses: 2001:db8::1/128
"""
def mocker_set(mocker, def mocker_set(mocker,
connection_exists=False, connection_exists=False,
@ -641,6 +681,13 @@ def mocked_ethernet_connection_dhcp_to_static(mocker):
)) ))
@pytest.fixture
def mocked_dummy_connection_static_unchanged(mocker):
mocker_set(mocker,
connection_exists=True,
execute_return=(0, TESTCASE_DUMMY_STATIC_SHOW_OUTPUT, ""))
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_BOND, indirect=['patch_ansible_module']) @pytest.mark.parametrize('patch_ansible_module', TESTCASE_BOND, indirect=['patch_ansible_module'])
def test_bond_connection_create(mocked_generic_connection_create, capfd): def test_bond_connection_create(mocked_generic_connection_create, capfd):
""" """
@ -1581,3 +1628,58 @@ def test_create_wireless(mocked_generic_connection_create, capfd):
results = json.loads(out) results = json.loads(out)
assert not results.get('failed') assert not results.get('failed')
assert results['changed'] assert results['changed']
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_DUMMY_STATIC, indirect=['patch_ansible_module'])
def test_create_dummy_static(mocked_generic_connection_create, capfd):
"""
Test : Create dummy connection with static IP configuration
"""
with pytest.raises(SystemExit):
nmcli.main()
assert nmcli.Nmcli.execute_command.call_count == 2
arg_list = nmcli.Nmcli.execute_command.call_args_list
add_args, add_kw = arg_list[0]
assert add_args[0][0] == '/usr/bin/nmcli'
assert add_args[0][1] == 'con'
assert add_args[0][2] == 'add'
assert add_args[0][3] == 'type'
assert add_args[0][4] == 'dummy'
assert add_args[0][5] == 'con-name'
assert add_args[0][6] == 'non_existent_nw_device'
add_args_text = list(map(to_text, add_args[0]))
for param in ['connection.interface-name', 'dummy_non_existant',
'ipv4.addresses', '10.10.10.10/24',
'ipv4.gateway', '10.10.10.1',
'ipv4.dns', '1.1.1.1,8.8.8.8',
'ipv6.addresses', '2001:db8::1/128']:
assert param in add_args_text
up_args, up_kw = arg_list[1]
assert up_args[0][0] == '/usr/bin/nmcli'
assert up_args[0][1] == 'con'
assert up_args[0][2] == 'up'
assert up_args[0][3] == 'non_existent_nw_device'
out, err = capfd.readouterr()
results = json.loads(out)
assert not results.get('failed')
assert results['changed']
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_DUMMY_STATIC, indirect=['patch_ansible_module'])
def test_dummy_connection_static_unchanged(mocked_dummy_connection_static_unchanged, capfd):
"""
Test : Dummy connection with static IP configuration unchanged
"""
with pytest.raises(SystemExit):
nmcli.main()
out, err = capfd.readouterr()
results = json.loads(out)
assert not results.get('failed')
assert not results['changed']