Repository: ansible/ansible

Issue:
Pushover Hostname api.pushover.net:443 doesn't match
<!--- Verify first that your issue/request is not already reported in GitHub -->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report with X-Ref: ansible/ansible-modules-extras#3677
Closed on extras repo due to repo merge
##### COMPONENT NAME
<!--- Name of the plugin/module/task -->
[Pushover](http://docs.ansible.com/ansible/pushover_module.html)

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.0.0
  config file = /Users/kkirsche/git/yaml/mac_setup/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).
-->
```
[defaults]
inventory: ./production
remote_user: kkirsche
remote_port: 22
forks: 20
pipelining: true
callback_whitelist: json
#stdout_callback: json
```

##### 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.
-->
macOS 10.12.1 -> macOS 10.12.1 (localhost) — N/A

##### SUMMARY
<!--- Explain the problem briefly -->
Running the pushover module results in the error:
```
hostname 'api.pushover.net:443' doesn't match either of '*.pushover.net', 'pushover.net'\", \"failed\": true, \"invocation
```

##### 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 -->
**tasks/main.yml**
```
---
# tasks file for ssh_config

- name: Notify that SSH Configuration is being changed
  pushover:
    msg: Mac SSH Configuration is being updated
    app_token: "{{ pushoverAppToken }}"
    user_key: "{{ pushoverUserKey }}"

- name: Create ~/.ssh if it doesn't exist
  file:
    path: "{{ ansible_env.HOME }}/.ssh"
    state: directory
    mode: "{{ ssh_directory_mode }}"

- name: Create ssh configuration file
  template:
    dest: "{{ ansible_env.HOME }}/.ssh/config"
    src: config.j2
    mode: "{{ ssh_config_mode }}"
```

**templates/config.j2**
```
{% for host in ssh_config_hosts %}
Host {{ ssh_config_hosts[host].host }}
{% if ssh_config_hosts[host].hostname is defined %}
Hostname {{ ssh_config_hosts[host].hostname }}
{% endif %}
{% if ssh_config_hosts[host].user is defined %}
User {{ ssh_config_hosts[host].user }}
{% endif %}
{% if ssh_config_hosts[host].port is defined %}
Port {{ ssh_config_hosts[host].port }}
{% endif %}
{% if ssh_config_hosts[host].proxy_command is defined %}
ProxyCommand {{ ssh_config_hosts[host].proxy_command }}
{% endif %}
{% if ssh_config_hosts[host].identity_file is defined %}
IdentityFile {{ ssh_config_hosts[host].identity_file }}
{% endif %}
{% if ssh_config_hosts[host].local_forward is defined %}
LocalForward {{ ssh_config_hosts[host].local_forward }}
{% endif %}

{% endfor %}
```

**defaults/main.yml**
```
---
# defaults file for ssh_config
ssh_directory_mode: 0700
ssh_config_mode: 0600

ssh_remote_user: kkirsche

ssh_config_hosts:
  googledns:
    host: gdns
    hostname: 8.8.8.8
    user: "{{ ssh_remote_user }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
For it to send a pushover notification prior to running the configuration changes

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with high verbosity (-vvvv) -->
The pushover notification failed with `hostname 'api.pushover.net:443' doesn't match either of '*.pushover.net', 'pushover.net'\", \"failed\": true, \"invocation`

<!--- Paste verbatim command output between quotes below -->
```
___________________________________________________________
/ TASK [ssh_config : Notify that SSH Configuration is being \
\ changed]                                                  /
-----------------------------------------------------------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/\
               ||----w |
               ||     ||

task path: /Users/kkirsche/git/yaml/mac_setup/roles/ssh_config/tasks/main.yml:4
Using module file /usr/local/Cellar/ansible/2.2.0.0_1/libexec/lib/python2.7/site-packages/ansible/modules/extras/notification/pushover.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: kkirsche
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340 `" && echo ansible-tmp-1481047350.24-71608570119340="` echo $HOME/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340 `" ) && sleep 0'
<127.0.0.1> PUT /var/folders/8y/pj9zz4b12r37490xnlqb7gb13tt57z/T/tmpO7biWl TO /Users/kkirsche/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340/pushover.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /Users/kkirsche/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340/ /Users/kkirsche/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340/pushover.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python /Users/kkirsche/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340/pushover.py; rm -rf "/Users/kkirsche/.ansible/tmp/ansible-tmp-1481047350.24-71608570119340/" > /dev/null 2>&1 && sleep 0'
fatal: [127.0.0.1]: FAILED! => {
   "changed": false,
   "failed": true,
   "invocation": {
       "module_name": "pushover"
   },
   "module_stderr": "",
   "module_stdout": "\n{\"msg\": \"hostname 'api.pushover.net:443' doesn't match either of '*.pushover.net', 'pushover.net'\", \"failed\": true, \"invocation\": {\"module_args\": {\"msg\": \"Mac SSH Configuration is being updated\", \"user_key\": \"VALUE_SPECIFIED_IN_NO_LOG_PARAMETER\", \"app_token\": \"VALUE_SPECIFIED_IN_NO_LOG_PARAMETER\", \"pri\": \"0\"}}}\n\n{\"msg\": \"Unable to send msg via pushover\", \"failed\": true, \"invocation\": {\"module_args\": {\"msg\": \"Mac SSH Configuration is being updated\", \"user_key\": \"VALUE_SPECIFIED_IN_NO_LOG_PARAMETER\", \"app_token\": \"VALUE_SPECIFIED_IN_NO_LOG_PARAMETER\", \"pri\": \"0\"}}}\n",
   "msg": "MODULE FAILURE"
}
...ignoring
```



Discussion:
This seems to be the cause of 2 things:

1. Your python version not having either:
    * `from ssl import match_hostname, CertificateError`
    * `from backports.ssl_match_hostname import match_hostname, CertificateError`
1. The pushover module explicitly specifying a port of `443` in it's URLs (Which it probably shouldn't be)
1. The fallback `_dnsname_match` and `match_hostname` not accounting for an explicitly supplied port number.
```
Python 2.7.12 (default, Oct 11 2016, 05:24:00)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from ssl import match_hostname, CertificateError
>>> from backports.ssl_match_hostname import match_hostname, CertificateError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named backports.ssl_match_hostname
```

If part 2 is true, what is backports and should this be listed as a package dependency on http://docs.ansible.com/ansible/pushover_module.html
I think the correct solution is removing the explicitly defined port.
I wouldn't mind doing that, but no clue with the team's directions how to run the modified module for their pull request template 😞 
Figured it out! Submitting a pull request. For me, as a Homebrew user, it meant editing `/usr/local/Cellar/ansible/2.2.0.0_1/libexec/lib/python2.7/site-packages/ansible/modules/extras/notification/pushover.py`

Resolving patch:
diff --git a/lib/ansible/modules/notification/pushover.py b/lib/ansible/modules/notification/pushover.py
--- a/lib/ansible/modules/notification/pushover.py
+++ b/lib/ansible/modules/notification/pushover.py
@@ -70,7 +70,6 @@
 class Pushover(object):
     ''' Instantiates a pushover object, use it to send notifications '''
     base_uri = 'https://api.pushover.net'
-    port = 443
 
     def __init__(self, module, user, token):
         self.module = module
@@ -80,7 +79,7 @@ def __init__(self, module, user, token):
     def run(self, priority, msg):
         ''' Do, whatever it is, we do. '''
 
-        url = '%s:%s/1/messages.json' % (self.base_uri, self.port)
+        url = '%s/1/messages.json' % (self.base_uri)
 
         # parse config
         options = dict(user=self.user,


Test patch: