We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ios_config multiline banner timeout
<!---
This looks to match issue 5318 which is listed as resolved but I am having the same issue. I have used ^ as the deliminator in the src file as well as the default @.
-->

##### ISSUE TYPE
<!---
 - Bug Report
-->
##### COMPONENT NAME
```
<!---
ios_config
-->
```
##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
adminlen@len-nm-1:~/ansible$ ansible --version
ansible 2.3.0
  config file = /home/adminlen/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
-->

##### CONFIGURATION
<!---
```
adminlen@len-nm-1:~/ansible$ cat ansible.cfg
[defaults]
transport = paramiko
hostfile = ./myhosts
host_key_checking = True
timeout = 5
```
-->

##### OS / ENVIRONMENT
<!---
```
I am running from ubuntu server 16.04.
i am managing Cisco IOS 15.5.3
```
-->

##### SUMMARY
<!---
```
The playbook timeouts when applying multiline banner, either login or motd.
```
-->

##### STEPS TO REPRODUCE
<!---
```
Here is my playbook and src file:
ansible$ cat router-login-banner.yml
---
-hosts: testsitehsrp1
gather_facts: no
connection: local

tasks:
    name: Set motd and alias commands for dsl
    ios_config:
    username: adminlen
    save: yes
    src: /home/adminlen/ansible/router-login-banner-test

adminlen@len-nm-1:~/ansible$ cat router-login-banner-test
banner login @

test login
banner

@
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- hosts: testsitehsrp1
  gather_facts: no
  connection: local

  tasks:
  - name: Set motd and alias commands for dsl
    ios_config:
      username: adminlen
      save: yes
      src: /home/adminlen/ansible/router-login-banner-test

```

##### EXPECTED RESULTS
<!--- 
```
Here is what happens when the banner is contained on a single line. This is what I expect to happen with the multiline banner

---
- hosts: testsitehsrp1
  gather_facts: no
  connection: local

  tasks:
  - name: Set motd and alias commands for dsl
    ios_config:
      username: adminlen
      save: yes
      src: /home/adminlen/ansible/router-login-banner-test-1line

adminlen@len-nm-1:~/ansible$ cat router-login-banner-test-1line
banner login @ test 1 line banner @

adminlen@len-nm-1:~/ansible$ ansible-playbook router-login-banner-2.yml --ask-pass
SSH password:

PLAY [testsitehsrp1] ******************************************************************************************************************

TASK [Set motd and alias commands for dsl] ********************************************************************************************
 [WARNING]: argument username has been deprecated and will be removed in a future version

changed: [testsitehsrp1]

PLAY RECAP ****************************************************************************************************************************
testsitehsrp1              : ok=1    changed=1    unreachable=0    failed=0

```
 -->

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
adminlen@len-nm-1:~/ansible$ ansible-playbook -vvv router-login-banner.yml --ask-pass
Using /home/adminlen/ansible/ansible.cfg as config file
SSH password:

PLAYBOOK: router-login-banner.yml *******************************************************************************
1 plays in router-login-banner.yml

PLAY [testsitehsrp1] ********************************************************************************************
META: ran handlers

TASK [Set motd and alias commands for dsl] **********************************************************************
task path: /home/adminlen/ansible/router-login-banner.yml:7
Using module file /usr/local/lib/python2.7/dist-packages/ansible-2.3.0-py2.7.egg/ansible/modules/network/ios/ios_config.py
<10.100.80.2> ESTABLISH LOCAL CONNECTION FOR USER: adminlen
<10.100.80.2> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.100.80.2> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534" && echo ansible-tmp-1487961451.38-133078886647534="echo /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534" ) && sleep 0'
<10.100.80.2> PUT /tmp/tmpIbJY6x TO /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ios_config.py
<10.100.80.2> EXEC /bin/sh -c 'chmod u+x /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ios_config.py && sleep 0'
<10.100.80.2> EXEC /bin/sh -c '/usr/bin/python /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ios_config.py; rm -rf "/home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/" > /dev/null 2>&1 && sleep 0'
fatal: [testsitehsrp1]: FAILED! => {
"changed": false,
"command": "banner login @",
"failed": true,
"invocation": {
"module_args": {
"after": null,
"auth_pass": null,
"authorize": null,
"backup": false,
"before": null,
"config": null,
"defaults": false,
"force": false,
"host": null,
"lines": null,
"match": "line",
"multiline_delimiter": "@",
"parents": null,
"password": null,
"port": null,
"provider": null,
"replace": "line",
"save": true,
"src": "banner login @ \n\ntest login\nbanner\n\n@\n\n",
"ssh_keyfile": null,
"timeout": null,
"username": "adminlen"
}
},
"msg": "timeout trying to send command: banner login @",
"rc": 1
}
to retry, use: --limit @/home/adminlen/ansible/router-login-banner.retry

PLAY RECAP ******************************************************************************************************
testsitehsrp1 : ok=0 changed=0 unreachable=0 failed=1
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/ansible/modules/network/ios/ios_banner.py`
Content:
```
1 #!/usr/bin/python
2 #
3 # This file is part of Ansible
4 #
5 # Ansible is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Ansible is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 
19 ANSIBLE_METADATA = {'metadata_version': '1.0',
20                     'status': ['preview'],
21                     'supported_by': 'community'}
22 
23 
24 DOCUMENTATION = """
25 ---
26 module: ios_banner
27 version_added: "2.3"
28 author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
29 short_description: Manage multiline banners on Cisco IOS devices
30 description:
31   - This will configure both login and motd banners on remote devices
32     running Cisco IOS.  It allows playbooks to add or remote
33     banner text from the active running configuration.
34 extends_documentation_fragment: ios
35 options:
36   banner:
37     description:
38       - Specifies which banner that should be
39         configured on the remote device.
40     required: true
41     default: null
42     choices: ['login', 'banner']
43   text:
44     description:
45       - The banner text that should be
46         present in the remote device running configuration.  This argument
47         accepts a multiline string. Requires I(state=present).
48     default: null
49   state:
50     description:
51       - Specifies whether or not the configuration is
52         present in the current devices active running configuration.
53     default: present
54     choices: ['present', 'absent']
55 """
56 
57 EXAMPLES = """
58 - name: configure the login banner
59   ios_banner:
60     banner: login
61     text: |
62       this is my login banner
63       that contains a multiline
64       string
65     state: present
66 
67 - name: remove the motd banner
68   ios_banner:
69     banner: motd
70     state: absent
71 """
72 
73 RETURN = """
74 commands:
75   description: The list of configuration mode commands to send to the device
76   returned: always
77   type: list
78   sample:
79     - banner login
80     - this is my login banner
81     - that contains a multiline
82     - string
83 """
84 from ansible.module_utils.basic import AnsibleModule
85 from ansible.module_utils.connection import exec_command
86 from ansible.module_utils.ios import load_config, run_commands
87 from ansible.module_utils.ios import ios_argument_spec, check_args
88 import re
89 
90 def map_obj_to_commands(updates, module):
91     commands = list()
92     want, have = updates
93     state = module.params['state']
94 
95     if state == 'absent' and have['text']:
96         commands.append('no banner %s' % module.params['banner'])
97 
98     elif state == 'present':
99         if want['text'] and (want['text'] != have.get('text')):
100             banner_cmd = 'banner %s' % module.params['banner']
101             banner_cmd += ' @\n'
102             banner_cmd += want['text'].strip()
103             banner_cmd += '\n@'
104             commands.append(banner_cmd)
105 
106     return commands
107 
108 def map_config_to_obj(module):
109     rc, out, err = exec_command(module, 'show banner %s' % module.params['banner'])
110     if rc == 0:
111         output = out
112     else:
113         rc, out, err = exec_command(module,
114                                     'show running-config | begin banner %s'
115                                     % module.params['banner'])
116         output = re.search('\^C(.*)\^C', out, re.S).group(1).strip()
117     obj = {'banner': module.params['banner'], 'state': 'absent'}
118     if output:
119         obj['text'] = output
120         obj['state'] = 'present'
121     return obj
122 
123 def map_params_to_obj(module):
124     text = module.params['text']
125     if text:
126         text = str(text).strip()
127 
128     return {
129         'banner': module.params['banner'],
130         'text': text,
131         'state': module.params['state']
132     }
133 
134 def main():
135     """ main entry point for module execution
136     """
137     argument_spec = dict(
138         banner=dict(required=True, choices=['login', 'motd']),
139         text=dict(),
140         state=dict(default='present', choices=['present', 'absent'])
141     )
142 
143     argument_spec.update(ios_argument_spec)
144 
145     required_if = [('state', 'present', ('text',))]
146 
147     module = AnsibleModule(argument_spec=argument_spec,
148                            required_if=required_if,
149                            supports_check_mode=True)
150 
151     warnings = list()
152     check_args(module, warnings)
153 
154     result = {'changed': False}
155     if warnings:
156         result['warnings'] = warnings
157     want = map_params_to_obj(module)
158     have = map_config_to_obj(module)
159 
160     commands = map_obj_to_commands((want, have), module)
161     result['commands'] = commands
162 
163     if commands:
164         if not module.check_mode:
165             response = load_config(module, commands)
166 
167         result['changed'] = True
168 
169     module.exit_json(**result)
170 
171 if __name__ == '__main__':
172     main()
173
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/ansible/modules/network/ios/ios_banner.py b/lib/ansible/modules/network/ios/ios_banner.py
--- a/lib/ansible/modules/network/ios/ios_banner.py
+++ b/lib/ansible/modules/network/ios/ios_banner.py
@@ -113,7 +113,10 @@
         rc, out, err = exec_command(module,
                                     'show running-config | begin banner %s'
                                     % module.params['banner'])
-        output = re.search('\^C(.*)\^C', out, re.S).group(1).strip()
+        if out:
+            output = re.search('\^C(.*)\^C', out, re.S).group(1).strip()
+        else:
+            output = None
     obj = {'banner': module.params['banner'], 'state': 'absent'}
     if output:
         obj['text'] = output

{"golden_diff": "diff --git a/lib/ansible/modules/network/ios/ios_banner.py b/lib/ansible/modules/network/ios/ios_banner.py\n--- a/lib/ansible/modules/network/ios/ios_banner.py\n+++ b/lib/ansible/modules/network/ios/ios_banner.py\n@@ -113,7 +113,10 @@\n         rc, out, err = exec_command(module,\n                                     'show running-config | begin banner %s'\n                                     % module.params['banner'])\n-        output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\n+        if out:\n+            output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\n+        else:\n+            output = None\n     obj = {'banner': module.params['banner'], 'state': 'absent'}\n     if output:\n         obj['text'] = output\n", "issue": "ios_config multiline banner timeout\n<!---\r\nThis looks to match issue 5318 which is listed as resolved but I am having the same issue. I have used ^ as the deliminator in the src file as well as the default @.\r\n-->\r\n\r\n##### ISSUE TYPE\r\n<!---\r\n - Bug Report\r\n-->\r\n##### COMPONENT NAME\r\n```\r\n<!---\r\nios_config\r\n-->\r\n```\r\n##### ANSIBLE VERSION\r\n<!--- Paste verbatim output from \u201cansible --version\u201d between quotes below -->\r\n```\r\nadminlen@len-nm-1:~/ansible$ ansible --version\r\nansible 2.3.0\r\n  config file = /home/adminlen/ansible/ansible.cfg\r\n  configured module search path = Default w/o overrides\r\n```\r\n-->\r\n\r\n##### CONFIGURATION\r\n<!---\r\n```\r\nadminlen@len-nm-1:~/ansible$ cat ansible.cfg\r\n[defaults]\r\ntransport = paramiko\r\nhostfile = ./myhosts\r\nhost_key_checking = True\r\ntimeout = 5\r\n```\r\n-->\r\n\r\n##### OS / ENVIRONMENT\r\n<!---\r\n```\r\nI am running from ubuntu server 16.04.\r\ni am managing Cisco IOS 15.5.3\r\n```\r\n-->\r\n\r\n##### SUMMARY\r\n<!---\r\n```\r\nThe playbook timeouts when applying multiline banner, either login or motd.\r\n```\r\n-->\r\n\r\n##### STEPS TO REPRODUCE\r\n<!---\r\n```\r\nHere is my playbook and src file:\r\nansible$ cat router-login-banner.yml\r\n---\r\n-hosts: testsitehsrp1\r\ngather_facts: no\r\nconnection: local\r\n\r\ntasks:\r\n    name: Set motd and alias commands for dsl\r\n    ios_config:\r\n    username: adminlen\r\n    save: yes\r\n    src: /home/adminlen/ansible/router-login-banner-test\r\n\r\nadminlen@len-nm-1:~/ansible$ cat router-login-banner-test\r\nbanner login @\r\n\r\ntest login\r\nbanner\r\n\r\n@\r\n-->\r\n\r\n<!--- Paste example playbooks or commands between quotes below -->\r\n```yaml\r\n---\r\n- hosts: testsitehsrp1\r\n  gather_facts: no\r\n  connection: local\r\n\r\n  tasks:\r\n  - name: Set motd and alias commands for dsl\r\n    ios_config:\r\n      username: adminlen\r\n      save: yes\r\n      src: /home/adminlen/ansible/router-login-banner-test\r\n\r\n```\r\n\r\n##### EXPECTED RESULTS\r\n<!--- \r\n```\r\nHere is what happens when the banner is contained on a single line. This is what I expect to happen with the multiline banner\r\n\r\n---\r\n- hosts: testsitehsrp1\r\n  gather_facts: no\r\n  connection: local\r\n\r\n  tasks:\r\n  - name: Set motd and alias commands for dsl\r\n    ios_config:\r\n      username: adminlen\r\n      save: yes\r\n      src: /home/adminlen/ansible/router-login-banner-test-1line\r\n\r\nadminlen@len-nm-1:~/ansible$ cat router-login-banner-test-1line\r\nbanner login @ test 1 line banner @\r\n\r\nadminlen@len-nm-1:~/ansible$ ansible-playbook router-login-banner-2.yml --ask-pass\r\nSSH password:\r\n\r\nPLAY [testsitehsrp1] ******************************************************************************************************************\r\n\r\nTASK [Set motd and alias commands for dsl] ********************************************************************************************\r\n [WARNING]: argument username has been deprecated and will be removed in a future version\r\n\r\nchanged: [testsitehsrp1]\r\n\r\nPLAY RECAP ****************************************************************************************************************************\r\ntestsitehsrp1              : ok=1    changed=1    unreachable=0    failed=0\r\n\r\n```\r\n -->\r\n\r\n##### ACTUAL RESULTS\r\n<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->\r\n\r\n<!--- Paste verbatim command output between quotes below -->\r\n```\r\nadminlen@len-nm-1:~/ansible$ ansible-playbook -vvv router-login-banner.yml --ask-pass\r\nUsing /home/adminlen/ansible/ansible.cfg as config file\r\nSSH password:\r\n\r\nPLAYBOOK: router-login-banner.yml *******************************************************************************\r\n1 plays in router-login-banner.yml\r\n\r\nPLAY [testsitehsrp1] ********************************************************************************************\r\nMETA: ran handlers\r\n\r\nTASK [Set motd and alias commands for dsl] **********************************************************************\r\ntask path: /home/adminlen/ansible/router-login-banner.yml:7\r\nUsing module file /usr/local/lib/python2.7/dist-packages/ansible-2.3.0-py2.7.egg/ansible/modules/network/ios/ios_config.py\r\n<10.100.80.2> ESTABLISH LOCAL CONNECTION FOR USER: adminlen\r\n<10.100.80.2> EXEC /bin/sh -c 'echo ~ && sleep 0'\r\n<10.100.80.2> EXEC /bin/sh -c '( umask 77 && mkdir -p \"echo /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534\" && echo ansible-tmp-1487961451.38-133078886647534=\"echo /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534\" ) && sleep 0'\r\n<10.100.80.2> PUT /tmp/tmpIbJY6x TO /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ios_config.py\r\n<10.100.80.2> EXEC /bin/sh -c 'chmod u+x /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ios_config.py && sleep 0'\r\n<10.100.80.2> EXEC /bin/sh -c '/usr/bin/python /home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/ios_config.py; rm -rf \"/home/adminlen/.ansible/tmp/ansible-tmp-1487961451.38-133078886647534/\" > /dev/null 2>&1 && sleep 0'\r\nfatal: [testsitehsrp1]: FAILED! => {\r\n\"changed\": false,\r\n\"command\": \"banner login @\",\r\n\"failed\": true,\r\n\"invocation\": {\r\n\"module_args\": {\r\n\"after\": null,\r\n\"auth_pass\": null,\r\n\"authorize\": null,\r\n\"backup\": false,\r\n\"before\": null,\r\n\"config\": null,\r\n\"defaults\": false,\r\n\"force\": false,\r\n\"host\": null,\r\n\"lines\": null,\r\n\"match\": \"line\",\r\n\"multiline_delimiter\": \"@\",\r\n\"parents\": null,\r\n\"password\": null,\r\n\"port\": null,\r\n\"provider\": null,\r\n\"replace\": \"line\",\r\n\"save\": true,\r\n\"src\": \"banner login @ \\n\\ntest login\\nbanner\\n\\n@\\n\\n\",\r\n\"ssh_keyfile\": null,\r\n\"timeout\": null,\r\n\"username\": \"adminlen\"\r\n}\r\n},\r\n\"msg\": \"timeout trying to send command: banner login @\",\r\n\"rc\": 1\r\n}\r\nto retry, use: --limit @/home/adminlen/ansible/router-login-banner.retry\r\n\r\nPLAY RECAP ******************************************************************************************************\r\ntestsitehsrp1 : ok=0 changed=0 unreachable=0 failed=1\r\n```\r\n\n", "before_files": [{"content": "#!/usr/bin/python\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n#\n\nANSIBLE_METADATA = {'metadata_version': '1.0',\n                    'status': ['preview'],\n                    'supported_by': 'community'}\n\n\nDOCUMENTATION = \"\"\"\n---\nmodule: ios_banner\nversion_added: \"2.3\"\nauthor: \"Ricardo Carrillo Cruz (@rcarrillocruz)\"\nshort_description: Manage multiline banners on Cisco IOS devices\ndescription:\n  - This will configure both login and motd banners on remote devices\n    running Cisco IOS.  It allows playbooks to add or remote\n    banner text from the active running configuration.\nextends_documentation_fragment: ios\noptions:\n  banner:\n    description:\n      - Specifies which banner that should be\n        configured on the remote device.\n    required: true\n    default: null\n    choices: ['login', 'banner']\n  text:\n    description:\n      - The banner text that should be\n        present in the remote device running configuration.  This argument\n        accepts a multiline string. Requires I(state=present).\n    default: null\n  state:\n    description:\n      - Specifies whether or not the configuration is\n        present in the current devices active running configuration.\n    default: present\n    choices: ['present', 'absent']\n\"\"\"\n\nEXAMPLES = \"\"\"\n- name: configure the login banner\n  ios_banner:\n    banner: login\n    text: |\n      this is my login banner\n      that contains a multiline\n      string\n    state: present\n\n- name: remove the motd banner\n  ios_banner:\n    banner: motd\n    state: absent\n\"\"\"\n\nRETURN = \"\"\"\ncommands:\n  description: The list of configuration mode commands to send to the device\n  returned: always\n  type: list\n  sample:\n    - banner login\n    - this is my login banner\n    - that contains a multiline\n    - string\n\"\"\"\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible.module_utils.connection import exec_command\nfrom ansible.module_utils.ios import load_config, run_commands\nfrom ansible.module_utils.ios import ios_argument_spec, check_args\nimport re\n\ndef map_obj_to_commands(updates, module):\n    commands = list()\n    want, have = updates\n    state = module.params['state']\n\n    if state == 'absent' and have['text']:\n        commands.append('no banner %s' % module.params['banner'])\n\n    elif state == 'present':\n        if want['text'] and (want['text'] != have.get('text')):\n            banner_cmd = 'banner %s' % module.params['banner']\n            banner_cmd += ' @\\n'\n            banner_cmd += want['text'].strip()\n            banner_cmd += '\\n@'\n            commands.append(banner_cmd)\n\n    return commands\n\ndef map_config_to_obj(module):\n    rc, out, err = exec_command(module, 'show banner %s' % module.params['banner'])\n    if rc == 0:\n        output = out\n    else:\n        rc, out, err = exec_command(module,\n                                    'show running-config | begin banner %s'\n                                    % module.params['banner'])\n        output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\n    obj = {'banner': module.params['banner'], 'state': 'absent'}\n    if output:\n        obj['text'] = output\n        obj['state'] = 'present'\n    return obj\n\ndef map_params_to_obj(module):\n    text = module.params['text']\n    if text:\n        text = str(text).strip()\n\n    return {\n        'banner': module.params['banner'],\n        'text': text,\n        'state': module.params['state']\n    }\n\ndef main():\n    \"\"\" main entry point for module execution\n    \"\"\"\n    argument_spec = dict(\n        banner=dict(required=True, choices=['login', 'motd']),\n        text=dict(),\n        state=dict(default='present', choices=['present', 'absent'])\n    )\n\n    argument_spec.update(ios_argument_spec)\n\n    required_if = [('state', 'present', ('text',))]\n\n    module = AnsibleModule(argument_spec=argument_spec,\n                           required_if=required_if,\n                           supports_check_mode=True)\n\n    warnings = list()\n    check_args(module, warnings)\n\n    result = {'changed': False}\n    if warnings:\n        result['warnings'] = warnings\n    want = map_params_to_obj(module)\n    have = map_config_to_obj(module)\n\n    commands = map_obj_to_commands((want, have), module)\n    result['commands'] = commands\n\n    if commands:\n        if not module.check_mode:\n            response = load_config(module, commands)\n\n        result['changed'] = True\n\n    module.exit_json(**result)\n\nif __name__ == '__main__':\n    main()\n", "path": "lib/ansible/modules/network/ios/ios_banner.py"}], "after_files": [{"content": "#!/usr/bin/python\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n#\n\nANSIBLE_METADATA = {'metadata_version': '1.0',\n                    'status': ['preview'],\n                    'supported_by': 'community'}\n\n\nDOCUMENTATION = \"\"\"\n---\nmodule: ios_banner\nversion_added: \"2.3\"\nauthor: \"Ricardo Carrillo Cruz (@rcarrillocruz)\"\nshort_description: Manage multiline banners on Cisco IOS devices\ndescription:\n  - This will configure both login and motd banners on remote devices\n    running Cisco IOS.  It allows playbooks to add or remote\n    banner text from the active running configuration.\nextends_documentation_fragment: ios\noptions:\n  banner:\n    description:\n      - Specifies which banner that should be\n        configured on the remote device.\n    required: true\n    default: null\n    choices: ['login', 'banner']\n  text:\n    description:\n      - The banner text that should be\n        present in the remote device running configuration.  This argument\n        accepts a multiline string. Requires I(state=present).\n    default: null\n  state:\n    description:\n      - Specifies whether or not the configuration is\n        present in the current devices active running configuration.\n    default: present\n    choices: ['present', 'absent']\n\"\"\"\n\nEXAMPLES = \"\"\"\n- name: configure the login banner\n  ios_banner:\n    banner: login\n    text: |\n      this is my login banner\n      that contains a multiline\n      string\n    state: present\n\n- name: remove the motd banner\n  ios_banner:\n    banner: motd\n    state: absent\n\"\"\"\n\nRETURN = \"\"\"\ncommands:\n  description: The list of configuration mode commands to send to the device\n  returned: always\n  type: list\n  sample:\n    - banner login\n    - this is my login banner\n    - that contains a multiline\n    - string\n\"\"\"\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible.module_utils.connection import exec_command\nfrom ansible.module_utils.ios import load_config, run_commands\nfrom ansible.module_utils.ios import ios_argument_spec, check_args\nimport re\n\ndef map_obj_to_commands(updates, module):\n    commands = list()\n    want, have = updates\n    state = module.params['state']\n\n    if state == 'absent' and have['text']:\n        commands.append('no banner %s' % module.params['banner'])\n\n    elif state == 'present':\n        if want['text'] and (want['text'] != have.get('text')):\n            banner_cmd = 'banner %s' % module.params['banner']\n            banner_cmd += ' @\\n'\n            banner_cmd += want['text'].strip()\n            banner_cmd += '\\n@'\n            commands.append(banner_cmd)\n\n    return commands\n\ndef map_config_to_obj(module):\n    rc, out, err = exec_command(module, 'show banner %s' % module.params['banner'])\n    if rc == 0:\n        output = out\n    else:\n        rc, out, err = exec_command(module,\n                                    'show running-config | begin banner %s'\n                                    % module.params['banner'])\n        if out:\n            output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\n        else:\n            output = None\n    obj = {'banner': module.params['banner'], 'state': 'absent'}\n    if output:\n        obj['text'] = output\n        obj['state'] = 'present'\n    return obj\n\ndef map_params_to_obj(module):\n    text = module.params['text']\n    if text:\n        text = str(text).strip()\n\n    return {\n        'banner': module.params['banner'],\n        'text': text,\n        'state': module.params['state']\n    }\n\ndef main():\n    \"\"\" main entry point for module execution\n    \"\"\"\n    argument_spec = dict(\n        banner=dict(required=True, choices=['login', 'motd']),\n        text=dict(),\n        state=dict(default='present', choices=['present', 'absent'])\n    )\n\n    argument_spec.update(ios_argument_spec)\n\n    required_if = [('state', 'present', ('text',))]\n\n    module = AnsibleModule(argument_spec=argument_spec,\n                           required_if=required_if,\n                           supports_check_mode=True)\n\n    warnings = list()\n    check_args(module, warnings)\n\n    result = {'changed': False}\n    if warnings:\n        result['warnings'] = warnings\n    want = map_params_to_obj(module)\n    have = map_config_to_obj(module)\n\n    commands = map_obj_to_commands((want, have), module)\n    result['commands'] = commands\n\n    if commands:\n        if not module.check_mode:\n            response = load_config(module, commands)\n\n        result['changed'] = True\n\n    module.exit_json(**result)\n\nif __name__ == '__main__':\n    main()\n", "path": "lib/ansible/modules/network/ios/ios_banner.py"}]}