From 8de00e3e1c0a876acf34dfeba1fb06c6a62e7af5 Mon Sep 17 00:00:00 2001 From: dgadmin Date: Wed, 27 Mar 2019 11:20:27 -0400 Subject: [PATCH] To ipv6 network (#48572) * Add to_ipv6_subnet function * Use the correct function for subnet * Corrected code style and tests * Corrected testcase assertion 64 bits make 8 octets, or 4 hextets * Import from correct module directly --- lib/ansible/module_utils/common/network.py | 30 +++++++++++++++++++ lib/ansible/modules/cloud/amazon/ec2_group.py | 4 +-- .../module_utils/network/common/test_utils.py | 11 +++++-- .../modules/cloud/amazon/test_ec2_group.py | 3 +- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/lib/ansible/module_utils/common/network.py b/lib/ansible/module_utils/common/network.py index 45fba7df208..f385c2525bb 100644 --- a/lib/ansible/module_utils/common/network.py +++ b/lib/ansible/module_utils/common/network.py @@ -79,6 +79,36 @@ def to_subnet(addr, mask, dotted_notation=False): return '%s/%s' % ('.'.join(network), cidr) +def to_ipv6_subnet(addr): + """ IPv6 addresses are eight groupings. The first four groupings (64 bits) comprise the subnet address. """ + + # https://tools.ietf.org/rfc/rfc2374.txt + + # Split by :: to identify omitted zeros + ipv6_prefix = addr.split('::')[0] + + # Get the first four groups, or as many as are found + :: + found_groups = [] + for group in ipv6_prefix.split(':'): + found_groups.append(group) + if len(found_groups) == 4: + break + if len(found_groups) < 4: + found_groups.append('::') + + # Concatenate network address parts + network_addr = '' + for group in found_groups: + if group != '::': + network_addr += str(group) + network_addr += str(':') + + # Ensure network address ends with :: + if not network_addr.endswith('::'): + network_addr += str(':') + return network_addr + + def to_ipv6_network(addr): """ IPv6 addresses are eight groupings. The first three groupings (48 bits) comprise the network address. """ diff --git a/lib/ansible/modules/cloud/amazon/ec2_group.py b/lib/ansible/modules/cloud/amazon/ec2_group.py index df103fe6869..b85b320d809 100644 --- a/lib/ansible/modules/cloud/amazon/ec2_group.py +++ b/lib/ansible/modules/cloud/amazon/ec2_group.py @@ -303,7 +303,7 @@ from ansible.module_utils.aws.iam import get_aws_account_id from ansible.module_utils.aws.waiters import get_waiter from ansible.module_utils.ec2 import AWSRetry, camel_dict_to_snake_dict, compare_aws_tags from ansible.module_utils.ec2 import ansible_dict_to_boto3_filter_list, boto3_tag_list_to_ansible_dict, ansible_dict_to_boto3_tag_list -from ansible.module_utils.network.common.utils import to_ipv6_network, to_subnet +from ansible.module_utils.common.network import to_ipv6_subnet, to_subnet from ansible.module_utils._text import to_text from ansible.module_utils.six import string_types @@ -726,7 +726,7 @@ def validate_ip(module, cidr_ip): try: ip = to_subnet(split_addr[0], split_addr[1]) except ValueError: - ip = to_ipv6_network(split_addr[0]) + "/" + split_addr[1] + ip = to_ipv6_subnet(split_addr[0]) + "/" + split_addr[1] if ip != cidr_ip: module.warn("One of your CIDR addresses ({0}) has host bits set. To get rid of this warning, " "check the network mask and make sure that only network bits are set: {1}.".format(cidr_ip, ip)) diff --git a/test/units/module_utils/network/common/test_utils.py b/test/units/module_utils/network/common/test_utils.py index bedc1edd20e..f34834ce5f0 100644 --- a/test/units/module_utils/network/common/test_utils.py +++ b/test/units/module_utils/network/common/test_utils.py @@ -26,8 +26,9 @@ import pytest from ansible.module_utils.network.common.utils import to_list, sort_list from ansible.module_utils.network.common.utils import dict_diff, dict_merge from ansible.module_utils.network.common.utils import conditional, Template -from ansible.module_utils.network.common.utils import to_masklen, to_netmask, to_subnet, to_ipv6_network -from ansible.module_utils.network.common.utils import is_masklen, is_netmask +from ansible.module_utils.common.network import ( + to_masklen, to_netmask, to_subnet, to_ipv6_network, to_ipv6_subnet, is_masklen, is_netmask +) def test_to_list(): @@ -204,3 +205,9 @@ def test_to_ipv6_network(): assert '2001:db8::' == to_ipv6_network('2001:db8::') assert '2001:0db8:85a3::' == to_ipv6_network('2001:0db8:85a3:0000:0000:8a2e:0370:7334') assert '2001:0db8:85a3::' == to_ipv6_network('2001:0db8:85a3:0:0:8a2e:0370:7334') + + +def test_to_ipv6_subnet(): + assert '2001:db8::' == to_ipv6_subnet('2001:db8::') + assert '2001:0db8:85a3:4242::' == to_ipv6_subnet('2001:0db8:85a3:4242:0000:8a2e:0370:7334') + assert '2001:0db8:85a3:4242::' == to_ipv6_subnet('2001:0db8:85a3:4242:0:8a2e:0370:7334') diff --git a/test/units/modules/cloud/amazon/test_ec2_group.py b/test/units/modules/cloud/amazon/test_ec2_group.py index 0b23368f47c..9fee943e9e8 100644 --- a/test/units/modules/cloud/amazon/test_ec2_group.py +++ b/test/units/modules/cloud/amazon/test_ec2_group.py @@ -73,7 +73,8 @@ def test_validate_ip(): ips = [ ('1.1.1.1/24', '1.1.1.0/24'), ('192.168.56.101/16', '192.168.0.0/16'), - ('1203:8fe0:fe80:b897:8990:8a7c:99bf:323d/64', '1203:8fe0:fe80::/64'), + # 64 bits make 8 octets, or 4 hextets + ('1203:8fe0:fe80:b897:8990:8a7c:99bf:323d/64', '1203:8fe0:fe80:b897::/64'), ] for ip, net in ips: