Repository: ansible/ansible-modules-core

Issue:
docker_image path param doesn't support home directory
##### Issue Type:

<!-- Please pick one and delete the rest: -->
- Bug Report
##### Plugin Name:

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

docker_image
##### Ansible Version:

```
ansible 2.0.1.0
  config file = /Users/mylokin/.ansible.cfg
  configured module search path = Default w/o overrides
```
##### Ansible Configuration:

```
[defaults]
host_key_checking = false
inventory = inventory/hosts

[ssh_connection]
ssh_args = -F inventory/sshconfig
```
##### Environment:

<!-- Please mention the OS you are running Ansible from, and the OS you are managing,
or say “N/A” for anything that isn't platform-specific. -->

OSX: 10.11.3
Ansible Host: 2.0.1.0
Python: 2.7.11
Ansible Remote Client: Ubuntu 14.04 Linux
##### Summary:

<!-- Please explain the problem briefly.  -->

`path` param of docker_image module doesn't respect `become_user`. 
~/ expands into home directory of ssh user, not become user.
##### Steps To Reproduce:

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

```
ansible -vvvv docker1 -b --become-user=guide -m docker_image -a "path=~/guide name=guide state=build"
```

<!-- You can also paste gist.github.com links for larger files.  -->
##### Expected Results:

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

`path` param should be expanded regarding `become_user`. 
##### Actual Results:

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

There are two users on client host: vagrant and guide. 
/home/vagrant/guide/Dockerfile doesn't exist
/home/guide/guide/Dockerfile exists

```
ansible -vvvv docker1 -b --become-user=guide -m docker_image -a "path=~/guide name=guide state=build"
Using /Users/mylokin/Documents/Development/mention2/cluster/ansible.cfg as config file
Loaded callback minimal of type stdout, v2.0
<docker1> ESTABLISH SSH CONNECTION FOR USER: None
<docker1> SSH: EXEC ssh -C -vvv -F inventory/sshconfig -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -tt docker1 '/bin/sh -c '"'"'( umask 22 && mkdir -p "` echo /tmp/ansible-tmp-1456950999.38-161188090611547 `" && echo "` echo /tmp/ansible-tmp-1456950999.38-161188090611547 `" )'"'"''
<docker1> PUT /var/folders/8b/p1k2kj3d0svdn1fyhqtvkfcc0000gn/T/tmpMzow9v TO /tmp/ansible-tmp-1456950999.38-161188090611547/docker_image
<docker1> SSH: EXEC sftp -b - -C -vvv -F inventory/sshconfig -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 '[docker1]'
<docker1> ESTABLISH SSH CONNECTION FOR USER: None
<docker1> SSH: EXEC ssh -C -vvv -F inventory/sshconfig -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -tt docker1 '/bin/sh -c '"'"'chmod a+r /tmp/ansible-tmp-1456950999.38-161188090611547/docker_image'"'"''
<docker1> ESTABLISH SSH CONNECTION FOR USER: None
<docker1> SSH: EXEC ssh -C -vvv -F inventory/sshconfig -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -tt docker1 '/bin/sh -c '"'"'sudo -H -S -n -u guide /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-xwkyjkxpfkphuzogzouozejsxnrtjnrf; /bin/sh -c '"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /tmp/ansible-tmp-1456950999.38-161188090611547/docker_image'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"''"'"'"'"'"'"'"'"''"'"''
<docker1> ESTABLISH SSH CONNECTION FOR USER: None
<docker1> SSH: EXEC ssh -C -vvv -F inventory/sshconfig -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -tt docker1 '/bin/sh -c '"'"'rm -f -r /tmp/ansible-tmp-1456950999.38-161188090611547/ > /dev/null 2>&1'"'"''
docker1 | FAILED! => {
    "changed": false,
    "failed": true,
    "invocation": {
        "module_name": "docker_image"
    },
    "module_stderr": "OpenSSH_6.9p1, LibreSSL 2.1.8\r\ndebug1: Reading configuration data inventory/sshconfig\r\ndebug1: inventory/sshconfig line 1: Applying options for docker1\r\ndebug2: ssh_connect: needpriv 0\r\ndebug1: Connecting to 10.10.10.16 [10.10.10.16] port 22.\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: fd 3 clearing O_NONBLOCK\r\ndebug1: Connection established.\r\ndebug3: timeout: 10000 ms remain after connect\r\ndebug1: key_load_public: No such file or directory\r\ndebug1: identity file /Users/mylokin/Documents/Development/mention2/.vagrant/machines/docker1/parallels/private_key type -1\r\ndebug1: key_load_public: No such file or directory\r\ndebug1: identity file /Users/mylokin/Documents/Development/mention2/.vagrant/machines/docker1/parallels/private_key-cert type -1\r\ndebug1: Enabling compatibility mode for protocol 2.0\r\ndebug1: Local version string SSH-2.0-OpenSSH_6.9\r\ndebug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3\r\ndebug1: match: OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3 pat OpenSSH_6.6.1* compat 0x04000000\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: Authenticating to 10.10.10.16:22 as 'vagrant'\r\ndebug3: hostkeys_foreach: reading file \"/dev/null\"\r\ndebug1: SSH2_MSG_KEXINIT sent\r\ndebug1: SSH2_MSG_KEXINIT received\r\ndebug2: kex_parse_kexinit: curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1\r\ndebug2: kex_parse_kexinit: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa,ssh-dss\r\ndebug2: kex_parse_kexinit: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se\r\ndebug2: kex_parse_kexinit: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se\r\ndebug2: kex_parse_kexinit: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-md5-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-md5-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: zlib@openssh.com,zlib,none\r\ndebug2: kex_parse_kexinit: zlib@openssh.com,zlib,none\r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: first_kex_follows 0 \r\ndebug2: kex_parse_kexinit: reserved 0 \r\ndebug2: kex_parse_kexinit: curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1\r\ndebug2: kex_parse_kexinit: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ssh-ed25519\r\ndebug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se\r\ndebug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se\r\ndebug2: kex_parse_kexinit: hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com\r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: first_kex_follows 0 \r\ndebug2: kex_parse_kexinit: reserved 0 \r\ndebug1: kex: server->client chacha20-poly1305@openssh.com <implicit> zlib@openssh.com\r\ndebug1: kex: client->server chacha20-poly1305@openssh.com <implicit> zlib@openssh.com\r\ndebug1: expecting SSH2_MSG_KEX_ECDH_REPLY\r\ndebug1: Server host key: ecdsa-sha2-nistp256 SHA256:6ID53wsa4UtIqYMbBdc4rGw+t/LP2cIzK+ArxWfcP+w\r\ndebug3: hostkeys_foreach: reading file \"/dev/null\"\r\nWarning: Permanently added '10.10.10.16' (ECDSA) to the list of known hosts.\r\ndebug2: set_newkeys: mode 1\r\ndebug1: SSH2_MSG_NEWKEYS sent\r\ndebug1: expecting SSH2_MSG_NEWKEYS\r\ndebug2: set_newkeys: mode 0\r\ndebug1: SSH2_MSG_NEWKEYS received\r\ndebug1: Roaming not allowed by server\r\ndebug1: SSH2_MSG_SERVICE_REQUEST sent\r\ndebug2: service_accept: ssh-userauth\r\ndebug1: SSH2_MSG_SERVICE_ACCEPT received\r\ndebug2: key: /Users/mylokin/Documents/Development/mention2/.vagrant/machines/docker1/parallels/private_key (0x0), explicit\r\ndebug1: Authentications that can continue: publickey,password\r\ndebug3: start over, passed a different list publickey,password\r\ndebug3: preferred gssapi-with-mic,gssapi-keyex,hostbased,publickey\r\ndebug3: authmethod_lookup publickey\r\ndebug3: remaining preferred: ,gssapi-keyex,hostbased,publickey\r\ndebug3: authmethod_is_enabled publickey\r\ndebug1: Next authentication method: publickey\r\ndebug1: Trying private key: /Users/mylokin/Documents/Development/mention2/.vagrant/machines/docker1/parallels/private_key\r\ndebug3: sign_and_send_pubkey: RSA SHA256:Xc9GSKkgvTx6rPjpl6Hk2xHpxc7L3AzsgVQ7Enc81Lg\r\ndebug2: we sent a publickey packet, wait for reply\r\ndebug1: Enabling compression at level 6.\r\ndebug1: Authentication succeeded (publickey).\r\nAuthenticated to 10.10.10.16 ([10.10.10.16]:22).\r\ndebug2: fd 6 setting O_NONBLOCK\r\ndebug2: fd 7 setting O_NONBLOCK\r\ndebug1: channel 0: new [client-session]\r\ndebug3: ssh_session2_open: channel_new: 0\r\ndebug2: channel 0: send open\r\ndebug1: Requesting no-more-sessions@openssh.com\r\ndebug1: Entering interactive session.\r\ndebug2: callback start\r\ndebug2: fd 3 setting TCP_NODELAY\r\ndebug3: ssh_packet_set_tos: set IP_TOS 0x10\r\ndebug2: client_session2_setup: id 0\r\ndebug2: channel 0: request pty-req confirm 1\r\ndebug1: Sending command: /bin/sh -c 'sudo -H -S -n -u guide /bin/sh -c '\"'\"'echo BECOME-SUCCESS-xwkyjkxpfkphuzogzouozejsxnrtjnrf; /bin/sh -c '\"'\"'\"'\"'\"'\"'\"'\"'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /tmp/ansible-tmp-1456950999.38-161188090611547/docker_image'\"'\"'\"'\"'\"'\"'\"'\"''\"'\"''\r\ndebug2: channel 0: request exec confirm 1\r\ndebug2: callback done\r\ndebug2: channel 0: open confirm rwindow 0 rmax 32768\r\ndebug2: channel_input_status_confirm: type 99 id 0\r\ndebug2: PTY allocation request accepted on channel 0\r\ndebug2: channel 0: rcvd adjust 2097152\r\ndebug2: channel_input_status_confirm: type 99 id 0\r\ndebug2: exec request accepted on channel 0\r\ndebug2: channel 0: rcvd eof\r\ndebug2: channel 0: output open -> drain\r\ndebug2: channel 0: obuf empty\r\ndebug2: channel 0: close_write\r\ndebug2: channel 0: output drain -> closed\r\ndebug1: client_input_channel_req: channel 0 rtype exit-status reply 0\r\ndebug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0\r\ndebug2: channel 0: rcvd eow\r\ndebug2: channel 0: close_read\r\ndebug2: channel 0: input open -> closed\r\ndebug2: channel 0: rcvd close\r\ndebug3: channel 0: will not send data after close\r\ndebug2: channel 0: almost dead\r\ndebug2: channel 0: gc: notify user\r\ndebug2: channel 0: gc: user detached\r\ndebug2: channel 0: send close\r\ndebug2: channel 0: is dead\r\ndebug2: channel 0: garbage collecting\r\ndebug1: channel 0: free: client-session, nchannels 1\r\ndebug3: channel 0: status: The following connections are open:\r\n  #0 client-session (t4 r0 i3/0 o3/0 fd -1/-1 cc -1)\r\n\r\ndebug1: fd 1 clearing O_NONBLOCK\r\ndebug1: fd 2 clearing O_NONBLOCK\r\nConnection to 10.10.10.16 closed.\r\nTransferred: sent 3276, received 3156 bytes, in 0.1 seconds\r\nBytes per second: sent 21998.4, received 21192.6\r\ndebug1: Exit status 1\r\ndebug1: compress outgoing: raw data 702, compressed 464, factor 0.66\r\ndebug1: compress incoming: raw data 464, compressed 702, factor 1.51\r\n",
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/tmp/ansible-tmp-1456950999.38-161188090611547/docker_image\", line 2416, in <module>\r\n    main()\r\n  File \"/tmp/ansible-tmp-1456950999.38-161188090611547/docker_image\", line 401, in main\r\n    image_id = manager.build()\r\n  File \"/tmp/ansible-tmp-1456950999.38-161188090611547/docker_image\", line 293, in build\r\n    stream = self.client.build(self.path, dockerfile=self.dockerfile, tag=':'.join([self.name, self.tag]), nocache=self.nocache, rm=True, stream=True)\r\n  File \"/usr/local/lib/python2.7/dist-packages/docker/api/build.py\", line 42, in build\r\n    raise TypeError(\"You must specify a directory to build in path\")\r\nTypeError: You must specify a directory to build in path\r\n",
    "msg": "MODULE FAILURE",
    "parsed": false
}
```



Discussion:

Resolving patch:
diff --git a/cloud/docker/docker_image.py b/cloud/docker/docker_image.py
--- a/cloud/docker/docker_image.py
+++ b/cloud/docker/docker_image.py
@@ -353,7 +353,7 @@ def remove_images(self):
 def main():
     module = AnsibleModule(
         argument_spec = dict(
-            path               = dict(required=False, default=None),
+            path               = dict(required=False, default=None, type='path'),
             dockerfile         = dict(required=False, default="Dockerfile"),
             name               = dict(required=True),
             tag                = dict(required=False, default="latest"),


Test patch: