From 4f7f57e655cb931938ebe95fa0ed05e95ffa1179 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Fri, 8 Nov 2019 19:30:38 +0530 Subject: [PATCH] PR raised to add the feature of adding/removing IP from a Host record (#50975) * 50238 fix --- .../module_utils/net_tools/nios/api.py | 80 +++++++++++++++++-- .../net_tools/nios/nios_host_record.py | 52 +++++++++++- 2 files changed, 125 insertions(+), 7 deletions(-) diff --git a/lib/ansible/module_utils/net_tools/nios/api.py b/lib/ansible/module_utils/net_tools/nios/api.py index 2588cbc5ba4..ccc8c565a80 100644 --- a/lib/ansible/module_utils/net_tools/nios/api.py +++ b/lib/ansible/module_utils/net_tools/nios/api.py @@ -304,6 +304,21 @@ class WapiModule(WapiBase): if update and new_name: proposed_object['name'] = new_name + check_remove = [] + if (ib_obj_type == NIOS_HOST_RECORD): + # this check is for idempotency, as if the same ip address shall be passed + # add param will be removed, and same exists true for remove case as well. + if 'ipv4addrs' in [current_object and proposed_object]: + for each in current_object['ipv4addrs']: + if each['ipv4addr'] == proposed_object['ipv4addrs'][0]['ipv4addr']: + if 'add' in proposed_object['ipv4addrs'][0]: + del proposed_object['ipv4addrs'][0]['add'] + break + check_remove += each.values() + if proposed_object['ipv4addrs'][0]['ipv4addr'] not in check_remove: + if 'remove' in proposed_object['ipv4addrs'][0]: + del proposed_object['ipv4addrs'][0]['remove'] + res = None modified = not self.compare_objects(current_object, proposed_object) if 'extattrs' in proposed_object: @@ -324,28 +339,55 @@ class WapiModule(WapiBase): result['api_results'] = self.call_func('create_token', ref, proposed_object) result['changed'] = True elif modified: - self.check_if_recordname_exists(obj_filter, ib_obj_ref, ib_obj_type, current_object, proposed_object) + if 'ipv4addrs' in proposed_object: + if ('add' not in proposed_object['ipv4addrs'][0]) and ('remove' not in proposed_object['ipv4addrs'][0]): + self.check_if_recordname_exists(obj_filter, ib_obj_ref, ib_obj_type, current_object, proposed_object) if (ib_obj_type in (NIOS_HOST_RECORD, NIOS_NETWORK_VIEW, NIOS_DNS_VIEW)): + run_update = True proposed_object = self.on_update(proposed_object, ib_spec) - res = self.update_object(ref, proposed_object) + if 'ipv4addrs' in proposed_object: + if ('add' or 'remove') in proposed_object['ipv4addrs'][0]: + run_update, proposed_object = self.check_if_add_remove_ip_arg_exists(proposed_object) + if run_update: + res = self.update_object(ref, proposed_object) + result['changed'] = True + else: + res = ref if (ib_obj_type in (NIOS_A_RECORD, NIOS_AAAA_RECORD, NIOS_PTR_RECORD, NIOS_SRV_RECORD)): # popping 'view' key as update of 'view' is not supported with respect to a:record/aaaa:record/srv:record/ptr:record + if 'ipv4addrs' in proposed_object: + if 'add' in proposed_object['ipv4addrs'][0]: + run_update, proposed_object = self.check_if_add_remove_ip_arg_exists(proposed_object) + if run_update: + res = self.update_object(ref, proposed_object) + result['changed'] = True + else: + res = ref + if (ib_obj_type in (NIOS_A_RECORD, NIOS_AAAA_RECORD)): + # popping 'view' key as update of 'view' is not supported with respect to a:record/aaaa:record proposed_object = self.on_update(proposed_object, ib_spec) del proposed_object['view'] res = self.update_object(ref, proposed_object) + result['changed'] = True elif 'network_view' in proposed_object: proposed_object.pop('network_view') + result['changed'] = True if not self.module.check_mode and res is None: proposed_object = self.on_update(proposed_object, ib_spec) self.update_object(ref, proposed_object) - result['changed'] = True + result['changed'] = True elif state == 'absent': if ref is not None: - if not self.module.check_mode: + if 'ipv4addrs' in proposed_object: + if 'remove' in proposed_object['ipv4addrs'][0]: + self.check_if_add_remove_ip_arg_exists(proposed_object) + self.update_object(ref, proposed_object) + result['changed'] = True + elif not self.module.check_mode: self.delete_object(ref) - result['changed'] = True + result['changed'] = True return result @@ -383,6 +425,34 @@ class WapiModule(WapiBase): return proposed_object + def check_if_add_remove_ip_arg_exists(self, proposed_object): + ''' + This function shall check if add/remove param is set to true and + is passed in the args, then we will update the proposed dictionary + to add/remove IP to existing host_record, if the user passes false + param with the argument nothing shall be done. + :returns: True if param is changed based on add/remove, and also the + changed proposed_object. + ''' + update = False + if 'add' in proposed_object['ipv4addrs'][0]: + if proposed_object['ipv4addrs'][0]['add']: + proposed_object['ipv4addrs+'] = proposed_object['ipv4addrs'] + del proposed_object['ipv4addrs'] + del proposed_object['ipv4addrs+'][0]['add'] + update = True + else: + del proposed_object['ipv4addrs'][0]['add'] + elif 'remove' in proposed_object['ipv4addrs'][0]: + if proposed_object['ipv4addrs'][0]['remove']: + proposed_object['ipv4addrs-'] = proposed_object['ipv4addrs'] + del proposed_object['ipv4addrs'] + del proposed_object['ipv4addrs-'][0]['remove'] + update = True + else: + del proposed_object['ipv4addrs'][0]['remove'] + return update, proposed_object + def issubset(self, item, objects): ''' Checks if item is a subset of objects :args item: the subset item to validate diff --git a/lib/ansible/modules/net_tools/nios/nios_host_record.py b/lib/ansible/modules/net_tools/nios/nios_host_record.py index 41b2fb32153..88e91866899 100644 --- a/lib/ansible/modules/net_tools/nios/nios_host_record.py +++ b/lib/ansible/modules/net_tools/nios/nios_host_record.py @@ -60,7 +60,9 @@ options: description: - Configures the IPv4 address for the host record. Users can dynamically allocate ipv4 address to host record by passing dictionary containing, - I(nios_next_ip) and I(CIDR network range). See example + I(nios_next_ip) and I(CIDR network range). If user wants to add or + remove the ipv4 address from existing record, I(add/remove) + params need to be used. See examples required: true aliases: - address @@ -78,6 +80,26 @@ options: required: false aliases: - mac + add: + version_added: "2.10" + description: + - If user wants to add the ipv4 address to an existing host record. + Note that with I(add) user will have to keep the I(state) as I(present), + as new IP address is allocated to existing host record. See examples. + type: bool + required: false + aliases: + - add + remove: + version_added: "2.10" + description: + - If user wants to remove the ipv4 address from an existing host record. + Note that with I(remove) user will have to change the I(state) to I(absent), + as IP address is de-allocated from an existing host record. See examples. + type: bool + required: false + aliases: + - remove ipv6addrs: description: - Configures the IPv6 addresses for the host record. This argument @@ -212,6 +234,30 @@ EXAMPLES = ''' username: admin password: admin connection: local +- name: add ip to host record + nios_host_record: + name: host.ansible.com + ipv4: + - address: 192.168.10.2 + add: true + state: present + provider: + host: "{{ inventory_hostname_short }}" + username: admin + password: admin + connection: local +- name: remove ip to host record + nios_host_record: + name: host.ansible.com + ipv4: + - address: 192.168.10.1 + remove: true + state: absent + provider: + host: "{{ inventory_hostname_short }}" + username: admin + password: admin + connection: local ''' RETURN = ''' # ''' @@ -254,7 +300,9 @@ def main(): ipv4addr_spec = dict( ipv4addr=dict(required=True, aliases=['address'], ib_req=True), configure_for_dhcp=dict(type='bool', required=False, aliases=['dhcp'], ib_req=True), - mac=dict(required=False, aliases=['mac'], ib_req=True) + mac=dict(required=False, aliases=['mac'], ib_req=True), + add=dict(type='bool', aliases=['add'], required=False), + remove=dict(type='bool', aliases=['remove'], required=False) ) ipv6addr_spec = dict(