Implicit localhost ondemand (#16900)

* Revert "There can be only one localhost"

This reverts commit 5f1bbb4fcd.
this broke several usages of localhost, see #16882, #16898 and #16886

* ensure there is only 1 localhost

fixes #16886, #16882 and #16898

- make sure localhost exists before returning it
- optimzed host caching
- ensure we always return a host object

(cherry picked from commit f7570f1dc4)
This commit is contained in:
Brian Coca 2016-08-02 10:39:00 -04:00 committed by Brian Coca
parent db4e661fef
commit df16e37ad7
2 changed files with 51 additions and 29 deletions

View file

@ -90,8 +90,6 @@ class Inventory(object):
self.clear_pattern_cache() self.clear_pattern_cache()
self.parse_inventory(host_list) self.parse_inventory(host_list)
if self.localhost is None:
self.localhost = self._create_implicit_localhost()
def serialize(self): def serialize(self):
data = dict() data = dict()
@ -128,13 +126,15 @@ class Inventory(object):
display.vvv("Unable to parse address from hostname, leaving unchanged: %s" % to_unicode(e)) display.vvv("Unable to parse address from hostname, leaving unchanged: %s" % to_unicode(e))
host = h host = h
port = None port = None
new_host = Host(host, port) new_host = Host(host, port)
all.add_host(new_host) if h in C.LOCALHOST:
if new_host.name in C.LOCALHOST: # set default localhost from inventory to avoid creating an implicit one. Last localhost defined 'wins'.
if self.localhost is None: if self.localhost is not None:
display.warning("A duplicate localhost-like entry was found (%s). First found localhost was %s" % (h, self.localhost.name))
display.vvvv("Set default localhost to %s" % h)
self.localhost = new_host self.localhost = new_host
else: all.add_host(new_host)
display.warning("A duplicate localhost-like entry was found (%s). First found localhost was %s" % (new_host.name, self.localhost.name))
elif self._loader.path_exists(host_list): elif self._loader.path_exists(host_list):
#TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins' #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
if self.is_directory(host_list): if self.is_directory(host_list):
@ -470,9 +470,16 @@ class Inventory(object):
for host in matching_hosts: for host in matching_hosts:
__append_host_to_results(host) __append_host_to_results(host)
if pattern in C.LOCALHOST and len(results) == 0:
new_host = self._create_implicit_localhost(pattern)
results.append(new_host)
return results return results
def _create_implicit_localhost(self, pattern='localhost'): def _create_implicit_localhost(self, pattern):
if self.localhost:
new_host = self.localhost
else:
new_host = Host(pattern) new_host = Host(pattern)
new_host.address = "127.0.0.1" new_host.address = "127.0.0.1"
new_host.implicit = True new_host.implicit = True
@ -486,6 +493,7 @@ class Inventory(object):
py_interp = '/usr/bin/python' py_interp = '/usr/bin/python'
new_host.set_variable("ansible_python_interpreter", py_interp) new_host.set_variable("ansible_python_interpreter", py_interp)
self.get_group("ungrouped").add_host(new_host) self.get_group("ungrouped").add_host(new_host)
self.localhost = new_host
return new_host return new_host
def clear_pattern_cache(self): def clear_pattern_cache(self):
@ -509,14 +517,28 @@ class Inventory(object):
return self._hosts_cache[hostname] return self._hosts_cache[hostname]
def _get_host(self, hostname): def _get_host(self, hostname):
if hostname in C.LOCALHOST and self.localhost:
self.localhost
matching_host = None matching_host = None
if hostname in C.LOCALHOST:
if self.localhost:
matching_host= self.localhost
else:
for host in self.get_group('all').get_hosts():
if host.name in C.LOCALHOST:
matching_host = host
break
if not matching_host:
matching_host = self._create_implicit_localhost(hostname)
# update caches
self._hosts_cache[hostname] = matching_host
for host in C.LOCALHOST.difference((hostname,)):
self._hosts_cache[host] = self._hosts_cache[hostname]
else:
for group in self.groups.values(): for group in self.groups.values():
for host in group.get_hosts(): for host in group.get_hosts():
if host not in self._hosts_cache:
self._hosts_cache[host.name] = host
if hostname == host.name: if hostname == host.name:
matching_host = host matching_host = host
self._hosts_cache[host.name] = host
return matching_host return matching_host
def get_group(self, groupname): def get_group(self, groupname):

View file

@ -62,7 +62,7 @@ class HostVars(collections.Mapping):
self._inventory = inventory self._inventory = inventory
def _find_host(self, host_name): def _find_host(self, host_name):
if host_name in C.LOCALHOST: if host_name in C.LOCALHOST and self._inventory.localhost:
host = self._inventory.localhost host = self._inventory.localhost
else: else:
host = self._inventory.get_host(host_name) host = self._inventory.get_host(host_name)