Repository: ansible/ansible

Issue:
ansible-pull broke fully after update from 2.3 to 2.4
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
ansible-pull

##### ANSIBLE VERSION
```
~> ansible --version
ansible 2.4.0.0
  config file = /home/klaus/.ansible.cfg
  configured module search path = [u'/home/klaus/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
```

##### CONFIGURATION
```
~> ansible-config dump --only-changed
ANSIBLE_SSH_PIPELINING(/etc/ansible/ansible.cfg) = True
DEFAULT_BECOME_METHOD(/etc/ansible/ansible.cfg) = su
DEFAULT_GATHERING(/etc/ansible/ansible.cfg) = smart
DEFAULT_MANAGED_STR(/etc/ansible/ansible.cfg) = Ansible managed file
RETRY_FILES_ENABLED(/etc/ansible/ansible.cfg) = False
```

##### OS / ENVIRONMENT
Debian and Devuan Linux 

##### SUMMARY
I have the following pull command:

```
ansible-pull --url=git@xxxx:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full --force site.yaml
```

This worked well up to version 2.3. With version 2.4 it doesn't work anymore.

There are two cases.

1.

When an checkout under /root/.ansible/pull/hostname already exists, I get something like this:
```
Starting Ansible Pull at 2017-10-08 08:55:46
/usr/bin/ansible-pull --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full --force site.yaml
 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available
…

 [WARNING]: No hosts matched, nothing to do

 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available
…
```

It tries the playbook but do neither check git at all nor apply any play.

The worst is that it return with error 0 so it gets unnoticed in cron.

2.

The second case is much  worse, when no checkout already exists, it does not even try to get the checkout from git.

##### STEPS TO REPRODUCE
See above

Let me say, this is the worst that can happen for a configuration management system.


Discussion:
I found some hints.

If I create a static `/root/hosts` file,  just having the hostname in it, I get the following:
```
~> ANSIBLE_FORCE_COLOR=true ansible-pull --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full --force site.yaml
Starting Ansible Pull at 2017-10-08 17:54:35
/usr/bin/ansible-pull --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full --force site.yaml
 [WARNING]: Could not match supplied host pattern, ignoring: yyy.domain

ikki | SUCCESS => {
    "after": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
    "before": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
    "changed": false, 
    "failed": false, 
    "remote_url_changed": false
}
 [WARNING]: Could not match supplied host pattern, ignoring: yyy.domain
```

Without any hosts file, I get the following:
```
~> ANSIBLE_FORCE_COLOR=true ansible-pull --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full --force site.yaml
Starting Ansible Pull at 2017-10-08 17:55:40
/usr/bin/ansible-pull --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full --force site.yaml
 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available

 [WARNING]: Could not match supplied host pattern, ignoring: yyy

 [WARNING]: Could not match supplied host pattern, ignoring: yyy.domain

 [WARNING]: No hosts matched, nothing to do

 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available

 [WARNING]: Could not match supplied host pattern, ignoring: yyy

 [WARNING]: Could not match supplied host pattern, ignoring: yyy.domain
```

Note that it always try to use yyy and yyy.domain. The later is never in inventory but is the fqdn of the host.
this looks like dupe of #30636, can you confirm #30938 fixes it for you?
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hi,

Am Mo den  9. Okt 2017 um 14:38 schrieb Brian Coca:
> this looks like dupe of #30636,

Yes, looks the same.

However, I would add that it seems to be two issues in one.

- - First is the pul when the repository was not cloned before. That is
  #30636 about. But note, that ansible keeps the clone between the
  sessions under /root/.ansible/pull/hostname.domain after the first
  one.

- - The second is the one I describe in the report. And that is even the
  much dangerouse one as I found out. If you have a inventory file
  /root/hosts laying around but with just the one hostname in it, it
  takes that to decide which groups a server is in. If that file is not
  there, it simply fail with setting return code to 0.

So for me it even doesn't work if I already have a clone.

> can you confirm #30938 fixes it for you?

I will try it. (A bit hard as I install ansible via apt from
debian/devuan repository.)

Regards
   Klaus
- -- 
Klaus Ethgen                                       http://www.ethgen.ch/
pub  4096R/4E20AF1C 2011-05-16            Klaus Ethgen <Klaus@Ethgen.ch>
Fingerprint: 85D4 CA42 952C 949B 1753  62B3 79D0 B06F 4E20 AF1C
-----BEGIN PGP SIGNATURE-----
Comment: Charset: ISO-8859-1

iQGzBAEBCgAdFiEEMWF28vh4/UMJJLQEpnwKsYAZ9qwFAlnbgTcACgkQpnwKsYAZ
9qyLCgv8Ds5RgGitB9fN3pSBXO5J5iXZxo1YRak445QDxwjVCrIWX86MHyJbL9Iu
XppqHewQtn1EEKxxHYYQMWqRTPzBHYjC19b6eGuxlHhULCU1MJFLKAeQgCeQJDj/
iIA0Z2sXY+TWMVhsjyRA4XcJjyCr/o46tLhqkFsmW0mrsIUjl30JEukQOnlqtg7t
P1qxomORidf3dMy+kESo552N6qP1ZLA+4GTrCjOROLqPEzean38KEN+R+7NDNthZ
eSkl1hSwUW+yuzTpKRQo+kjx5rT6QiXCD1xcBvH3sbeBhxIA3HjciHlHoIPcGVDF
nFbXdz4Sl2IDE9bF1+StYvvGhhBVi8QtNwEI0ZJBtNkfJlFUnt2mFq1xKxqe+Tya
prBicNVqJzmY7qVrDBh97yU4/aVYSAB3AjXVPeRhTGTlb3Qk1AVwkSuWx13NeVOX
TIRI95y14LRFDbI5tShOk+uVSj2PaH76E5iBQ0C8AMXJkpLCAcFDgKuPFzU3ktW5
pg8GABvy
=hFm7
-----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hi,

Am Mo den  9. Okt 2017 um 14:38 schrieb Brian Coca:
> can you confirm #30938 fixes it for you?

No, it does not resolv the case for me. It makes it even worse.

It solves the first case that it will not fail with the git pull. BUT

It then calls the playbook with localhost instead of the correct
hostname (as it seems). That will apply a playbook with wrong vars set
and no group. So this playbook run will destroy server activelly,
removing users that are needed and other stuff.

A hint is the warning, I still have:
   [WARNING]: Could not match supplied host pattern, ignoring: ikki
   [WARNING]: Could not match supplied host pattern, ignoring: ikki.ket
   ... The pull, now done ...
   [WARNING]: Could not match supplied host pattern, ignoring: ikki
   [WARNING]: Could not match supplied host pattern, ignoring: ikki.ket

The correct hostname is ikki and the fqdn is ikki.ket. (I cencored that
hostname before)

So, conclusion, before applying the patch, it just doesn't find any play
that match the host and does no harm. But with the patch it does all
plays that are specified for all so it destroys stuff.

Regards
   Klaus
- -- 
Klaus Ethgen                                       http://www.ethgen.ch/
pub  4096R/4E20AF1C 2011-05-16            Klaus Ethgen <Klaus@Ethgen.ch>
Fingerprint: 85D4 CA42 952C 949B 1753  62B3 79D0 B06F 4E20 AF1C
-----BEGIN PGP SIGNATURE-----
Comment: Charset: ISO-8859-1

iQGzBAEBCgAdFiEEMWF28vh4/UMJJLQEpnwKsYAZ9qwFAlnbhEQACgkQpnwKsYAZ
9qyvawv/bHRcUTT+iBZ3nGpojjIA113KnqgvkaoWDSf/piUHocSJIdqDdUrIw1Wz
QKGmRT2zBWFlYDcfurtuhVn6VPbfxfdIlHc560tlTY35FztWY00PNIz37FeNQaa6
lKCgofogzKKDg4hMdxvA/GIyhjOiYMLDZkzgtmdrDprx18w9ntqs60FYoBBF5dhv
364eHpxJFvtd5zI69BbtYQnGsv/Zv9Kpt8D2FkigDC8tBMCLmXYEF30LQU8n10v3
zRmeO81s1LWLTcT/Z35FgArfBTeCuHy5e3s6YzB051K1kWrC4WccQvIJ+rKvfLaM
r4J30cHH+vYv/g6ZQ3ADb4NbtG6pOwUEsp40FV169AmPx55WUA6lhCl3rVMV48v7
e20GaLBa9Ddc6Ezufc2y/WDFLv/rbj5I94lTqReMaFQ6s8f7TtyqCxYEnzSLcXZr
aXl4T6EQ/8SC20cXdg/Sopnc8ggElXzr+8RtSZv9MGUg7aM5SdcX4ynOG3M8JwIi
RoUqZz2s
=DDDC
-----END PGP SIGNATURE-----

Can you run with -vvvv to see the exact commands passed?

I'm not sure what you are expecting in this case when the host is not in the inventory, it should be using localhost. 

If you are worried about the 'implicit localhost including all vars' that has been reverted in separate patch, but was unrelated to pull. We added it on purpose, as it was a requested feature .. which we had to revert due to it breaking existing setups.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Am Mo den  9. Okt 2017 um 16:04 schrieb Brian Coca:
> Can you run with -vvvv to see the exact commands passed?

I can do that later on.

> I'm not sure what you are expecting in this case when the host is not in the inventory, it should be using localhost. 

You misunderstood. The host _is_ in the inventory that is coming from
the clone/checkout. But the inventory is not used.

This was working up to version 2.3 and broken in version 2.4.

> If you are worried about the 'implicit localhost including all vars' that has been reverted in separate patch, but was unrelated to pull, it was adding a requested feature .. which we had to revert due to it breaking existing setups.

It is not about localhost implying all or not. The problem is that
localhost is not in the inventory but the hostname is.

With 2.4 it seems to be unable to match the hostname (ikki in my case)
to the inventory where this exact hostname is in multiple times in
several groups.

The problem here is, as I sayd, that ansible-pull seems to refuse to use
the inventory from the git repository and try to match the hostname to a
nonexistant other inventory (/root/hosts or /etc/ansible/hosts, I
believe, both are not exsisting). It should (and did with up to 2.3) use
the inventory from /root/.ansible/pull/ikki.ket/hosts that is inside the
stuff that ansible-pull is checking out.

Regards
   Klaus
- -- 
Klaus Ethgen                                       http://www.ethgen.ch/
pub  4096R/4E20AF1C 2011-05-16            Klaus Ethgen <Klaus@Ethgen.ch>
Fingerprint: 85D4 CA42 952C 949B 1753  62B3 79D0 B06F 4E20 AF1C
-----BEGIN PGP SIGNATURE-----
Comment: Charset: ISO-8859-1

iQGzBAEBCgAdFiEEMWF28vh4/UMJJLQEpnwKsYAZ9qwFAlnbpjkACgkQpnwKsYAZ
9qye5gwAmmuPzoixJWN6OZ0XQ0ImGHroztS2brMtOmUehBph2dHltYa0VNVmIzu7
SA3hM8+HgnYkYNCtZg/KzDrl7XfVbcafC6IICaRhMxsNhvLfHy7STbXm9Hr5B978
bBvAws0wilUyLgf/RpUhyICvbh+WKM0t3tDUthEgA72P1SXFRRSO+JsDP1HydJ5A
vEnJD8RR3X57ePpXn3pZWmbkmv8j9Ii5SxfufmHw69QZ4SwmMu1vY+33FoVOxyY6
dSiZesfJIlCF4W87qJaKVf28BKYO9lNx0IB5s9gk5jxHCll193CkTLtRrIkkw9yi
b3vZ7Ml0bGt/uK/r4UHpJy+Z2mPwAFYeoqco+uLiT+i0/1ggNp577Ynw4uxeR49z
kjcsLBVrcaJX49eHAbau84sDgXKAEyW7NB0x3ZtY3DFgQondtlcjl8eCmH7Cc5Qc
kSIBu8rH/ClVC31qfNHmh4rrLqFgfnM+KJS7o8IXWOYcEdbnYe++JlT4zGPJswL8
Ufb/uFia
=XbG7
-----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Short correction, /etc/ansible/hosts exists and is a file with just
comments coming from the debian package.

But in ansible-pull, that file is completelly irrelevant and should not
be read.

Regards
   Klaus
- -- 
Klaus Ethgen                                       http://www.ethgen.ch/
pub  4096R/4E20AF1C 2011-05-16            Klaus Ethgen <Klaus@Ethgen.ch>
Fingerprint: 85D4 CA42 952C 949B 1753  62B3 79D0 B06F 4E20 AF1C
-----BEGIN PGP SIGNATURE-----
Comment: Charset: ISO-8859-1

iQGzBAEBCgAdFiEEMWF28vh4/UMJJLQEpnwKsYAZ9qwFAlnbpwkACgkQpnwKsYAZ
9qzV6wwAhUxJfw3RaYYHS9rKZmQay8CJtOZqkdm4cs7c/c3wakd60DvrHzI56SLt
VhQXBRqi6Z0FL3Czyzu0+6qGrQtdT6JnOSPNvrasesXHweobIky+lRHd0IkdMH/s
VpPag+/B6M3d8hQuPk+8sUFoxiiW6okvdNEAnnMn3kye1P11yfi49BNfz8FnBltY
TT1tiyhoUWFGEBy53ahG3Sh38r9mpPF3d+w4/AcznuyWO/1miP42Dtjnxl51m8ZN
qsY83KvvZFw32B4tv2hyDC5725XcQBezdWJShFtznF+fS1HvqG+8LzJc29g04KLO
fhpRfgq5s2NawIrA2fWtrRBfckzIl64RcTBNenVD4NnjdjavuYsxqfseLJaJ6pxp
gcUESHirOgxF0msKyVn2rm+2fV2X3Ii0OFUZpnuQ+ukilOoowDHtkCgr3t75K3jt
LCSbhad+XLadnY8JCC2AaLTntZMZUjcVo1j6eTZBNWNwOYwoXPzLZgXldodQxOkV
mVFF6xwL
=36DP
-----END PGP SIGNATURE-----

the problem is not on the pull, but on the playbook side then, the verbose output will show if we are seeing correctly or not the inventory pulled out from git. In my tests this works, but we need to see what is going on in your case.
I did some outputs now up to the first playbook part. I did redact them to have the same hostname (As the first run is from a different host as you might get at the moment).

The first here is the run from version 2.3:
```
~> ANSIBLE_FORCE_COLOR=true ansible-pull -vvvv --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full site.yaml
Using /etc/ansible/ansible.cfg as config file
Starting Ansible Pull at xxxx-xx-xx xx:xx:xx
/usr/bin/ansible-pull -vvvv --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full site.yaml
EXEC: /usr/bin/ansible -i "localhost," -c local  -vvvv -m git -a "name=git@tschil:ansible dest=/root/.ansible/pull/host.domain key_file=/root/.ssh/ansible.key" all -l "localhost,host,host.domain,127.0.0.1"
Using /etc/ansible/ansible.cfg as config file
Set default localhost to localhost
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc
META: ran handlers
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/source_control/git.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814 `" && echo ansible-tmp-1507567547.93-41659326875814="` echo /root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814 `" ) && sleep 0'
<localhost> PUT /tmp/tmptLoMJO TO /root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814/git.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814/ /root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814/git.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814/git.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1507567547.93-41659326875814/" > /dev/null 2>&1 && sleep 0'
localhost | SUCCESS => {
    "after": "478e5d6e692bf96856c309887e079f961ba4eb13",
    "before": "478e5d6e692bf96856c309887e079f961ba4eb13",
    "changed": false,
    "invocation": {
        "module_args": {
            "accept_hostkey": false,
            "bare": false,
            "clone": true,
            "depth": null,
            "dest": "/root/.ansible/pull/host.domain",
            "executable": null,
            "force": false,
            "key_file": "/root/.ssh/ansible.key",
            "name": "git@tschil:ansible",
            "recursive": true,
            "reference": null,
            "refspec": null,
            "remote": "origin",
            "repo": "git@tschil:ansible",
            "ssh_opts": null,
            "track_submodules": false,
            "umask": null,
            "update": true,
            "verify_commit": false,
            "version": "HEAD"
        }
    },
    "remote_url_changed": false
}
META: ran handlers
META: ran handlers
Using /etc/ansible/ansible.cfg as config file
statically included: /root/.ansible/pull/host.domain/roles/security/tasks/auditd.yaml
statically included: /root/.ansible/pull/host.domain/roles/iptables/tasks/ipv4.yaml
statically included: /root/.ansible/pull/host.domain/roles/iptables/tasks/ipv4.yaml
statically included: /root/.ansible/pull/host.domain/roles/openvpn/tasks/openvpn.yml
statically included: /root/.ansible/pull/host.domain/roles/openvpn/tasks/install.deb.yml
statically included: /root/.ansible/pull/host.domain/roles/openvpn/tasks/install.yum.yml
statically included: /root/.ansible/pull/host.domain/roles/openvpn/tasks/configure.yml
statically included: /root/.ansible/pull/host.domain/roles/openvpn/tasks/read-client-files.yml
statically included: /root/.ansible/pull/host.domain/roles/openvpn/tasks/setup-bridge.yml
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: site.yaml ********************************************************************************************
10 plays in /root/.ansible/pull/host.domain/site.yaml
```

The second is vanilla 2.4:
```
~> ANSIBLE_FORCE_COLOR=true ansible-pull -vvvv --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full site.yaml
ansible-pull 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-pull
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
Using /etc/ansible/ansible.cfg as config file
Starting Ansible Pull at xxxx-xx-xx xx:xx:xx
/usr/bin/ansible-pull -vvvv --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full site.yaml
EXEC: /usr/bin/ansible  -c local  -vvvv -m git -a "name=git@tschil:ansible dest=/root/.ansible/pull/host.domain key_file=/root/.ssh/ansible.key" all -l "localhost,host,host.domain,127.0.0.1"
ansible 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
Parsed /etc/ansible/hosts inventory source with ini plugin
 [WARNING]: Could not match supplied host pattern, ignoring: all
 [WARNING]: provided hosts list is empty, only localhost is available
 [WARNING]: Could not match supplied host pattern, ignoring: host
 [WARNING]: Could not match supplied host pattern, ignoring: host.domain
 [WARNING]: No hosts matched, nothing to do
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc
ansible-playbook 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
Parsed /etc/ansible/hosts inventory source with ini plugin
 [WARNING]: Could not match supplied host pattern, ignoring: all
 [WARNING]: provided hosts list is empty, only localhost is available
 [WARNING]: Could not match supplied host pattern, ignoring: host
 [WARNING]: Could not match supplied host pattern, ignoring: host.domain
[DEPRECATION WARNING]: The use of 'include' for tasks has been deprecated. Use 'import_tasks' for static inclusions or 'include_tasks' for dynamic inclusions. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: include is kept for backwards compatibility but usage is discouraged. The module documentation details page may explain more about this rationale.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
statically imported: /root/.ansible/pull/host.domain/roles/security/tasks/auditd.yaml
[DEPRECATION WARNING]: The use of 'static' has been deprecated. Use 'import_tasks' for static inclusion, or 'include_tasks' for dynamic inclusion. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
statically imported: /root/.ansible/pull/host.domain/roles/iptables/tasks/ipv4.yaml
statically imported: /root/.ansible/pull/host.domain/roles/iptables/tasks/ipv4.yaml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/openvpn.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/install.deb.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/install.yum.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/configure.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/read-client-files.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/setup-bridge.yml
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: site.yaml ********************************************************************************************
10 plays in /root/.ansible/pull/host.domain/site.yaml
```

And the last is from a 2.4 with your patch:
```
~> ANSIBLE_FORCE_COLOR=true ansible-pull -vvvv --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full site.yaml
ansible-pull 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-pull
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
Using /etc/ansible/ansible.cfg as config file
Starting Ansible Pull at xxxx-xx-xx xx:xx:xx
/usr/bin/ansible-pull -vvvv --url=git@tschil:ansible --inventory=hosts --private-key=/root/.ssh/ansible.key --full site.yaml
EXEC: /usr/bin/ansible  -i localhost,  -c local  -vvvv -m git -a "name=git@tschil:ansible dest=/root/.ansible/pull/host.domain key_file=/root/.ssh/ansible.key" all -l "localhost,host,host.domain,127.0.0.1"
ansible 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
Set default localhost to localhost
Parsed localhost, inventory source with host_list plugin
 [WARNING]: Could not match supplied host pattern, ignoring: host
 [WARNING]: Could not match supplied host pattern, ignoring: host.domain
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc
META: ran handlers
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/source_control/git.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396 `" && echo ansible-tmp-1507568475.67-260277826890396="` echo /root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396 `" ) && sleep 0'
<localhost> PUT /tmp/tmp2F5u3H TO /root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396/git.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396/ /root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396/git.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396/git.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1507568475.67-260277826890396/" > /dev/null 2>&1 && sleep 0'
localhost | SUCCESS => {
    "after": "478e5d6e692bf96856c309887e079f961ba4eb13",
    "before": "478e5d6e692bf96856c309887e079f961ba4eb13",
    "changed": false,
    "failed": false,
    "invocation": {
        "module_args": {
            "accept_hostkey": false,
            "archive": null,
            "bare": false,
            "clone": true,
            "depth": null,
            "dest": "/root/.ansible/pull/host.domain",
            "executable": null,
            "force": false,
            "key_file": "/root/.ssh/ansible.key",
            "name": "git@tschil:ansible",
            "recursive": true,
            "reference": null,
            "refspec": null,
            "remote": "origin",
            "repo": "git@tschil:ansible",
            "ssh_opts": null,
            "track_submodules": false,
            "umask": null,
            "update": true,
            "verify_commit": false,
            "version": "HEAD"
        }
    },
    "remote_url_changed": false
}
META: ran handlers
META: ran handlers
ansible-playbook 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.14 (default, Sep 17 2017, 18:50:44) [GCC 7.2.0]
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
Set default localhost to localhost
Parsed localhost, inventory source with host_list plugin
 [WARNING]: Could not match supplied host pattern, ignoring: host
 [WARNING]: Could not match supplied host pattern, ignoring: host.domain
[DEPRECATION WARNING]: The use of 'include' for tasks has been deprecated. Use 'import_tasks' for static inclusions or 'include_tasks' for dynamic inclusions. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: include is kept for backwards compatibility but usage is discouraged. The module documentation details page may explain more about this rationale.. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
statically imported: /root/.ansible/pull/host.domain/roles/security/tasks/auditd.yaml
[DEPRECATION WARNING]: The use of 'static' has been deprecated. Use 'import_tasks' for static inclusion, or 'include_tasks' for dynamic inclusion. This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
statically imported: /root/.ansible/pull/host.domain/roles/iptables/tasks/ipv4.yaml
statically imported: /root/.ansible/pull/host.domain/roles/iptables/tasks/ipv4.yaml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/openvpn.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/install.deb.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/install.yum.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/configure.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/read-client-files.yml
statically imported: /root/.ansible/pull/host.domain/roles/openvpn/tasks/setup-bridge.yml
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: site.yaml ********************************************************************************************
10 plays in /root/.ansible/pull/host.domain/site.yaml
```

You can use vimdiff to compare them...
Note the two lines:
```
 [WARNING]: Could not match supplied host pattern, ignoring: host
 [WARNING]: Could not match supplied host pattern, ignoring: host.domain
```

They show that it is not using the correct inventory as that would hold the definition for „host“ (non full qualified).

Note also that this warning for both is absolutelly misleading as there is just one version in inventory not both as that would trigger more problems. So if the host is found once, it should not warn about the other.

(I did one test the day before to put a inventory „hosts“ into `/root/hosts` and that seems to get used but when I put `host` and `host.domain` into that file the same time, it got weird.)
Ah, yes, if you wounder about, in all 3 cases above, there was already a checkout under `/root/.ansible/pull/host.domain`. I did not do the case with a plain new box where that clone is not existing.
can you rerun again? this time with ANSIBLE_DEBUG=1 
Which of the 3? And is it usefull to have all this output here?
You should only be running one command, `ansible-pull`.

All, no, but cannot see exactly what i need until you post it. 
What you put above at least shows that `ansible -m git ...` is being called correctly, now i need more info.
I wrote you by mail.
@mowgli unless I had you whitelisted its probably in `/dev/null` by now
to clarify, i mainly need the `EXEC ansible-playbook` line from the debug output after my PR is applied, but any of the lines pertaining to inventory sources might also be needed.
```
31370 1507579311.53430: EXEC: /usr/bin/ansible-playbook -c local  -vvvv /root/.ansible/pull/ikki.ket/site.yaml -t "all" -l "localhost,ikki,ikki.ket,127.0.0.1" -i localhost,
```

Then just whitelist me. :-D

Edit: I believe, the `-i localhost,` is the wrong part.
Next edit: Hmm.. and maybe without that it is loading the wrong file.
As I give the inventory non fg on the pull-commandline, it should be full qualified in tthe playbook run.

If I do so, I get the following:
```
~> /usr/bin/ansible-playbook -c local /root/.ansible/pull/ikki.ket/site.yaml -t "all" -l "localhost,ikki,ikki.ket,127.0.0.1" -i /root/.ansible/pull/ikki.ket/hosts
 [WARNING]: Could not match supplied host pattern, ignoring: ikki.ket
```

Still this warning that should not be there but only one, not both host names. And the playbok is running fine then.
~hmm, that shows that it is not finding the inventory files even after the pull~ nvmd ... scrolling

This does seem to be the correct file, can you post the debugging on the processing of it?
`-i /root/.ansible/pull/ikki.ket/hosts`
Ah, I found your bug.. (I think)

The problem is in the `os.chdir(self.options.dest)`. `self.options.dest` is the file name of the playbook (full path of site.yaml). And as you do not check the return code of that chdir, it is not chdir to the basename of that file.
What exactly do you need? `-i /root/.ansible/pull/ikki.ket/hosts` to what command?
@mowgli weird, that code has not changed in a long time, would be a preexisting bug. In any case dest is supposed to be a directory (we should really check).
Hmm. I think, my assumption is wrong.

The `self.options.dest` seems to be just the path without the site.yaml..
Ah, clear...

I run the command without the `-i localhost,` from `/root` when I did it manually. But even than, I gave the inventory with the original pull command so it is not working that way. Only when adding `-i hosts` instead of `-i localhost,` /after/ chdir to `/root/.ansible/pull/ikki.ket` it is doing what it should.

That does not explain why `self._get_inv_cli` is not working correct.

Edit: Is that `if getattr(self.options, 'inventory'):` working as it looks like? Or is that always false?
It should be `if self.options.inventory:`, right?
No idea, I am no python programmer.
The original from 2.3 was:
```python
if self.options.inventory:
    cmd += ' -i "%s"' % self.options.inventory
```

So no checks was made to find out if inventory exists or not.
FOUND IT!!!!!

self.options.inventory is `[u'/root/hosts']` when specified as `--inventory=hosts`

So, the options parsing code seems to resolv the path to full qualified! With that, your logic fails badly.

So, to fix it, the original logic to use don't try over smart with fully qualify an option might fix the problem (in combination with your patch).

Edit:
The code that broke it all is in `…/cli/__init__.py`:
```python
        # process inventory options
        if hasattr(self.options, 'inventory'):

            if self.options.inventory:

                # should always be list
                if isinstance(self.options.inventory, string_types):
                    self.options.inventory = [self.options.inventory]

                # Ensure full paths when needed
                self.options.inventory = [unfrackpath(opt) if ',' not in opt else opt for opt in self.options.inventory]

            else:
                self.options.inventory = C.DEFAULT_HOST_LIST
```

And let me add, that code was add by you at the 2017-05-23 with commit 8f97aef1a36. ;-)
This path fix could solve this also #31533
Sorry, no, does not fix it. And I put a print out for inventory to pull.py that shows that the path is still /root/hosts.
This bug is a catastrophe and breaks a significant part of my working infrastructure.

On a clean Install I have a cron script that runs

```sh
ansible-pull --accept-host-key -d /MY_PATH --key-file /MY_KEY --url='git@MY_GIT.git' --sleep=10 --checkout=master --inventory-file /MY_PATH/production MY_PLAYBOOK.yml
```

which calls

```sh
ansible  -c local  -vvvvv -m git -a "name=git@MY_GIT.git dest=/MY_PATH version=master accept_hostkey=yes key_file=/MY_KEY depth=1" all -l "localhost,MY_HOSTNAME,127.0.0.1"
```

WHICH NOW FAILS!

changing the call manually to 

```sh
ansible  -c local  -vvvvv -m git -a "name=git@MY_GIT.git dest=/MY_PATH version=master accept_hostkey=yes key_file=/MY_KEY depth=1" localhost -l "localhost,MY_HOSTNAME,127.0.0.1"
```

i.e. replace 'all' with 'localhost', fixes the problem.

`ansible-pull` **is my solution to manage remote infrastructure behind firewalls where I can't access machines. This bug broke remote provisioning and put me very very close to losing access to a number of my machines. It is almost catastrophic.**
the problem is **all stopped matching localhost** on a clean install (i.e. has not checked out the git repo). It evidently now fails to check it out because all no longer matches localhost so it thinks there is nothing to do.
@abadger sorry for the ping but I see you are managing 2.4.1 release candidates. Would be good to get some eyes on this as it's a serious regression.
@nzjrs yours seems to be different issue, can you check against current devel and/or 2.4.1 to see if that is fixed there? If it still fails, please open a separate ticket for your issue, please fill in the template and provide a simple reproducer if possible.
I'm sorry I'm not in a position to test at the moment. I'm underwater putting out fires from this? bug.

A reproducer is to run `ansible  -c local  -vvvvv -m git -a "name=git@MY_GIT.git dest=/MY_PATH version=master accept_hostkey=yes key_file=/MY_KEY depth=1" all -l "localhost,MY_HOSTNAME,127.0.0.1"
` on a fresh machine
Hi Brian,

Am Fr den 20. Okt 2017 um 15:39 schrieb Brian Coca:
> @nzjrs yours seems to be different issue, can you check against current devel and/or 2.4.1 to see if that is fixed there?

I don't think so, it seems to be right the same bug that I described in [detail in]
#30636 on 2017-10-09.

The problem are two problems in one. One can be fixed with your first
patch you mentioned here above (#30938, I believe). And that seems to be
the problem, John is talking about.

But the second one (that is nearly same problematic and is the source of
the first problem too, I believe) is that (as I wrote above under
"FOUND IT!!!!!", is that the path gets full qualified with the call and
later on you lost the information of the relative path.

The only solution, that I can think about, is to postpone the path
qualifying until the final chdir is done. But that means to drop the
commit that brought in the problem in cli/__init__.py, 8f97aef.

Let me finally punctuate, that problem is a serious problem and is
exactly the case that caused the damage, John is suffering from now. I
had the same trouble, but was lucky that I had ssh access to the boxes,
so I was able to downgrade to 2.3.2.

Regards
   Klaus

Resolving patch:
diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py
--- a/lib/ansible/cli/__init__.py
+++ b/lib/ansible/cli/__init__.py
@@ -112,6 +112,7 @@ class CLI(with_metaclass(ABCMeta, object)):
     # -F (quit-if-one-screen) -R (allow raw ansi control chars)
     # -S (chop long lines) -X (disable termcap init and de-init)
     LESS_OPTS = 'FRSX'
+    SKIP_INVENTORY_DEFAULTS = False
 
     def __init__(self, args, callback=None):
         """
@@ -424,8 +425,7 @@ def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False,
 
         if inventory_opts:
             parser.add_option('-i', '--inventory', '--inventory-file', dest='inventory', action="append",
-                              help="specify inventory host path (default=[%s]) or comma separated host list. "
-                                   "--inventory-file is deprecated" % C.DEFAULT_HOST_LIST)
+                              help="specify inventory host path or comma separated host list. --inventory-file is deprecated")
             parser.add_option('--list-hosts', dest='listhosts', action='store_true',
                               help='outputs a list of matching hosts; does not execute anything else')
             parser.add_option('-l', '--limit', default=C.DEFAULT_SUBSET, dest='subset',
@@ -605,8 +605,8 @@ def parse(self):
                     skip_tags.add(tag.strip())
             self.options.skip_tags = list(skip_tags)
 
-        # process inventory options
-        if hasattr(self.options, 'inventory'):
+        # process inventory options except for CLIs that require their own processing
+        if hasattr(self.options, 'inventory') and not self.SKIP_INVENTORY_DEFAULTS:
 
             if self.options.inventory:
 
@@ -616,7 +616,6 @@ def parse(self):
 
                 # Ensure full paths when needed
                 self.options.inventory = [unfrackpath(opt, follow=False) if ',' not in opt else opt for opt in self.options.inventory]
-
             else:
                 self.options.inventory = C.DEFAULT_HOST_LIST
 
diff --git a/lib/ansible/cli/pull.py b/lib/ansible/cli/pull.py
--- a/lib/ansible/cli/pull.py
+++ b/lib/ansible/cli/pull.py
@@ -67,6 +67,8 @@ class PullCLI(CLI):
                                  "look for a playbook based on the host's fully-qualified domain name,"
                                  'on the host hostname and finally a playbook named *local.yml*.', }
 
+    SKIP_INVENTORY_DEFAULTS = True
+
     def _get_inv_cli(self):
 
         inv_opts = ''
@@ -77,9 +79,6 @@ def _get_inv_cli(self):
                 elif ',' in inv or os.path.exists(inv):
                     inv_opts += ' -i %s ' % inv
 
-        if not inv_opts:
-            inv_opts = " -i localhost, "
-
         return inv_opts
 
     def parse(self):
@@ -125,9 +124,6 @@ def parse(self):
         self.parser.add_option("--check", default=False, dest='check', action='store_true',
                                help="don't make any changes; instead, try to predict some of the changes that may occur")
 
-        # for pull we don't want a default
-        self.parser.set_defaults(inventory=None)
-
         super(PullCLI, self).parse()
 
         if not self.options.dest:
@@ -177,6 +173,8 @@ def run(self):
         # Attempt to use the inventory passed in as an argument
         # It might not yet have been downloaded so use localhost as default
         inv_opts = self._get_inv_cli()
+        if not inv_opts:
+            inv_opts = " -i localhost, "
 
         # FIXME: enable more repo modules hg/svn?
         if self.options.module_name == 'git':


Test patch: