Repository: ansible/ansible-modules-extras

Issue:
Ansible Reports Twilio Failure Yet SMS Sent Successfullly
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### COMPONENT NAME

<!--- Name of the plugin/module/task -->

Twilio
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
ansible 2.1.1.0
  config file = /home/douglas/repos/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

```
Pipelining and threads but nothing else

```
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

```
Linux Mint

```
##### SUMMARY

<!--- Explain the problem briefly -->

```

TASK [accounts : send sms challenge] *******************************************
fatal: [pascal -> localhost]: FAILED! => {"changed": false, "failed": true, "msg": "unable to send message to +15163205079"}
...ignoring

Yet Twilio console shows SMS delivered while recipient confirms SMS 

```
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->

```
ansible-playbook accounts.yml "-e hosts=server -e csms=[] -e number=+blah -e user=blah" -t csms --sudo -K --ask-vault-pass

cat accounts.yml 

---
- hosts: "{{ hosts }}"
  roles: 
    - accounts
  gather_facts: True


cat roles/accounts/tasks/main.yml 

- include: create_user.yml
  when: create is defined

- include: remove_user.yml
  when: remove is defined

- include: xfs.yml
  when: ansible_hostname == "blah" or "blah"

- include: lab_email.yml
  when: lab is defined

- include: challenge.yml
  when: csms is defined

cat roles/accounts/tasks/challenge.yml 

- name: send sms challenge
  tags: csms 
  twilio:
   msg: "{{ challenge }}"
   account_sid: "SID"
   auth_token: "TOKEN"
   from_number: "+BLAH"
   to_number: "{{ number }}"
  delegate_to: localhost    
  ignore_errors: True

```

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->

SMS works without reported error
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with high verbosity (-vvvv) -->

SMS works but module reports error 

<!--- Paste verbatim command output between quotes below -->

```

 ansible-playbook accounts.yml "-e hosts=host -e csms=[] -e number=+blah -e user=blah" -t csms --sudo -K --ask-vault-pass -vvv
Using /home/user/repos/ansible/ansible.cfg as config file
SUDO password: 
Vault password: 

PLAYBOOK: accounts.yml *********************************************************
1 plays in accounts.yml

PLAY [pascal] ******************************************************************

TASK [setup] *******************************************************************
<pascal> ESTABLISH SSH CONNECTION FOR USER: None
<pascal> SSH: EXEC ssh -C -q -o ControlMaster=auto -o ControlPersist=60s -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=20 -o ControlPath=/home/user/.ansible/cp/ansible-ssh-%h-%p-%r host '/bin/sh -c '"'"'sudo -H -S  -p "[sudo via ansible, key=dovdppgsmmkpysizwmmmanqpnsnbhkbn] password: " -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-dovdppgsmmkpysizwmmmanqpnsnbhkbn; LANG=C LC_ALL=C LC_MESSAGES=C /usr/bin/python'"'"'"'"'"'"'"'"' && sleep 0'"'"''
ok: [pascal]

TASK [accounts : send sms challenge] *******************************************
task path: /home/user/repos/ansible/playbooks/roles/accounts/tasks/challenge.yml:11
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: user
<localhost> EXEC /bin/sh -c 'sudo -H -S  -p "[sudo via ansible, key=pgyfxtpxffqiposwtecseosepacqessa] password: " -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-pgyfxtpxffqiposwtecseosepacqessa; LANG=C LC_ALL=C LC_MESSAGES=C /usr/bin/python'"'"' && sleep 0'
fatal: [user -> localhost]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_args": {"account_sid": "blah", "auth_token": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", "from_number": "+blah", "media_url": null, "msg": "challenge", "to_number": "+blahblah", "url_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", "url_username": "blah"}, "module_name": "twilio"}, "msg": "unable to send message to +blah"}
...ignoring

PLAY RECAP *********************************************************************
host                     : ok=2    changed=0    unreachable=0    failed=0   

```



Discussion:
<!-- @JusticeForMikeBrown: Thanks for filing this bug report! -->

@makaimc ping, this issue is waiting for your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

I am able to reproduce this - looks like it was introduced in 1.9.6 after 1.9.4 (works in 1.9.4). With [this commit](https://github.com/ansible/ansible-modules-extras/commit/4ef6f4ea4248d2b16771cfcf72cab0cb4009fbd9). Doesn't look like the module was tested when the change was made because it's clear the ['status'] == 200 on line 164 will never be true. What's next step here?

I'm not familiar with this `fetch_url` function that broke the module, do I need to submit a fix for this? If I am specified as a maintainer on the module it would be good to get a heads up when changes are made and merged but not tested :/

IMHO the problem is, the module looks for 200 response code but it should (also) look for 201. Could you change https://github.com/ansible/ansible-modules-extras/blob/devel/notification/twilio.py#L164 to 

``` python
if info['status'] not in [200, 201]:
```

and test it again?

sure, i got my test environment set up again. will make some modifications and submit a PR tonight or tmrw AM


Resolving patch:
diff --git a/notification/twilio.py b/notification/twilio.py
--- a/notification/twilio.py
+++ b/notification/twilio.py
@@ -161,8 +161,12 @@ def main():
     for number in to_number:
         r, info = post_twilio_api(module, account_sid, auth_token, msg,
                 from_number, number, media_url)
-        if info['status'] != 200:
-            module.fail_json(msg="unable to send message to %s" % number)
+        if info['status'] not in [200, 201]:
+            body_message = "unknown error"
+            if 'body' in info:
+                body = json.loads(info['body'])
+                body_message = body['message']
+            module.fail_json(msg="unable to send message to %s: %s" % (number, body_message))
 
     module.exit_json(msg=msg, changed=False)
 


Test patch: