Repository: ansible/ansible

Issue:
Allow iosxr config module to use admin config mode
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Feature Idea

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
iosxr_config and iosxr util modules

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
$ ansible --version
ansible 2.2.1.0
  config file = /home/jmighion/git/blank-ansible-repo/ansible.cfg
  configured module search path = Default w/o overrides
```

##### SUMMARY
<!--- Explain the problem briefly -->
IOS-XR has an admin config mode to configure different things on the device. A simple boolean could be passed through the `iosxr_config` module param to the iosxr util module's `load_config` method to conditionally prepend "admin " to the initial "configure terminal" command. This would allow the `iosxr_config` module to configure things like local passwords or license info.




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

Resolving patch:
diff --git a/lib/ansible/module_utils/iosxr.py b/lib/ansible/module_utils/iosxr.py
--- a/lib/ansible/module_utils/iosxr.py
+++ b/lib/ansible/module_utils/iosxr.py
@@ -102,9 +102,12 @@ def run_commands(module, commands, check_rc=True):
     return responses
 
 
-def load_config(module, commands, warnings, commit=False, replace=False, comment=None):
+def load_config(module, commands, warnings, commit=False, replace=False, comment=None, admin=False):
+    cmd = 'configure terminal'
+    if admin:
+        cmd = 'admin ' + cmd
 
-    rc, out, err = exec_command(module, 'configure terminal')
+    rc, out, err = exec_command(module, cmd)
     if rc != 0:
         module.fail_json(msg='unable to enter configuration mode', err=to_text(err, errors='surrogate_or_strict'))
 
@@ -137,6 +140,7 @@ def load_config(module, commands, warnings, commit=False, replace=False, comment
     else:
         cmd = 'abort'
         diff = None
+
     rc, out, err = exec_command(module, cmd)
     if rc != 0:
         exec_command(module, 'abort')
diff --git a/lib/ansible/modules/network/iosxr/iosxr_config.py b/lib/ansible/modules/network/iosxr/iosxr_config.py
--- a/lib/ansible/modules/network/iosxr/iosxr_config.py
+++ b/lib/ansible/modules/network/iosxr/iosxr_config.py
@@ -146,6 +146,14 @@
     required: false
     default: 'configured by iosxr_config'
     version_added: "2.2"
+  admin:
+    description:
+      - Enters into administration configuration mode for making config
+        changes to the device.
+    required: false
+    default: false
+    choices: [ "yes", "no" ]
+    version_added: "2.4"
 """
 
 EXAMPLES = """
@@ -218,6 +226,7 @@ def run(module, result):
     replace_config = replace == 'config'
     path = module.params['parents']
     comment = module.params['comment']
+    admin = module.params['admin']
     check_mode = module.check_mode
 
     candidate = get_candidate(module)
@@ -243,7 +252,7 @@ def run(module, result):
             result['commands'] = commands
 
         diff = load_config(module, commands, result['warnings'],
-                           not check_mode, replace_config, comment)
+                           not check_mode, replace_config, comment, admin)
         if diff:
             result['diff'] = dict(prepared=diff)
             result['changed'] = True
@@ -270,6 +279,7 @@ def main():
         config=dict(),
         backup=dict(type='bool', default=False),
         comment=dict(default=DEFAULT_COMMIT_COMMENT),
+        admin=dict(type='bool', default=False)
     )
 
     argument_spec.update(iosxr_argument_spec)


Test patch:
diff --git a/test/units/modules/network/iosxr/test_iosxr_config.py b/test/units/modules/network/iosxr/test_iosxr_config.py
--- a/test/units/modules/network/iosxr/test_iosxr_config.py
+++ b/test/units/modules/network/iosxr/test_iosxr_config.py
@@ -107,6 +107,11 @@ def test_iosxr_config_force(self):
         set_module_args(dict(lines=lines, force=True))
         self.execute_module(changed=True, commands=lines)
 
+    def test_iosxr_config_admin(self):
+        lines = ['username admin', 'group root-system', 'secret P@ssw0rd']
+        set_module_args(dict(lines=lines, admin=True))
+        self.execute_module(changed=True, commands=lines)
+
     def test_iosxr_config_match_none(self):
         lines = ['ip address 1.2.3.4 255.255.255.0', 'description test string']
         parents = ['interface GigabitEthernet0/0']