From ee0c19e5190ecdf8743b342566bfd36e5088950a Mon Sep 17 00:00:00 2001 From: Wojciech Wypior Date: Fri, 2 Aug 2019 22:11:03 -0700 Subject: [PATCH] corrected lib imports to work with python 2.x (#60017) --- .../modules/network/f5/bigip_data_group.py | 92 +++++++++++++++---- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/lib/ansible/modules/network/f5/bigip_data_group.py b/lib/ansible/modules/network/f5/bigip_data_group.py index e16301c2307..ee6e1c840a6 100644 --- a/lib/ansible/modules/network/f5/bigip_data_group.py +++ b/lib/ansible/modules/network/f5/bigip_data_group.py @@ -85,6 +85,9 @@ options: RAM. - When C(internal) is C(no), at least one record must be specified in either C(records) or C(records_content). + - "When C(type) is: C(ip), C(address), C(addr) if the addresses use non default route domain, + they must be explicit about it that is they must contain a route domain notation C(%) eg. 10.10.1.1%11. + This is true regardless if the data group resides in a partition or not." type: list suboptions: key: @@ -153,6 +156,7 @@ extends_documentation_fragment: f5 author: - Tim Rupp (@caphrim007) - Wojciech Wypior (@wojtek0806) + - Greg Crosby (@crosbygw) ''' EXAMPLES = r''' @@ -278,7 +282,10 @@ import re from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import env_fallback -from io import StringIO +try: + from StringIO import StringIO +except ImportError: + from io import StringIO try: from library.module_utils.network.f5.bigip import F5RestClient @@ -344,6 +351,8 @@ class RecordsEncoder(object): self._separator = separator self._network_pattern = re.compile(r'^network\s+(?P[^ ]+)\s+prefixlen\s+(?P\d+)\s+.*') self._host_pattern = re.compile(r'^host\s+(?P[^ ]+)\s+.*') + self._rd_net_pattern = re.compile(r'(?P[^%]+)%(?P[0-9]+)/(?P[0-9]+)') + self._rd_host_pattern = re.compile(r'(?P[^%]+)%(?P[0-9]+)') def encode(self, record): if isinstance(record, dict): @@ -359,7 +368,42 @@ class RecordsEncoder(object): else: return self.encode_string_from_dict(record) + def encode_rd_address(self, record, match, host=False): + if host: + if is_valid_ip_interface(match.group('addr')): + key = ip_interface(u"{0}".format(match.group('addr'))) + else: + raise F5ModuleError( + "When specifying an 'address' type, the value to the left of the separator must be an IP." + ) + else: + if is_valid_ip_interface(match.group('addr')): + key = ip_interface(u"{0}/{1}".format(match.group('addr'), match.group('prefix'))) + else: + raise F5ModuleError( + "When specifying an 'address' type, the value to the left of the separator must be an IP." + ) + if key and 'value' in record: + if key.network.prefixlen in [32, 128]: + return self.encode_host(str(key.ip) + '%' + match.group('rd'), record['value']) + return self.encode_network( + str(key.network.network_address) + '%' + match.group('rd'), key.network.prefixlen, record['value'] + ) + elif key: + if key.network.prefixlen in [32, 128]: + return self.encode_host(str(key.ip) + '%' + match.group('rd'), str(key.ip) + '%' + match.group('rd')) + return self.encode_network( + str(key.network.network_address) + '%' + match.group('rd'), key.network.prefixlen, + str(key.network.network_address) + '%' + match.group('rd') + ) + def encode_address_from_dict(self, record): + rd_match = re.match(self._rd_net_pattern, record['key']) + if rd_match: + return self.encode_rd_address(record, rd_match) + rd_match = re.match(self._rd_host_pattern, record['key']) + if rd_match: + return self.encode_rd_address(record, rd_match, host=True) if is_valid_ip_interface(record['key']): key = ip_interface(u"{0}".format(str(record['key']))) else: @@ -415,6 +459,12 @@ class RecordsEncoder(object): # host 172.16.1.1/32 := "Host3" # host 2001:0db8:85a3:0000:0000:8a2e:0370:7334 := "Host4" return record + elif self._rd_net_pattern.match(record) or self._rd_host_pattern.match(record): + # 192.168.0.0%11/16 := "Network3", + # 2402:9400:1000:0::%11/64 := "Network4", + # 192.168.1.1%11/32 := "Host3", + # 2001:0db8:85a3:0000:0000:8a2e:0370:7334%11 := "Host4" + return record else: # 192.168.0.0/16 := "Network3", # 2402:9400:1000:0::/64 := "Network4", @@ -477,6 +527,8 @@ class RecordsDecoder(object): self._separator = separator self._network_pattern = re.compile(r'^network\s+(?P[^ ]+)\s+prefixlen\s+(?P\d+)\s+.*') self._host_pattern = re.compile(r'^host\s+(?P[^ ]+)\s+.*') + self._rd_net_ptrn = re.compile(r'^network\s+(?P[^%]+)%(?P[0-9]+)\s+prefixlen\s+(?P\d+)\s+.*') + self._rd_host_ptrn = re.compile(r'^host\s+(?P[^%]+)%(?P[0-9]+)\s+.*') def decode(self, record): record = record.strip().strip(',') @@ -486,6 +538,14 @@ class RecordsDecoder(object): return self.decode_from_string(record) def decode_address_from_string(self, record): + matches = self._rd_net_ptrn.match(record) + if matches: + # network 192.168.0.0%11 prefixlen 16 := "Network3", + # network 2402:9400:1000:0::%11 prefixlen 64 := "Network4", + value = record.split(self._separator)[1].strip().strip('"') + addr = "{0}%{1}/{2}".format(matches.group('addr'), matches.group('rd'), matches.group('prefix')) + result = dict(name=addr, data=value) + return result matches = self._network_pattern.match(record) if matches: # network 192.168.0.0 prefixlen 16 := "Network3", @@ -495,6 +555,15 @@ class RecordsDecoder(object): value = record.split(self._separator)[1].strip().strip('"') result = dict(name=str(addr), data=value) return result + matches = self._rd_host_ptrn.match(record) + if matches: + # host 172.16.1.1%11/32 := "Host3" + # host 2001:0db8:85a3:0000:0000:8a2e:0370:7334%11 := "Host4" + host = ip_interface(u"{0}".format(matches.group('addr'))) + addr = "{0}%{1}/{2}".format(matches.group('addr'), matches.group('rd'), str(host.network.prefixlen)) + value = record.split(self._separator)[1].strip().strip('"') + result = dict(name=addr, data=value) + return result matches = self._host_pattern.match(record) if matches: # host 172.16.1.1/32 := "Host3" @@ -504,6 +573,7 @@ class RecordsDecoder(object): value = record.split(self._separator)[1].strip().strip('"') result = dict(name=str(addr), data=value) return result + raise F5ModuleError( 'The value "{0}" is not an address'.format(record) ) @@ -590,17 +660,6 @@ class Parameters(AnsibleF5Parameters): class ApiParameters(Parameters): - - def _strip_route_domain(self, item): - result = dict() - pattern = r'(?P[^%]+)%(?P[0-9]+)/(?P[0-9]+)' - matches = re.search(pattern, item['name']) - if matches: - result['data'] = item['data'] - result['name'] = '{0}/{1}'.format(matches.group('ip'), matches.group('mask')) - return result - return item - @property def checksum(self): if self._values['checksum'] is None: @@ -608,16 +667,9 @@ class ApiParameters(Parameters): result = self._values['checksum'].split(':')[2] return result - @property - def records(self): - if self._values['records'] is None: - return None - result = [self._strip_route_domain(item) for item in self._values['records']] - return result - @property def records_list(self): - return self.records + return self._values['records'] @property def description(self):