Repository: ansible/ansible

Issue:
nxos_pim_rp_address errors out for both transports (cli and nxapi)
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
 - nxos_pim_rp_address

##### NXOS VERSION
7.0(3)I3(1)

##### ANSIBLE VERSION
```
ansible-playbook 2.4.0 (devel 781bb44b02) last updated 2017/06/08 15:20:16 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/usr/share/ansible']
  ansible python module location = /root/agents-ci/ansible/lib/ansible
  executable location = /root/agents-ci/ansible/bin/ansible-playbook
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```

##### OS / ENVIRONMENT
running on Ubuntu 14.04

##### SUMMARY
The module errors out in latest `devel` when using transport `nxapi` or `cli` but it errors out differently for each.

##### STEPS TO REPRODUCE
* CLI yaml file
```yaml
---
- debug: msg="START TRANSPORT:CLI nxos_pim_rp_address sanity test"

- name: configure
  nxos_pim_rp_address:
    rp_address: "10.1.1.20"
    state: present
    provider: "{{ cli }}"

- debug: msg="END TRANSPORT:CLI nxos_pim_rp_address sanity test"
```
* NXAPI yaml file
```yaml
---
- debug: msg="START TRANSPORT:NXAPI nxos_pim_rp_address sanity test"

- name: configure
  nxos_pim_rp_address:
    rp_address: "10.1.1.20"
    state: present
    provider: "{{ nxapi }}"

- debug: msg="END TRANSPORT:NXAPI nxos_pim_rp_address sanity test"
```

##### EXPECTED RESULTS
Expect nxapi_pim_rp_address module to run properly.

##### ACTUAL RESULTS FOR TRANSPORT CLI

```shell
TASK [nxos_pim_rp_address : debug] ************************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_pim_rp_address/tests/cli/sanity.yaml:2
ok: [n9k] => {
    "failed": false, 
    "msg": "START TRANSPORT:CLI nxos_pim_rp_address sanity test"
}

TASK [nxos_pim_rp_address : configure] ********************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_pim_rp_address/tests/cli/sanity.yaml:4
<n9k> connection transport is cli
<n9k> using connection plugin network_cli
<n9k> socket_path: /root/.ansible/pc/4cc10f215f
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/basic.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/netcfg.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/nxos.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/_text.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/pycompat24.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/__init__.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/_six.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/network_common.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/connection.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/urls.py
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
<n9k> ESTABLISH LOCAL CONNECTION FOR USER: root
<n9k> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414 `" && echo ansible-tmp-1496953067.88-50493394281414="` echo $HOME/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414 `" ) && sleep 0'
<n9k> PUT /tmp/tmp9tzsJY TO /root/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414/nxos_pim_rp_address.py
<n9k> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414/ /root/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414/nxos_pim_rp_address.py && sleep 0'
<n9k> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414/nxos_pim_rp_address.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1496953067.88-50493394281414/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_gxxCZK/ansible_module_nxos_pim_rp_address.py", line 272, in <module>
    main()
  File "/tmp/ansible_gxxCZK/ansible_module_nxos_pim_rp_address.py", line 257, in main
    result.update(response)
TypeError: 'NoneType' object is not iterable

fatal: [n9k]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_gxxCZK/ansible_module_nxos_pim_rp_address.py\", line 272, in <module>\n    main()\n  File \"/tmp/ansible_gxxCZK/ansible_module_nxos_pim_rp_address.py\", line 257, in main\n    result.update(response)\nTypeError: 'NoneType' object is not iterable\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}
	to retry, use: --limit @/root/agents-ci/ansible/test/integration/nxos.retry

PLAY RECAP ************************************************************************************************************************************************************************************************************************************
n9k          : ok=5    changed=0    unreachable=0    failed=1   
```

##### ACTUAL RESULTS FOR TRANSPORT NXAPI

```shell
TASK [nxos_pim_rp_address : debug] ************************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_pim_rp_address/tests/nxapi/sanity.yaml:2
ok: [n9k] => {
    "failed": false, 
    "msg": "START TRANSPORT:NXAPI nxos_pim_rp_address sanity test"
}

TASK [nxos_pim_rp_address : configure] ********************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_pim_rp_address/tests/nxapi/sanity.yaml:4
<n9k> connection transport is nxapi
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/basic.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/netcfg.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/nxos.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/_text.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/pycompat24.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/__init__.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/_six.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/network_common.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/connection.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/urls.py
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
<n9k> ESTABLISH LOCAL CONNECTION FOR USER: root
<n9k> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711 `" && echo ansible-tmp-1496953310.42-129920168794711="` echo $HOME/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711 `" ) && sleep 0'
<n9k> PUT /tmp/tmpiXx5GG TO /root/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711/nxos_pim_rp_address.py
<n9k> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711/ /root/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711/nxos_pim_rp_address.py && sleep 0'
<n9k> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711/nxos_pim_rp_address.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1496953310.42-129920168794711/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_15l9j2/ansible_module_nxos_pim_rp_address.py", line 272, in <module>
    main()
  File "/tmp/ansible_15l9j2/ansible_module_nxos_pim_rp_address.py", line 256, in main
    response = load_config(module, candidate)
  File "/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py", line 399, in load_config
  File "/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py", line 346, in load_config
  File "/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py", line 262, in send_request
  File "/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py", line 227, in _request_builder
TypeError: sequence item 0: expected string, CustomNetworkConfig found

fatal: [n9k]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_15l9j2/ansible_module_nxos_pim_rp_address.py\", line 272, in <module>\n    main()\n  File \"/tmp/ansible_15l9j2/ansible_module_nxos_pim_rp_address.py\", line 256, in main\n    response = load_config(module, candidate)\n  File \"/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 399, in load_config\n  File \"/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 346, in load_config\n  File \"/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 262, in send_request\n  File \"/tmp/ansible_15l9j2/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 227, in _request_builder\nTypeError: sequence item 0: expected string, CustomNetworkConfig found\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}
	to retry, use: --limit @/root/agents-ci/ansible/test/integration/nxos.retry

PLAY RECAP ************************************************************************************************************************************************************************************************************************************
n9k          : ok=6    changed=0    unreachable=0    failed=1   

```


Discussion:
cc @jedelman8 @GGabriele @rahushen @privateip @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/network/nxos/nxos_pim_rp_address.py b/lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
--- a/lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
+++ b/lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
@@ -16,9 +16,11 @@
 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-ANSIBLE_METADATA = {'metadata_version': '1.0',
-                    'status': ['preview'],
-                    'supported_by': 'community'}
+ANSIBLE_METADATA = {
+    'metadata_version': '1.0',
+    'status': ['preview'],
+    'supported_by': 'community',
+}
 
 
 DOCUMENTATION = '''
@@ -28,149 +30,93 @@
 version_added: "2.2"
 short_description: Manages configuration of an PIM static RP address instance.
 description:
-    - Manages configuration of an Protocol Independent Multicast (PIM) static
-      rendezvous point (RP) address instance.
+  - Manages configuration of an Protocol Independent Multicast (PIM) static
+    rendezvous point (RP) address instance.
 author: Gabriele Gerbino (@GGabriele)
 notes:
-    - C(state=absent) remove the whole rp-address configuration, if existing.
+  - C(state=absent) remove the whole rp-address configuration, if existing.
 options:
-    rp_address:
-        description:
-            - Configures a Protocol Independent Multicast (PIM) static
-              rendezvous point (RP) address. Valid values are
-              unicast addresses.
-        required: true
-    group_list:
-        description:
-            - Group range for static RP. Valid values are multicast addresses.
-        required: false
-        default: null
-    prefix_list:
-        description:
-            - Prefix list policy for static RP. Valid values are prefix-list
-              policy names.
-        required: false
-        default: null
-    route_map:
-        description:
-            - Route map policy for static RP. Valid values are route-map
-              policy names.
-        required: false
-        default: null
-    bidir:
-        description:
-            - Group range is treated in PIM bidirectional mode.
-        required: false
-        choices: ['true','false']
-        default: null
+  rp_address:
+    description:
+      - Configures a Protocol Independent Multicast (PIM) static
+        rendezvous point (RP) address. Valid values are
+        unicast addresses.
+    required: true
+  group_list:
+    description:
+      - Group range for static RP. Valid values are multicast addresses.
+    required: false
+    default: null
+  prefix_list:
+    description:
+      - Prefix list policy for static RP. Valid values are prefix-list
+        policy names.
+    required: false
+    default: null
+  route_map:
+    description:
+      - Route map policy for static RP. Valid values are route-map
+        policy names.
+    required: false
+    default: null
+  bidir:
+    description:
+      - Group range is treated in PIM bidirectional mode.
+    required: false
+    choices: ['true','false']
+    default: null
 '''
 EXAMPLES = '''
 - nxos_pim_rp_address:
     rp_address: "10.1.1.20"
     state: present
-    username: "{{ un }}"
-    password: "{{ pwd }}"
-    host: "{{ inventory_hostname }}"
 '''
 
 RETURN = '''
-proposed:
-    description: k/v pairs of parameters passed into module
-    returned: verbose mode
-    type: dict
-    sample: {"rp_address": "10.1.1.21"}
-existing:
-    description: list of existing pim rp-address configuration entries
-    returned: verbose mode
-    type: list
-    sample: []
-end_state:
-    description: pim rp-address configuration entries after module execution
-    returned: verbose mode
-    type: list
-    sample: [{"bidir": false, "group_list": "224.0.0.0/4",
-            "rp_address": "10.1.1.21"}]
-updates:
+commands:
     description: commands sent to the device
     returned: always
     type: list
     sample: ["router bgp 65535", "vrf test", "router-id 1.1.1.1"]
-changed:
-    description: check to see if a change was made on the device
-    returned: always
-    type: boolean
-    sample: true
 '''
 
 
-
 import re
-from ansible.module_utils.nxos import get_config, load_config, run_commands
+
+from ansible.module_utils.nxos import get_config, load_config
 from ansible.module_utils.nxos import nxos_argument_spec, check_args
 from ansible.module_utils.basic import AnsibleModule
 from ansible.module_utils.netcfg import CustomNetworkConfig
 
-import re
-
-BOOL_PARAMS = ['bidir']
-PARAM_TO_COMMAND_KEYMAP = {
-    'rp_address': 'ip pim rp-address'
-}
-PARAM_TO_DEFAULT_KEYMAP = {}
-WARNINGS = []
-
-def invoke(name, *args, **kwargs):
-    func = globals().get(name)
-    if func:
-        return func(*args, **kwargs)
-
-
-def get_value(config, module):
-    value_list = []
-    splitted_config = config.splitlines()
-    for line in splitted_config:
-        tmp = {}
-        if 'ip pim rp-address' in line:
-            splitted_line = line.split()
-            tmp['rp_address'] = splitted_line[3]
-            if len(splitted_line) > 5:
-                value = splitted_line[5]
-                if splitted_line[4] == 'route-map':
-                    tmp['route_map'] = value
-                elif splitted_line[4] == 'prefix-list':
-                    tmp['prefix_list'] = value
-                elif splitted_line[4] == 'group-list':
-                    tmp['group_list'] = value
-            if 'bidir' in line:
-                tmp['bidir'] = True
-            else:
-                tmp['bidir'] = False
-            value_list.append(tmp)
-    return value_list
-
 
 def get_existing(module, args):
     existing = {}
     config = str(get_config(module))
-    existing = get_value(config, module)
-    return existing
+    address = module.params['rp_address']
 
+    pim_address_re = r'ip pim rp-address (?P<value>.*)$'
+    for line in re.findall(pim_address_re, config, re.M):
 
-def apply_key_map(key_map, table):
-    new_dict = {}
-    for key, value in table.items():
-        new_key = key_map.get(key)
-        if new_key:
-            value = table.get(key)
-            if value:
-                new_dict[new_key] = value
-            else:
-                new_dict[new_key] = value
-    return new_dict
+        values = line.split()
+        if values[0] != address:
+            continue
+
+        existing['bidir'] = existing.get('bidir') or 'bidir' in line
+        if len(values) > 2:
+            value = values[1]
+            if values[2] == 'route-map':
+                existing['route_map'] = value
+            elif values[2] == 'prefix-list':
+                existing['prefix_list'] = value
+            elif values[2] == 'group-list':
+                existing['group_list'] = value
+
+    return existing
 
 
 def state_present(module, existing, proposed, candidate):
-    command = 'ip pim rp-address {0}'.format(module.params['rp_address'])
+    address = module.params['rp_address']
+    command = 'ip pim rp-address {0}'.format(address)
     commands = build_command(proposed, command)
     if commands:
         candidate.add(commands, parents=[])
@@ -186,17 +132,16 @@ def build_command(param_dict, command):
     return [command]
 
 
-def state_absent(module, existing, proposed, candidate):
-    commands = list()
-    for each in existing:
-        if each.get('rp_address') == proposed['rp_address']:
-            command = 'no ip pim rp-address {0}'.format(proposed['rp_address'])
-            if each.get('group_list'):
-                commands = build_command(each, command)
-            else:
-                commands = [command]
-    if commands:
-        candidate.add(commands, parents=[])
+def state_absent(module, existing, candidate):
+    address = module.params['rp_address']
+
+    command = 'no ip pim rp-address {0}'.format(address)
+    if existing.get('group_list'):
+        commands = build_command(existing, command)
+    else:
+        commands = [command]
+
+    candidate.add(commands, parents=[])
 
 
 def main():
@@ -206,28 +151,23 @@ def main():
         prefix_list=dict(required=False, type='str'),
         route_map=dict(required=False, type='str'),
         bidir=dict(required=False, type='bool'),
-        state=dict(choices=['present', 'absent'], default='present',
-                       required=False),
-        include_defaults=dict(default=False),
-        config=dict(),
-        save=dict(type='bool', default=False)
+        state=dict(choices=['present', 'absent'], default='present', required=False),
     )
-
     argument_spec.update(nxos_argument_spec)
 
     module = AnsibleModule(argument_spec=argument_spec,
-                                mutually_exclusive=[['group_list', 'route_map'],
-                                                    ['group_list', 'prefix_list'],
-                                                    ['route_map', 'prefix_list']],
-                                supports_check_mode=True)
+                           mutually_exclusive=[['group_list', 'route_map'],
+                                               ['group_list', 'prefix_list'],
+                                               ['route_map', 'prefix_list']],
+                           supports_check_mode=True)
 
     warnings = list()
     check_args(module, warnings)
-
+    result = {'changed': False, 'commands': [], 'warnings': warnings}
 
     state = module.params['state']
 
-    args =  [
+    args = [
         'rp_address',
         'group_list',
         'prefix_list',
@@ -235,39 +175,35 @@ def main():
         'bidir'
     ]
 
-    existing = invoke('get_existing', module, args)
-    end_state = existing
+    existing = get_existing(module, args)
     proposed_args = dict((k, v) for k, v in module.params.items()
-                    if v is not None and k in args)
+                         if v is not None and k in args)
 
     proposed = {}
     for key, value in proposed_args.items():
-        if str(value).lower() == 'true':
-            value = True
-        elif str(value).lower() == 'false':
-            value = False
-        for each in existing:
-            if each.get(key) or (not each.get(key) and value):
+        if key != 'rp_address':
+            if str(value).lower() == 'true':
+                value = True
+            elif str(value).lower() == 'false':
+                value = False
+
+            if existing.get(key) != value:
                 proposed[key] = value
 
-    result = {}
     candidate = CustomNetworkConfig(indent=3)
-    invoke('state_%s' % state, module, existing, proposed, candidate)
-    response = load_config(module, candidate)
-    result.update(response)
+    if state == 'present' and (proposed or not existing):
+        state_present(module, existing, proposed, candidate)
+    elif state == 'absent' and existing:
+        state_absent(module, existing, candidate)
 
-    if module._verbosity > 0:
-        end_state = invoke('get_existing', module, args)
-        result['end_state'] = end_state
-        result['existing'] = existing
-        result['proposed'] = proposed_args
-
-    if WARNINGS:
-        result['warnings'] = WARNINGS
+    if candidate:
+        candidate = candidate.items_text()
+        result['commands'] = candidate
+        result['changed'] = True
+        load_config(module, candidate)
 
     module.exit_json(**result)
 
 
 if __name__ == '__main__':
     main()
-


Test patch:
diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt
--- a/test/sanity/pep8/legacy-files.txt
+++ b/test/sanity/pep8/legacy-files.txt
@@ -372,7 +372,6 @@ lib/ansible/modules/network/nxos/nxos_ntp_options.py
 lib/ansible/modules/network/nxos/nxos_nxapi.py
 lib/ansible/modules/network/nxos/nxos_overlay_global.py
 lib/ansible/modules/network/nxos/nxos_pim_interface.py
-lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
 lib/ansible/modules/network/nxos/nxos_ping.py
 lib/ansible/modules/network/nxos/nxos_smu.py
 lib/ansible/modules/network/nxos/nxos_snapshot.py
diff --git a/test/units/modules/network/nxos/fixtures/nxos_pim_rp_address/config.cfg b/test/units/modules/network/nxos/fixtures/nxos_pim_rp_address/config.cfg
new file mode 100644
--- /dev/null
+++ b/test/units/modules/network/nxos/fixtures/nxos_pim_rp_address/config.cfg
@@ -0,0 +1 @@
+ip pim rp-address 1.2.3.4
diff --git a/test/units/modules/network/nxos/test_nxos_pim_rp_address.py b/test/units/modules/network/nxos/test_nxos_pim_rp_address.py
new file mode 100644
--- /dev/null
+++ b/test/units/modules/network/nxos/test_nxos_pim_rp_address.py
@@ -0,0 +1,62 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+
+from ansible.compat.tests.mock import patch
+from ansible.modules.network.nxos import nxos_pim_rp_address
+from .nxos_module import TestNxosModule, load_fixture, set_module_args
+
+
+class TestNxosPimRpAddressModule(TestNxosModule):
+
+    module = nxos_pim_rp_address
+
+    def setUp(self):
+        self.mock_load_config = patch('ansible.modules.network.nxos.nxos_pim_rp_address.load_config')
+        self.load_config = self.mock_load_config.start()
+
+        self.mock_get_config = patch('ansible.modules.network.nxos.nxos_pim_rp_address.get_config')
+        self.get_config = self.mock_get_config.start()
+
+    def tearDown(self):
+        self.mock_load_config.stop()
+        self.mock_get_config.stop()
+
+    def load_fixtures(self, commands=None, device=''):
+        self.get_config.return_value = load_fixture('nxos_pim_rp_address', 'config.cfg')
+        self.load_config.return_value = None
+
+    def test_nxos_pim_rp_address(self):
+        set_module_args(dict(rp_address='5.6.7.8'))
+        self.execute_module(changed=True, commands=['ip pim rp-address 5.6.7.8'])
+
+    def test_nxos_pim_rp_address_no_change(self):
+        set_module_args(dict(rp_address='1.2.3.4'))
+        self.execute_module(changed=False, commands=[])
+
+    def test_nxos_pim_rp_address_absent(self):
+        set_module_args(dict(rp_address='1.2.3.4', state='absent'))
+        self.execute_module(changed=True, commands=['no ip pim rp-address 1.2.3.4'])
+
+    def test_nxos_pim_rp_address_absent_no_change(self):
+        set_module_args(dict(rp_address='5.6.7.8', state='absent'))
+        self.execute_module(changed=False, commands=[])