{"action":"created","issue":{"url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3575","repository_url":"https://api.github.com/repos/ansible/ansible-modules-core","labels_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3575/labels{/name}","comments_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3575/comments","events_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3575/events","html_url":"https://github.com/ansible/ansible-modules-core/pull/3575","id":152062874,"number":3575,"title":"unarchive: use Python's tarfile module for tar listing","user":{"login":"hsoft","id":505201,"avatar_url":"https://avatars.githubusercontent.com/u/505201?v=3","gravatar_id":"","url":"https://api.github.com/users/hsoft","html_url":"https://github.com/hsoft","followers_url":"https://api.github.com/users/hsoft/followers","following_url":"https://api.github.com/users/hsoft/following{/other_user}","gists_url":"https://api.github.com/users/hsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/hsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsoft/subscriptions","organizations_url":"https://api.github.com/users/hsoft/orgs","repos_url":"https://api.github.com/users/hsoft/repos","events_url":"https://api.github.com/users/hsoft/events{/privacy}","received_events_url":"https://api.github.com/users/hsoft/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ansible/ansible-modules-core/labels/bugfix_pull_request","name":"bugfix_pull_request","color":"ded270"},{"url":"https://api.github.com/repos/ansible/ansible-modules-core/labels/community_review","name":"community_review","color":"fad8c7"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-05-01T01:30:56Z","updated_at":"2016-05-01T05:02:05Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3575","html_url":"https://github.com/ansible/ansible-modules-core/pull/3575","diff_url":"https://github.com/ansible/ansible-modules-core/pull/3575.diff","patch_url":"https://github.com/ansible/ansible-modules-core/pull/3575.patch"},"body":"##### ISSUE TYPE\r\n - Bugfix Pull Request\r\n\r\n##### COMPONENT NAME\r\nunarchive\r\n\r\n##### ANSIBLE VERSION\r\n```\r\nansible-playbook 2.2.0 (devel 1d6608e84f) last updated 2016/04/29 16:43:56 (GMT -400)\r\n  lib/ansible/modules/core: (fix-unarchive-encoding 40ee859114) last updated 2016/04/30 21:23:35 (GMT -400)\r\n  lib/ansible/modules/extras: (detached HEAD ca310f3d15) last updated 2016/04/29 16:53:29 (GMT -400)\r\n  config file =\r\n  configured module search path = Default w/o overrides\r\n```\r\n\r\n##### SUMMARY\r\nfixes https://github.com/ansible/ansible/issues/11348\r\n\r\nDepending on the current active locale, `tar`'s file listing can end up\r\nspitting backslash-escaped characters. Unfortunately, when that happens,\r\nwe end up with double-escaped backslashes, giving us a wrong path,\r\nmaking our action fail.\r\n\r\nWe could try un-double-escaping our paths, but that would be complicated\r\nand, I think, error-prone. The easiest way forward seemed to simply use\r\nthe `tarfile` module.\r\n\r\nWhy use it only for listing? Because the `unarchive` option also\r\nsupports the `extra_opts` option, and that supporting this would require\r\nus to mimick `tar`'s interface.\r\n\r\nFor listing files, however, I don't think that the loss of `extra_opts`\r\nsupport causes problems (well, I hope so).\r\n\r\nBefore the fix:\r\n\r\n```\r\n$ cat foo.yml\r\n- hosts: localhost\r\n  tasks:\r\n    - unarchive: src=foo.tar copy=no dest=/tmp\r\n\r\n$ cd /tmp\r\n$ mkdir foo\r\n$ touch foo/é.txt\r\n$ tar -cf foo.tar foo\r\n$ LANG=C ansible-playbook -c local foo.yml\r\n[WARNING]: Host file not found: /etc/ansible/hosts\r\n\r\n [WARNING]: provided hosts list is empty, only localhost is available\r\n\r\n\r\nPLAY [localhost] ***************************************************************\r\n\r\nTASK [setup] *******************************************************************\r\nok: [localhost]\r\n\r\nTASK [unarchive] ***************************************************************\r\nfatal: [localhost]: FAILED! => {\"changed\": false, \"failed\": true, \"msg\": \"Unexpected error when accessing exploded file: [Errno 2] No such file or directory: '/tmp/foo/\\\\\\\\303\\\\\\\\251.txt'\"}\r\n\r\nNO MORE HOSTS LEFT *************************************************************\r\n        to retry, use: --limit @foo.retry\r\n\r\nPLAY RECAP *********************************************************************\r\nlocalhost                  : ok=1    changed=0    unreachable=0    failed=1\r\n```\r\n\r\nAfter the fix:\r\n\r\n```\r\n$ LANG=C ansible-playbook -c local foo.yml\r\n [WARNING]: Host file not found: /etc/ansible/hosts\r\n\r\n [WARNING]: provided hosts list is empty, only localhost is available\r\n\r\n\r\nPLAY [localhost] ***************************************************************\r\n\r\nTASK [unarchive] ***************************************************************\r\nok: [localhost]\r\n\r\nPLAY RECAP *********************************************************************\r\nlocalhost                  : ok=1    changed=0    unreachable=0    failed=0\r\n```"},"comment":{"url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/comments/216016669","html_url":"https://github.com/ansible/ansible-modules-core/pull/3575#issuecomment-216016669","issue_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3575","id":216016669,"user":{"login":"abadger","id":209242,"avatar_url":"https://avatars.githubusercontent.com/u/209242?v=3","gravatar_id":"","url":"https://api.github.com/users/abadger","html_url":"https://github.com/abadger","followers_url":"https://api.github.com/users/abadger/followers","following_url":"https://api.github.com/users/abadger/following{/other_user}","gists_url":"https://api.github.com/users/abadger/gists{/gist_id}","starred_url":"https://api.github.com/users/abadger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abadger/subscriptions","organizations_url":"https://api.github.com/users/abadger/orgs","repos_url":"https://api.github.com/users/abadger/repos","events_url":"https://api.github.com/users/abadger/events{/privacy}","received_events_url":"https://api.github.com/users/abadger/received_events","type":"User","site_admin":false},"created_at":"2016-05-01T05:02:05Z","updated_at":"2016-05-01T05:02:05Z","body":"This looks pretty good but it doesn't handle xz compressed tar archives.  If we go this route you'll probably have to write a new function in the TarXzArchive class to handle that case.  Maybe you can use one of the streaming modes: https://docs.python.org/2/library/tarfile.html#tarfile.open  along with invoking the xz program via subproces to do that."}}