Repository: ansible/ansible

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
```



Discussion:
I am unable to reproduce:

```
(ansible) [ricky@ricky-laptop playbooks]$ ansible-playbook -i inventory.network ios/issue_22216.yaml -k
SSH password: 

PLAY [ios] ***********************************************************************************************************************************************************************************

TASK [Set motd and alias commands for dsl] ***************************************************************************************************************************************************
 [WARNING]: argument username has been deprecated and will be removed in a future version

changed: [ios01]

PLAY RECAP ***********************************************************************************************************************************************************************************
ios01                      : ok=1    changed=1    unreachable=0    failed=0   

(ansible) [ricky@ricky-laptop playbooks]$ cat ios/issue_22216.yaml 
---
- hosts: ios
  gather_facts: no
  connection: local
  remote_user: cisco

  tasks:
  - name: Set motd and alias commands for dsl
    ios_config:
      username: cisco
      save: yes
      src: issue_22216.banner
(ansible) [ricky@ricky-laptop playbooks]$ cat ios/issue_22216.banner 
banner login @ This is a banner for issue 22216 @
```

Can you please paste your src file ?
Your banner is on a single line which works mine is multiline

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

test login
banner

@



Len Tucker


On Thu, Mar 2, 2017 at 6:49 PM, Ricardo Carrillo Cruz <
notifications@github.com> wrote:

> I am unable to reproduce:
>
> (ansible) [ricky@ricky-laptop playbooks]$ ansible-playbook -i inventory.network ios/issue_22216.yaml -k
> SSH password:
>
> PLAY [ios] ***********************************************************************************************************************************************************************************
>
> TASK [Set motd and alias commands for dsl] ***************************************************************************************************************************************************
>  [WARNING]: argument username has been deprecated and will be removed in a future version
>
> changed: [ios01]
>
> PLAY RECAP ***********************************************************************************************************************************************************************************
> ios01                      : ok=1    changed=1    unreachable=0    failed=0
>
> (ansible) [ricky@ricky-laptop playbooks]$ cat ios/issue_22216.yaml
> ---
> - hosts: ios
>   gather_facts: no
>   connection: local
>   remote_user: cisco
>
>   tasks:
>   - name: Set motd and alias commands for dsl
>     ios_config:
>       username: cisco
>       save: yes
>       src: issue_22216.banner
> (ansible) [ricky@ricky-laptop playbooks]$ cat ios/issue_22216.banner
> banner login @ This is a banner for issue 22216 @
>
> Can you please paste your src file ?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-283820294>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOW-7Nu-Da6HSLzvNQWCvbjbdbHNXks5rh1WVgaJpZM4MRqfo>
> .
>

Thanks, I can reproduce.

Will take a look.
Just an FYI, this appears to have been addresses in the past but as you can
see it does not work.
https://github.com/ansible/ansible-modules-core/issues/5318

Len Tucker


On Thu, Mar 2, 2017 at 7:05 PM, Ricardo Carrillo Cruz <
notifications@github.com> wrote:

> Thanks, I can reproduce.
>
> Will take a look.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-283823257>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOUpiaygutQkKFg0YsZPOqxGlxqDXks5rh1lUgaJpZM4MRqfo>
> .
>

Having same issue. It is also not clear why `multiline_delimiter` is only allowed to one character and whether or not you intend to use `^C` (two characters) or the ascii character code 3 aka, `ETX` (one character). I would guess `^C` since it is applying the commands one at a time and not doing a merge, but since it is two characters, I am not sure.
Cisco IOS only allows a single character for the banner. Regardless of what
character you use for the banner in the configuration it cisco always
changes it to ^C.
Here is a test where i set the banner using @ as the deliminator. Then i do
a show run to show the config and you can see that it replaces with ^C.

router(config)#banner motd @

Enter TEXT message.  End with the character '@'.

This is my test banner

@
router(config)#do show run | begin banner motd

banner motd ^C

This is my test banner

^C

What appears to be happening with sensible is it was waiting for a reply
from >banner motd @
But nothing is returned and the command times out.

If you look at this bug which shows for the correct module they identified
the issue and it says they fixed it but its not.
https://github.com/ansible/ansible-modules-core/issues/5318

What are the next steps with the issue?


Len Tucker


On Sun, Mar 5, 2017 at 2:41 PM, Ken Celenza <notifications@github.com>
wrote:

> Having same issue. It is also not clear why multiline_delimiter is only
> allowed to one character and whether or not you intend to use ^C (two
> characters) or the ascii character code 3 aka, ETX (one character). I
> would guess ^C since it is applying the commands one at a time and not
> doing a merge, but since it is two characters, I am not sure.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-284255685>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOV4YLvKKlvfcaJ3h3p-l2i411FIFks5riw_XgaJpZM4MRqfo>
> .
>

Len, the point I was trying to make is cisco does allow `^C` to be used, which is seen as a representation of ascii code 3, ETX. It has to be one or the other, allow two characters--the way one would if using putty or any ssh client, or only allow 1 character but user must be careful to set it as ETX, for instance in vim you can do this in insert mode typing ctrl+V release the V, and then press C. This is not a method I would suspect common amongst users, and should be clearly documented if so.
Ken,
What are the odds of getting the multiline banner working?

Len Tucker


On Sun, Mar 5, 2017 at 11:01 PM, Ken Celenza <notifications@github.com>
wrote:

> Len, the point I was trying to make is cisco does allow ^C to be used,
> which is seen as a representation of ascii code 3, ETX. It has to be one or
> the other, allow two characters--the way one would if using putty or any
> ssh client, or only allow 1 character but user must be careful to set it as
> ETX, for instance in vim you can do this in insert mode typing ctrl+V
> release the V, and then press C. This is not a method I would suspect
> common amongst users, and should be clearly documented if so.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-284297671>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOcXVfPRhQgxvm9aLV0GD70y134qgks5ri4UygaJpZM4MRqfo>
> .
>

Multiline handling on Cisco IOS devices is hard due to the ^C mogrifying, making the codebase hard to maintain.

Therefore, I will fix this by creating an 'ios_banner' module, that will handle both single and multi-line, just like the newly created eos_banner module:

https://docs.ansible.com/ansible/eos_banner_module.html
@rcarrillocruz A solution is certainly better than no solution. That being said, it seems odd that there is no way to keep this in *_config? 

The ios_config module correctly identifies a banner and parses it. The only thing is the run_commands does not seem to like running the commands. 

@itdependsnetworks Can you please pull from devel and try out ios_banner module?

I just merged it.
The only issue I am running in to is that it does not include the newlines
so the banner ends up on one line. I included \n in the playbook and it
just added them to the banner.

adminlen@len-nm-1:~/ansible$ cat router-login-banner.yml
---
- hosts: testsitehsrp1
  gather_facts: no
  connection: local

  tasks:
  - name: Set motd and alias commands for dsl
    ios_banner:
      username: adminlen
      banner: login
      text:
        this is my\n
        multiline banner\n
        will it display correctly\n

results:
adminlen@len-nm-1:~$ ssh testsitehsrp1

this is my multiline banner will it display correctly
Password:

testsite-hsrp1#show banner login
this is my\n multiline banner\n will it display correctly\n



Len Tucker


On Thu, Mar 16, 2017 at 11:36 AM, Ricardo Carrillo Cruz <
notifications@github.com> wrote:

> @itdependsnetworks <https://github.com/itdependsnetworks> Can you please
> pull from devel and try out ios_banner module?
>
> I just merged it.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-287096400>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOfKW2VRUj-AttxfedccvgPXFdRHTks5rmVcPgaJpZM4MRqfo>
> .
>

To make a multi-line banner you should use the YAML literal block ('|'):

```
    ios_banner:
      username: adminlen
      banner: login
      text: |
        this is my
        multiline banner
        will it display correctly
```

Try it out, works for me like here: http://dpaste.com/1C1A4WJ
That works. How would I add formatting and not have all text left aligned
like:















*---- hosts: testsitehsrp1  gather_facts: no  connection: local  tasks:  -
name: Set motd and alias commands for dsl    ios_banner:      username:
adminlen      banner: login      text: |             this is my
multiline banner             will it display correctly*

Len Tucker


On Thu, Mar 16, 2017 at 12:04 PM, Ricardo Carrillo Cruz <
notifications@github.com> wrote:

> To make a multi-line block you should use the YAML literal block ('|'):
>
>     ios_banner:
>       username: adminlen
>       banner: login
>       text: |
>         this is my
>         multiline banner
>         will it display correctly
>
> Try it out, works for me like here: http://dpaste.com/1C1A4WJ
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-287105643>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznObX4iXyKI2xIe2-gnCGiBVmYLtf1ks5rmV2igaJpZM4MRqfo>
> .
>

Your previous comment didn't get formatted (you can use triple quotes to enclose text you don't want to be interpreted by the GH parser).
However, I take it you mean how to add spacing and not have everything left aligned.
You simply add your spaces, the initial indentation is just to let the YAML parser that you start the literal block, if you add more spaces then those will be printed out.
e.g.

```
- hosts: ios
  connection: local
  remote_user: cisco

  tasks:
    - name: Setup
      ios_banner:
        banner: login
        text: |
          Junk login banner
            multi (this one with two spaces indentation)
              line (this one with 4 spaces indentation)
          ! (this one with no indentation at all)
        state: present
        authorize: yes
```

Then after running the playbook:

```
Junk login banner
  multi (this one with two spaces indentation)
    line (this one with 4 spaces indentation)
! (this one with no indentation at all)
```
Is it possible to add spaces to the first line.
Most login banners start with
*** warning or something ***
Centered over a text block.

Len Tucker


On Thu, Mar 16, 2017 at 12:42 PM, Ricardo Carrillo Cruz <
notifications@github.com> wrote:

> Your previous comment didn't get formatted (you can use triple quotes to
> enclose text you don't want to be interpreted by the GH parser).
> However, I take it you mean how to add spacing and not have everything
> left aligned.
> You simply add your spaces, the initial indentation is just to let the
> YAML parser that you start the literal block, if you add more spaces then
> those will be printed out.
> e.g.
>
> - hosts: ios
>   connection: local
>   remote_user: cisco
>
>   tasks:
>     - name: Setup
>       ios_banner:
>         banner: login
>         text: |
>           Junk login banner
>             multi (this one with two spaces indentation)
>               line (this one with 4 spaces indentation)
>           ! (this one with no indentation at all)
>         state: present
>         authorize: yes
>
> Then after running the playbook:
>
> Junk login banner
>   multi (this one with two spaces indentation)
>     line (this one with 4 spaces indentation)
> ! (this one with no indentation at all)
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-287117617>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOefyOqcxZwr6XrpwwHO2OgYTWUrzks5rmWaSgaJpZM4MRqfo>
> .
>

Thanks for the update. As per IRC chat, it did not work for me, here is my pb and output

```
---

- name: Test playbook for index number
  hosts: ios
  connection: local
  gather_facts: no

  tasks:

  - name: "IOS CONFIG TEST"
    ios_config:
      commands: "ip route 10.200.200.200 255.255.255.255 10.200.201.1"
      host: "{{ ansible_host }}"
      username: "{{user }}"
      password: "{{ password }}"

  - name: "BANNER TEST"
    ios_banner:
      banner: "motd"
      text: |
        this is my login banner
        that contains a multiline
        string
      state: "present"
      host: "{{ ansible_host }}"
      username: "{{user }}"
      password: "{{ password }}"
```


```
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible-playbook -i inventory banner.yml -vvvv
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /home/ken/.virtualenvs/ansibledev/local/lib/python2.7/site-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: banner.yml *********************************************************************************************************************************************************************************************
1 plays in banner.yml

PLAY [Test playbook for index number] ****************************************************************************************************************************************************************************
META: ran handlers

TASK [IOS CONFIG TEST] *******************************************************************************************************************************************************************************************
task path: /github/cookbook/banner.yml:14
Using module file /home/ken/.virtualenvs/ansibledev/local/lib/python2.7/site-packages/ansible/modules/network/ios/ios_config.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872 `" && echo ansible-tmp-1489692259.87-212522245230872="` echo /home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmpZ4IWfr TO /home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872/ios_config.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872/ /home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872/ios_config.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872/ios_config.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1489692259.87-212522245230872/" > /dev/null 2>&1 && sleep 0'
 [WARNING]: argument username has been deprecated and will be removed in a future version

 [WARNING]: argument host has been deprecated and will be removed in a future version

 [WARNING]: argument password has been deprecated and will be removed in a future version

ok: [ios] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "after": null,
            "auth_pass": null,
            "authorize": null,
            "backup": false,
            "before": null,
            "commands": "ip route 10.200.200.200 255.255.255.255 10.200.201.1",
            "config": null,
            "defaults": false,
            "force": false,
            "host": "10.1.100.46",
            "lines": [
                "ip route 10.200.200.200 255.255.255.255 10.200.201.1"
            ],
            "match": "line",
            "multiline_delimiter": "@",
            "parents": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "provider": null,
            "replace": "line",
            "save": false,
            "src": null,
            "ssh_keyfile": null,
            "timeout": null,
            "username": "ntc"
        }
    }
}

TASK [BANNER TEST] ***********************************************************************************************************************************************************************************************
task path: /github/cookbook/banner.yml:21
Using module file /home/ken/.virtualenvs/ansibledev/local/lib/python2.7/site-packages/ansible/modules/network/ios/ios_banner.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135 `" && echo ansible-tmp-1489692261.82-99058578747135="` echo /home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmpbFtvjh TO /home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135/ios_banner.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135/ /home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135/ios_banner.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135/ios_banner.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1489692261.82-99058578747135/" > /dev/null 2>&1 && sleep 0'
fatal: [ios]: FAILED! => {
    "changed": false,
    "failed": true,
    "invocation": {
        "module_args": {
            "auth_pass": null,
            "authorize": null,
            "banner": "motd",
            "host": "10.1.100.46",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "provider": null,
            "ssh_keyfile": null,
            "state": "present",
            "text": "this is my login banner\nthat contains a multiline\nstring\n",
            "timeout": null,
            "username": "ntc"
        }
    },
    "msg": "show banner motd\r\n              ^\r\n% Invalid input detected at '^' marker.\r\n\r\nny-sw01#",
    "rc": 1
}

PLAY RECAP *******************************************************************************************************************************************************************************************************
ios                        : ok=1    changed=0    unreachable=0    failed=1

(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$
```
So the user/pass/hostname at the task level is a red herring, it works for me the way you use it:

```
(ansible) [ricky@ricky-laptop playbooks]$ cat ios/test_ios_banner.yaml 
- hosts: ios
  connection: local

  tasks:
    - name: Setup
      ios_banner:
        banner:  motd
        text: |
          Junk motd banner
          multi
          line
        state: present
        authorize: yes
        host: "{{ ansible_host }}"
        username: "{{ user }}"
        password: "{{ password }}"
```

Running ansible works and changes the banner:

```
....
....
changed: [ios01] => {
    "changed": true, 
    "commands": [
        "banner motd @\nJunk motd banner\nmulti\nline\n@"
    ], 
    "invocation": {
        "module_args": {
            "auth_pass": null, 
            "authorize": true, 
            "banner": "motd", 
            "host": "ios01", 
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "port": null, 
            "provider": null, 
            "ssh_keyfile": null, 
            "state": "present", 
            "text": "Junk motd banner\nmulti\nline\n", 
            "timeout": null, 
            "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
        }
    }
}
META: ran handlers
META: ran handlers

PLAY RECAP ***********************************************************************************************************************************************************************************
ios01                      : ok=2    changed=1    unreachable=0    failed=0   
```

And this is the motd banner changed via IOS shell:

```
ios01#show banner motd
Junk motd banner
multi
line
```

The only thing I can think of is that you need to set 'authorize: yes' to your task?
Riccardo,

Thank you for your work on this module. It is greatly appreciated.

Len Tucker


On Thu, Mar 16, 2017 at 3:56 PM, Ricardo Carrillo Cruz <
notifications@github.com> wrote:

> So the user/pass/hostname at the task level is a red herring, it works for
> me the way you use it:
>
> (ansible) [ricky@ricky-laptop playbooks]$ cat ios/test_ios_banner.yaml
> - hosts: ios
>   connection: local
>
>   tasks:
>     - name: Setup
>       ios_banner:
>         banner:  motd
>         text: |
>           Junk motd banner
>           multi
>           line
>         state: present
>         authorize: yes
>         host: "{{ ansible_host }}"
>         username: "{{ user }}"
>         password: "{{ password }}"
>
> Running ansible works and changes the banner:
>
> ....
> ....
> changed: [ios01] => {
>     "changed": true,
>     "commands": [
>         "banner motd @\nJunk motd banner\nmulti\nline\n@"
>     ],
>     "invocation": {
>         "module_args": {
>             "auth_pass": null,
>             "authorize": true,
>             "banner": "motd",
>             "host": "ios01",
>             "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
>             "port": null,
>             "provider": null,
>             "ssh_keyfile": null,
>             "state": "present",
>             "text": "Junk motd banner\nmulti\nline\n",
>             "timeout": null,
>             "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
>         }
>     }
> }
> META: ran handlers
> META: ran handlers
>
> PLAY RECAP ***********************************************************************************************************************************************************************************
> ios01                      : ok=2    changed=1    unreachable=0    failed=0
>
> And this is the motd banner changed via IOS shell:
>
> ios01#show banner motd
> Junk motd banner
> multi
> line
>
> The only thing I can think of is that you need to set 'authorize: yes' to
> your task?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/22216#issuecomment-287172778>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AYznOa5K07cQ_dk97y1TReUkGa_kx3rhks5rmZPXgaJpZM4MRqfo>
> .
>

Is there a way to use a banner from an external file or does it have to be
in the playbook?

Len Tucker


On Thu, Mar 16, 2017 at 4:17 PM, Len Tucker <lentucker@gmail.com> wrote:

> Riccardo,
>
> Thank you for your work on this module. It is greatly appreciated.
>
> Len Tucker
>
>
> On Thu, Mar 16, 2017 at 3:56 PM, Ricardo Carrillo Cruz <
> notifications@github.com> wrote:
>
>> So the user/pass/hostname at the task level is a red herring, it works
>> for me the way you use it:
>>
>> (ansible) [ricky@ricky-laptop playbooks]$ cat ios/test_ios_banner.yaml
>> - hosts: ios
>>   connection: local
>>
>>   tasks:
>>     - name: Setup
>>       ios_banner:
>>         banner:  motd
>>         text: |
>>           Junk motd banner
>>           multi
>>           line
>>         state: present
>>         authorize: yes
>>         host: "{{ ansible_host }}"
>>         username: "{{ user }}"
>>         password: "{{ password }}"
>>
>> Running ansible works and changes the banner:
>>
>> ....
>> ....
>> changed: [ios01] => {
>>     "changed": true,
>>     "commands": [
>>         "banner motd @\nJunk motd banner\nmulti\nline\n@"
>>     ],
>>     "invocation": {
>>         "module_args": {
>>             "auth_pass": null,
>>             "authorize": true,
>>             "banner": "motd",
>>             "host": "ios01",
>>             "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
>>             "port": null,
>>             "provider": null,
>>             "ssh_keyfile": null,
>>             "state": "present",
>>             "text": "Junk motd banner\nmulti\nline\n",
>>             "timeout": null,
>>             "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
>>         }
>>     }
>> }
>> META: ran handlers
>> META: ran handlers
>>
>> PLAY RECAP ***********************************************************************************************************************************************************************************
>> ios01                      : ok=2    changed=1    unreachable=0    failed=0
>>
>> And this is the motd banner changed via IOS shell:
>>
>> ios01#show banner motd
>> Junk motd banner
>> multi
>> line
>>
>> The only thing I can think of is that you need to set 'authorize: yes' to
>> your task?
>>
>> —
>> You are receiving this because you authored the thread.
>> Reply to this email directly, view it on GitHub
>> <https://github.com/ansible/ansible/issues/22216#issuecomment-287172778>,
>> or mute the thread
>> <https://github.com/notifications/unsubscribe-auth/AYznOa5K07cQ_dk97y1TReUkGa_kx3rhks5rmZPXgaJpZM4MRqfo>
>> .
>>
>
>

I included the ios_config to show that it works there. Additionally confirmed user/pass brings you into privlege mode. 
@Len357 While there's no explicit parameter in the module to load a banner text from file, you can put the banner text in a variables file and use the Ansible vars_files/include_vars/-e @my_file_containing vars methods:

http://docs.ansible.com/ansible/playbooks_variables.html#variable-file-separation
http://docs.ansible.com/ansible/include_vars_module.html
http://docs.ansible.com/ansible/playbooks_variables.html#passing-variables-on-the-command-line

HTH
@itdependsnetworks I'm afraid I cannot reproduce, can you please run this playbook and let me know if you get an error? It works for me:

```
- hosts: ios
  connection: local

  tasks:
    - name: ios_config test
      ios_config:
        commands: no banner motd
        host: "{{ ansible_host }}"
        username: "{{ user }}"
        password: "{{ password }}"

    - name: Setup motd banner
      ios_banner:
        banner:  motd
        text: "{{ lookup('pipe', 'date') }}"
        state: present
        host: "{{ ansible_host }}"
        username: "{{ user }}"
        password: "{{ password }}"

(ansible) [ricky@ricky-laptop playbooks]$ ansible-playbook -i inventory.network ios/issue_ios_banner.yaml -e "user=cisco password=cisco"

PLAY [ios] ***********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************
ok: [ios01]

TASK [ios_config test] ***********************************************************************************************************************************************************************
 [WARNING]: argument username has been deprecated and will be removed in a future version

 [WARNING]: argument host has been deprecated and will be removed in a future version

 [WARNING]: argument password has been deprecated and will be removed in a future version

changed: [ios01]

TASK [Setup motd banner] *********************************************************************************************************************************************************************
changed: [ios01]

PLAY RECAP ***********************************************************************************************************************************************************************************
ios01                      : ok=3    changed=2    unreachable=0    failed=0   

```

What commit are you on?

This is my ansible --version output:

```
ansible 2.4.0 (devel dc68503ef2) last updated 2017/03/20 12:27:17 (GMT +200)
```
I believe I took this verison from devel shortly after you pushed. I can pull which ever commit level you need, but my `ansible --version` does not seem to give as specific output as yours. 
```
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible-playbook -i inventory banner2.yml -vvvv
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /home/ken/.virtualenvs/ansibledev/local/lib/python2.7/site-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: banner2.yml **********************************************************************************************************************************************************************************************************************************************************
1 plays in banner2.yml

PLAY [ios] *********************************************************************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [ios_config test] *********************************************************************************************************************************************************************************************************************************************************
task path: /github/cookbook/banner2.yml:12
Using module file /home/ken/.virtualenvs/ansibledev/local/lib/python2.7/site-packages/ansible/modules/network/ios/ios_config.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777 `" && echo ansible-tmp-1490014724.33-225021058435777="` echo /home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmpVJMylF TO /home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777/ios_config.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777/ /home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777/ios_config.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777/ios_config.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1490014724.33-225021058435777/" > /dev/null 2>&1 && sleep 0'
 [WARNING]: argument username has been deprecated and will be removed in a future version

 [WARNING]: argument host has been deprecated and will be removed in a future version

 [WARNING]: argument password has been deprecated and will be removed in a future version

changed: [ios] => {
    "banners": {},
    "changed": true,
    "commands": [
        "no banner motd"
    ],
    "invocation": {
        "module_args": {
            "after": null,
            "auth_pass": null,
            "authorize": null,
            "backup": false,
            "before": null,
            "commands": "no banner motd",
            "config": null,
            "defaults": false,
            "force": false,
            "host": "10.1.100.46",
            "lines": [
                "no banner motd"
            ],
            "match": "line",
            "multiline_delimiter": "@",
            "parents": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "provider": null,
            "replace": "line",
            "save": false,
            "src": null,
            "ssh_keyfile": null,
            "timeout": null,
            "username": "ntc"
        }
    },
    "updates": [
        "no banner motd"
    ]
}

TASK [Setup motd banner] *******************************************************************************************************************************************************************************************************************************************************
task path: /github/cookbook/banner2.yml:19
Using module file /home/ken/.virtualenvs/ansibledev/local/lib/python2.7/site-packages/ansible/modules/network/ios/ios_banner.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060 `" && echo ansible-tmp-1490014726.24-155032398259060="` echo /home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmp2Qh2tu TO /home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060/ios_banner.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060/ /home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060/ios_banner.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060/ios_banner.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1490014726.24-155032398259060/" > /dev/null 2>&1 && sleep 0'
fatal: [ios]: FAILED! => {
    "changed": false,
    "failed": true,
    "invocation": {
        "module_args": {
            "auth_pass": null,
            "authorize": null,
            "banner": "motd",
            "host": "10.1.100.46",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "provider": null,
            "ssh_keyfile": null,
            "state": "present",
            "text": "Mon Mar 20 08:58:45 EDT 2017",
            "timeout": null,
            "username": "ntc"
        }
    },
    "msg": "show banner motd\r\n              ^\r\n% Invalid input detected at '^' marker.\r\n\r\nny-sw01#",
    "rc": 1
}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
ios                        : ok=1    changed=1    unreachable=0    failed=1

(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible --version
ansible 2.4.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/etc/ntc/ansible-modules/']
  python version = 2.7.6 (default, Oct 26 2016, 20:32:47) [GCC 4.8.4]
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$
```
I've spotted an issue over the weekend affecting privileged accounts, tracked https://github.com/ansible/ansible/pull/22782.

Out of curiosity, if you set 'authorize: yes' to both tasks, can you run the playbook twice and let me know if they run ok?
no change, ios_config always works, ios_banner does not. In my use-case, it does not need to authorize. 
If you login manually to your IOS device and run 'show banner motd', what do you get?
For some reason it seems on my runs i'm in config mode, which is it fails for you, 'show banner motd' is run on the root shell.

Let me prep a patch.
good catch, didn't realize it was running a `show banner motd`

```
y-sw01#show banner motd
              ^
% Invalid input detected at '^' marker.

ny-sw01#show ver
ny-sw01#show version
Cisco IOS Software, C3560 Software (C3560-IPSERVICESK9-M), Version 12.2(55)SE11, RELEASE SOFTWARE (fc3)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2016 by Cisco Systems, Inc.
Compiled Wed 17-Aug-16 13:07 by prod_rel_team
Image text-base: 0x01000000, data-base: 0x02F00000

ROM: Bootstrap program is C3560 boot loader
BOOTLDR: C3560 Boot Loader (C3560-HBOOT-M) Version 12.2(44)SE5, RELEASE SOFTWARE (fc1)

ny-sw01 uptime is 3 weeks, 3 days, 15 hours, 34 minutes
System returned to ROM by power-on
System image file is "flash:c3560-ipservicesk9-mz.122-55.SE11.bin"


This product contains cryptographic features and is subject to United
States and local country laws governing import, export, transfer and
use. Delivery of Cisco cryptographic products does not imply
third-party authority to import, export, distribute or use encryption.
Importers, exporters, distributors and users are responsible for
compliance with U.S. and local country laws. By using this product you
agree to comply with applicable laws and regulations. If you are unable
to comply with U.S. and local laws, return this product immediately.

A summary of U.S. laws governing Cisco cryptographic products may be found at:
http://www.cisco.com/wwl/export/crypto/tool/stqrg.html

If you require further assistance please contact us by sending email to
export@cisco.com.

cisco WS-C3560-24TS (PowerPC405) processor (revision E0) with 131072K bytes of memory.
Processor board ID FDO1144X2S7
Last reset from power-on
2 Virtual Ethernet interfaces
24 FastEthernet interfaces
2 Gigabit Ethernet interfaces
The password-recovery mechanism is enabled.

512K bytes of flash-simulated non-volatile configuration memory.
Base ethernet MAC Address       : 00:1E:49:5E:2A:80
Motherboard assembly number     : 73-9897-06
Power supply part number        : 341-0097-02
Motherboard serial number       : FDO114406JX
Power supply serial number      : DCA114081JY
Model revision number           : E0
Motherboard revision number     : B0
Model number                    : WS-C3560-24TS-S
System serial number            : FDO1144X2S7
Top Assembly Part Number        : 800-26160-02
Top Assembly Revision Number    : E0
Version ID                      : V02
CLEI Code Number                : COMMG00ARB
Hardware Board Revision Number  : 0x01


Switch Ports Model              SW Version            SW Image
------ ----- -----              ----------            ----------
*    1 26    WS-C3560-24TS      12.2(55)SE11          C3560-IPSERVICESK9-M


Configuration register is 0xF

```
OH, so this must be the typical router/switch IOS subtle differences.

If you run 'show running-config' do you get the banner info there?
Yes
```
ny-sw01#show run | be banner
banner motd ^C
this
is a
multi-line
banner
^C
!
```
alright, let me prep a patch, I'll try to first gather via 'show banner', if failure then fallback to 'show run' and extract the banner.
@itdependsnetworks can you try the PR https://github.com/ansible/ansible/pull/22793 and test it ?

I simulated locally by putting false on if, so it always enters the else branch and works for my lab router, don't have a switch where 'show banner' doesn't work.
Double check my ansible --version, I checked out your branch, but perhaps I did something wrong. Did not work, and here is the error. 

```
(rcruz) ken@kcelenza-ubuntu:/github/cookbook$ ansible-playbook -i inventory banner2.yml -vvvv
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /home/ken/ansible/lib/ansible/plugins/callback/__init__.pyc

PLAYBOOK: banner2.yml **********************************************************************************************************************************************************************************************************************************************************
1 plays in banner2.yml

PLAY [ios] *********************************************************************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [ios_config test] *********************************************************************************************************************************************************************************************************************************************************
task path: /github/cookbook/banner2.yml:12
Using module file /home/ken/ansible/lib/ansible/modules/network/ios/ios_config.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475 `" && echo ansible-tmp-1490035904.72-231873661688475="` echo /home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmpbGMScC TO /home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475/ios_config.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475/ /home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475/ios_config.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475/ios_config.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1490035904.72-231873661688475/" > /dev/null 2>&1 && sleep 0'
 [WARNING]: argument username has been deprecated and will be removed in a future version

 [WARNING]: argument host has been deprecated and will be removed in a future version

 [WARNING]: argument password has been deprecated and will be removed in a future version

changed: [ios] => {
    "banners": {},
    "changed": true,
    "commands": [
        "no banner motd"
    ],
    "invocation": {
        "module_args": {
            "after": null,
            "auth_pass": null,
            "authorize": true,
            "backup": false,
            "before": null,
            "commands": "no banner motd",
            "config": null,
            "defaults": false,
            "force": false,
            "host": "10.1.100.46",
            "lines": [
                "no banner motd"
            ],
            "match": "line",
            "multiline_delimiter": "@",
            "parents": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "provider": null,
            "replace": "line",
            "save": false,
            "src": null,
            "ssh_keyfile": null,
            "timeout": null,
            "username": "ntc"
        }
    },
    "updates": [
        "no banner motd"
    ]
}

TASK [Setup motd banner] *******************************************************************************************************************************************************************************************************************************************************
task path: /github/cookbook/banner2.yml:20
Using module file /home/ken/ansible/lib/ansible/modules/network/ios/ios_banner.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991 `" && echo ansible-tmp-1490035907.01-125765664623991="` echo /home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmpliLQrv TO /home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991/ios_banner.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991/ /home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991/ios_banner.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991/ios_banner.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1490035907.01-125765664623991/" > /dev/null 2>&1 && sleep 0'
 [WARNING]: Removed unexpected internal key in module return: _ansible_parsed = False

The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_JzYCTX/ansible_module_ios_banner.py", line 171, in <module>
    main()
  File "/tmp/ansible_JzYCTX/ansible_module_ios_banner.py", line 157, in main
    have = map_config_to_obj(module)
  File "/tmp/ansible_JzYCTX/ansible_module_ios_banner.py", line 115, in map_config_to_obj
    output = out.split('^C')[1].strip()
IndexError: list index out of range

fatal: [ios]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_JzYCTX/ansible_module_ios_banner.py\", line 171, in <module>\n    main()\n  File \"/tmp/ansible_JzYCTX/ansible_module_ios_banner.py\", line 157, in main\n    have = map_config_to_obj(module)\n  File \"/tmp/ansible_JzYCTX/ansible_module_ios_banner.py\", line 115, in map_config_to_obj\n    output = out.split('^C')[1].strip()\nIndexError: list index out of range\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
ios                        : ok=1    changed=1    unreachable=0    failed=1

(rcruz) ken@kcelenza-ubuntu:/github/cookbook$ ansible --version
ansible 2.4.0 (fix_ios_banner_on_switches 9c34adeded) last updated 2017/03/20 14:48:43 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/etc/ntc/ansible-modules/']
  python version = 2.7.6 (default, Oct 26 2016, 20:32:47) [GCC 4.8.4]
(rcruz) ken@kcelenza-ubuntu:/github/cookbook$
```
Can you please run 'show running-config | begin banner motd' in a shell and paste the output?
You can find the output below. This concerns me a bit, but I may be missing something. The old method was doing a regex that correctly identified just the banner. Want to make sure this will not get confused if the banner delimiter changes. 

```
ny-sw01#show running-config | begin banner motd
banner motd ^C
this
is a
multi-line
banner
^C
!
line con 0
 password 7 <ommitted>
line vty 0 4
 exec-timeout 60 0
 privilege level 15
 transport input all
line vty 5 15
 exec-timeout 60 0
 privilege level 15
!
ntp source Loopback0
ntp server 10.26.3.203
ntp server 10.26.3.202
ntp server 10.26.3.201
ntp server 10.26.3.200 prefer
end
```

Not sure why the split call returns a None (that's what I assume it happens to you, there's no list to index).

I've pushed a new version of the patch using re python module, give it a go and let me know how it goes.
fwiw, i merged the pull request as it was working on my tests and wanted it to be ready for RC2 , which is due out today.
@rcarrillocruz sorry I missed last update. let me give another try 
Still unable to get it working. Here is the verbose output, playbook and version:

```
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible-playbook -i inventory banner2.yml -vvvv
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /home/ken/ansible/lib/ansible/plugins/callback/__init__.pyc

PLAYBOOK: banner2.yml **********************************************************************************************************************************************************************************************************************************************************
1 plays in banner2.yml

PLAY [ios] *********************************************************************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [ios_config test] *********************************************************************************************************************************************************************************************************************************************************
task path: /github/cookbook/banner2.yml:12
Using module file /home/ken/ansible/lib/ansible/modules/network/ios/ios_config.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810 `" && echo ansible-tmp-1490188274.63-84407785309810="` echo /home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmp_OklMM TO /home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810/ios_config.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810/ /home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810/ios_config.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810/ios_config.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1490188274.63-84407785309810/" > /dev/null 2>&1 && sleep 0'
 [WARNING]: argument username has been deprecated and will be removed in a future version

 [WARNING]: argument host has been deprecated and will be removed in a future version

 [WARNING]: argument password has been deprecated and will be removed in a future version

changed: [ios] => {
    "banners": {},
    "changed": true,
    "commands": [
        "no banner motd"
    ],
    "invocation": {
        "module_args": {
            "after": null,
            "auth_pass": null,
            "authorize": true,
            "backup": false,
            "before": null,
            "commands": "no banner motd",
            "config": null,
            "defaults": false,
            "force": false,
            "host": "10.1.100.46",
            "lines": [
                "no banner motd"
            ],
            "match": "line",
            "multiline_delimiter": "@",
            "parents": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "provider": null,
            "replace": "line",
            "save": false,
            "src": null,
            "ssh_keyfile": null,
            "timeout": null,
            "username": "ntc"
        }
    },
    "updates": [
        "no banner motd"
    ]
}

TASK [Setup motd banner] *******************************************************************************************************************************************************************************************************************************************************
task path: /github/cookbook/banner2.yml:20
Using module file /home/ken/ansible/lib/ansible/modules/network/ios/ios_banner.py
<10.1.100.46> ESTABLISH LOCAL CONNECTION FOR USER: ken
<10.1.100.46> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.1.100.46> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860 `" && echo ansible-tmp-1490188276.63-18576639304860="` echo /home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860 `" ) && sleep 0'
<10.1.100.46> PUT /tmp/tmporETQD TO /home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860/ios_banner.py
<10.1.100.46> EXEC /bin/sh -c 'chmod u+x /home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860/ /home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860/ios_banner.py && sleep 0'
<10.1.100.46> EXEC /bin/sh -c 'python /home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860/ios_banner.py; rm -rf "/home/ken/.ansible/tmp/ansible-tmp-1490188276.63-18576639304860/" > /dev/null 2>&1 && sleep 0'
 [WARNING]: Removed unexpected internal key in module return: _ansible_parsed = False

The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_7Nw2Ye/ansible_module_ios_banner.py", line 172, in <module>
    main()
  File "/tmp/ansible_7Nw2Ye/ansible_module_ios_banner.py", line 158, in main
    have = map_config_to_obj(module)
  File "/tmp/ansible_7Nw2Ye/ansible_module_ios_banner.py", line 116, in map_config_to_obj
    output = re.search('\^C(.*)\^C', out, re.S).group(1).strip()
AttributeError: 'NoneType' object has no attribute 'group'

fatal: [ios]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_7Nw2Ye/ansible_module_ios_banner.py\", line 172, in <module>\n    main()\n  File \"/tmp/ansible_7Nw2Ye/ansible_module_ios_banner.py\", line 158, in main\n    have = map_config_to_obj(module)\n  File \"/tmp/ansible_7Nw2Ye/ansible_module_ios_banner.py\", line 116, in map_config_to_obj\n    output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\nAttributeError: 'NoneType' object has no attribute 'group'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
ios                        : ok=1    changed=1    unreachable=0    failed=1

(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ cat banner2.yml
---

- hosts: ios
  connection: local
  gather_facts: no


  tasks:
    - name: ios_config test
      ios_config:
        commands: no banner motd
        host: "{{ ansible_host }}"
        username: "{{ user }}"
        password: "{{ password }}"
        authorize: yes

    - name: Setup motd banner
      ios_banner:
        banner:  motd
        text: "{{ lookup('pipe', 'date') }}"
        state: present
        host: "{{ ansible_host }}"
        username: "{{ user }}"
        password: "{{ password }}"
        authorize: yes

(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible --version
ansible 2.4.0 (fix_ios_banner_on_switches 4a6ec00774) last updated 2017/03/22 09:05:56 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/etc/ntc/ansible-modules/']
  python version = 2.7.6 (default, Oct 26 2016, 20:32:47) [GCC 4.8.4]
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$
```
@itdependsnetworks I created an instrumented ios_banner module to debug arguments and stuff:

https://github.com/rcarrillocruz/ansible/tree/troubleshoot_22216

Please check that branch, run the test playbook without ANSIBLE_LOG_PATH and provide /tmp/ansible.out from your controller machine.
Finally got time to do this. I assume you mean to set the ansible_log_path, if that is wrong, let me know. 

```
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible --version
ansible 2.4.0 (troubleshoot_22216 74f59f6985) last updated 2017/03/28 10:34:18 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/etc/ntc/ansible-modules/']
  python version = 2.7.6 (default, Oct 26 2016, 20:32:47) [GCC 4.8.4]
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$
```

```2017-03-28 10:38:23,441 p=5722 u=ken |  Using /etc/ansible/ansible.cfg as config file
2017-03-28 10:38:25,132 p=5722 u=ken |  Loading callback plugin default of type stdout, v2.0 from /home/ken/ansible/lib/ansible/plugins/callback/__init__.pyc
2017-03-28 10:38:25,147 p=5722 u=ken |  PLAYBOOK: banner2.yml **********************************************************************************************************************************************************************************************************************************************************
2017-03-28 10:38:25,148 p=5722 u=ken |  1 plays in banner2.yml
2017-03-28 10:38:25,151 p=5722 u=ken |  PLAY [ios] *********************************************************************************************************************************************************************************************************************************************************************
2017-03-28 10:38:25,170 p=5722 u=ken |  META: ran handlers
2017-03-28 10:38:25,173 p=5722 u=ken |  TASK [ios_config test] *********************************************************************************************************************************************************************************************************************************************************
2017-03-28 10:38:25,173 p=5722 u=ken |  task path: /github/cookbook/banner2.yml:14
2017-03-28 10:38:25,552 p=5734 u=ken |  starting new persistent socket with path /home/ken/.ansible/pc/4de37a45f7
2017-03-28 10:38:25,553 p=5734 u=ken |  using connection plugin network_cli
2017-03-28 10:38:25,638 paramiko.transport starting thread (client mode): 0xb660f28cL
2017-03-28 10:38:25,639 paramiko.transport Local version/idstring: SSH-2.0-paramiko_2.1.2
2017-03-28 10:38:25,649 paramiko.transport Remote version/idstring: SSH-1.99-Cisco-1.25
2017-03-28 10:38:25,649 paramiko.transport Connected (version 1.99, client Cisco-1.25)
2017-03-28 10:38:25,650 paramiko.transport kex algos:[u'diffie-hellman-group1-sha1'] server key:[u'ssh-rsa'] client encrypt:[u'aes128-cbc', u'3des-cbc', u'aes192-cbc', u'aes256-cbc'] server encrypt:[u'aes128-cbc', u'3des-cbc', u'aes192-cbc', u'aes256-cbc'] client mac:[u'hmac-sha1', u'hmac-sha1-96', u'hmac-md5', u'hmac-md5-96'] server mac:[u'hmac-sha1', u'hmac-sha1-96', u'hmac-md5', u'hmac-md5-96'] client compress:[u'none'] server compress:[u'none'] client lang:[u''] server lang:[u''] kex follows?False
2017-03-28 10:38:25,650 paramiko.transport Kex agreed: diffie-hellman-group1-sha1
2017-03-28 10:38:25,650 paramiko.transport Cipher agreed: aes128-cbc
2017-03-28 10:38:25,650 paramiko.transport MAC agreed: hmac-md5
2017-03-28 10:38:25,650 paramiko.transport Compression agreed: none
2017-03-28 10:38:26,129 paramiko.transport kex engine KexGroup1 specified hash_algo <built-in function openssl_sha1>
2017-03-28 10:38:26,130 paramiko.transport Switch to new keys ...
2017-03-28 10:38:26,445 paramiko.transport userauth is OK
2017-03-28 10:38:26,468 paramiko.transport Authentication (password) successful!
2017-03-28 10:38:26,474 p=5734 u=ken |  ssh connection done, setting terminal
2017-03-28 10:38:26,477 p=5734 u=ken |  ssh connection has completed successfully
2017-03-28 10:38:26,477 p=5734 u=ken |  connection established in 0:00:00.924101
2017-03-28 10:38:26,546 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:26,547 p=5734 u=ken |  socket operation is CONTEXT
2017-03-28 10:38:26,547 p=5734 u=ken |  updating play_context for connection
2017-03-28 10:38:26,547 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:26,547 p=5734 u=ken |  attempting to open shell to device
2017-03-28 10:38:26,548 paramiko.transport [chan 0] Max packet in: 32768 bytes
2017-03-28 10:38:26,558 paramiko.transport [chan 0] Max packet out: 4096 bytes
2017-03-28 10:38:26,558 paramiko.transport Secsh channel 0 opened.
2017-03-28 10:38:26,575 paramiko.transport [chan 0] Sesch channel 0 request ok
2017-03-28 10:38:26,584 paramiko.transport [chan 0] Sesch channel 0 request ok
2017-03-28 10:38:26,649 p=5734 u=ken |  shell successfully opened
2017-03-28 10:38:26,650 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:26,783 p=5722 u=ken |  Using module file /home/ken/ansible/lib/ansible/modules/network/ios/ios_config.py
2017-03-28 10:38:26,892 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:26,892 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:28,109 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:28,113 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:28,113 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:28,152 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:28,152 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:28,152 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:28,204 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:28,205 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:28,205 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:28,237 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:28,251 p=5722 u=ken |  changed: [ios] => {
    "banners": {},
    "changed": true,
    "commands": [
        "no banner motd"
    ],
    "invocation": {
        "module_args": {
            "after": null,
            "auth_pass": null,
            "authorize": true,
            "backup": false,
            "before": null,
            "commands": "no banner motd",
            "config": null,
            "defaults": false,
            "force": false,
            "host": null,
            "lines": [
                "no banner motd"
            ],
            "match": "line",
            "multiline_delimiter": "@",
            "parents": null,
            "password": null,
            "port": null,
            "provider": {
                "auth_pass": null,
                "authorize": true,
                "host": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "port": null,
                "ssh_keyfile": null,
                "timeout": null,
                "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
            },
            "replace": "line",
            "save": false,
            "src": null,
            "ssh_keyfile": null,
            "timeout": null,
            "username": null
        }
    },
    "updates": [
        "no banner motd"
    ]
}
2017-03-28 10:38:28,253 p=5722 u=ken |  TASK [Setup motd banner] *******************************************************************************************************************************************************************************************************************************************************
2017-03-28 10:38:28,254 p=5722 u=ken |  task path: /github/cookbook/banner2.yml:23
2017-03-28 10:38:28,637 p=5770 u=ken |  re-using existing socket connection
2017-03-28 10:38:28,638 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:28,638 p=5734 u=ken |  socket operation is CONTEXT
2017-03-28 10:38:28,638 p=5734 u=ken |  updating play_context for connection
2017-03-28 10:38:28,639 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:28,639 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:28,752 p=5722 u=ken |  Using module file /home/ken/ansible/lib/ansible/modules/network/ios/ios_banner.py
2017-03-28 10:38:28,867 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:28,867 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:29,409 p=5734 u=ken |  socket operation completed with rc 1
2017-03-28 10:38:29,409 p=5734 u=ken |  incoming request accepted on persistent socket
2017-03-28 10:38:29,409 p=5734 u=ken |  socket operation is EXEC
2017-03-28 10:38:30,721 p=5734 u=ken |  socket operation completed with rc 0
2017-03-28 10:38:30,734 p=5722 u=ken |  The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_uIarJz/ansible_module_ios_banner.py", line 183, in <module>
    main()
  File "/tmp/ansible_uIarJz/ansible_module_ios_banner.py", line 169, in main
    have = map_config_to_obj(module)
  File "/tmp/ansible_uIarJz/ansible_module_ios_banner.py", line 125, in map_config_to_obj
    output = re.search('\^C(.*)\^C', out, re.S).group(1).strip()
AttributeError: 'NoneType' object has no attribute 'group'

2017-03-28 10:38:30,736 p=5722 u=ken |  fatal: [ios]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_uIarJz/ansible_module_ios_banner.py\", line 183, in <module>\n    main()\n  File \"/tmp/ansible_uIarJz/ansible_module_ios_banner.py\", line 169, in main\n    have = map_config_to_obj(module)\n  File \"/tmp/ansible_uIarJz/ansible_module_ios_banner.py\", line 125, in map_config_to_obj\n    output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\nAttributeError: 'NoneType' object has no attribute 'group'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}
2017-03-28 10:38:30,739 p=5722 u=ken |  PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
2017-03-28 10:38:30,740 p=5722 u=ken |  ios                        : ok=1    changed=1    unreachable=0    failed=1```
Hi @itdependsnetworks 

The instrumented code dumps variables and stuff onto /tmp/ansible.out, I need you run the playbook without ANSIBLE_LOG_PATH set (as the code will already log stuff on /tmp/ansible.out, to avoid overwriting by ansible -vvvv) and provide /tmp/ansible.out .


```
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ ansible-playbook -i inventory banner2.yml

PLAY [ios] *********************************************************************************************************************************************************************************************************************************************************************

TASK [ios_config test] *********************************************************************************************************************************************************************************************************************************************************
changed: [ios]

TASK [Setup motd banner] *******************************************************************************************************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'NoneType' object has no attribute 'group'
fatal: [ios]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_LWoNZm/ansible_module_ios_banner.py\", line 183, in <module>\n    main()\n  File \"/tmp/ansible_LWoNZm/ansible_module_ios_banner.py\", line 169, in main\n    have = map_config_to_obj(module)\n  File \"/tmp/ansible_LWoNZm/ansible_module_ios_banner.py\", line 125, in map_config_to_obj\n    output = re.search('\\^C(.*)\\^C', out, re.S).group(1).strip()\nAttributeError: 'NoneType' object has no attribute 'group'\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
ios                        : ok=1    changed=1    unreachable=0    failed=1

(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$ cat /tmp/ansible.out
DEBUG:root:TROUBLESHOOT> cmd: 'show banner motd'
DEBUG:root:TROUBLESHOOT> rc: 1
DEBUG:root:TROUBLESHOOT> out: ''
DEBUG:root:TROUBLESHOOT> err: "show banner motd\r\n              ^\r\n% Invalid input detected at '^' marker.\r\n\r\nny-sw01#"
DEBUG:root:TROUBLESHOOT> cmd: 'show running-config | begin banner motd'
DEBUG:root:TROUBLESHOOT> rc: 0
DEBUG:root:TROUBLESHOOT> out: ''
DEBUG:root:TROUBLESHOOT> err: ''
(ansibledev) ken@kcelenza-ubuntu:/github/cookbook$
```

Resolving patch:
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 @@ def map_config_to_obj(module):
         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


Test patch: