summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMichael DeHaan <michael@ansibleworks.com>2013-06-01 16:38:16 +0200
committerMichael DeHaan <michael@ansibleworks.com>2013-06-01 16:38:16 +0200
commit6cd3ba5b06578deda4aca19e77debb59d1d7df49 (patch)
treea8d2c7aa2eb2201eb2f31f4fcf4b13218ed1e77e /lib
parentMerge pull request #3089 from kentfrazier/unsafe-extra-vars-fix (diff)
downloadansible-6cd3ba5b06578deda4aca19e77debb59d1d7df49.tar.xz
ansible-6cd3ba5b06578deda4aca19e77debb59d1d7df49.zip
Allow the group_vars and host_vars directories to be stored alongside the playbook as well as inventory.
Diffstat (limited to 'lib')
-rw-r--r--lib/ansible/inventory/__init__.py18
-rw-r--r--lib/ansible/inventory/vars_plugins/group_vars.py87
2 files changed, 83 insertions, 22 deletions
diff --git a/lib/ansible/inventory/__init__.py b/lib/ansible/inventory/__init__.py
index 55d8e0b06e..460b63053a 100644
--- a/lib/ansible/inventory/__init__.py
+++ b/lib/ansible/inventory/__init__.py
@@ -38,7 +38,7 @@ class Inventory(object):
__slots__ = [ 'host_list', 'groups', '_restriction', '_also_restriction', '_subset',
'parser', '_vars_per_host', '_vars_per_group', '_hosts_cache', '_groups_list',
- '_vars_plugins']
+ '_vars_plugins', '_playbook_basedir']
def __init__(self, host_list=C.DEFAULT_HOST_LIST):
@@ -54,6 +54,9 @@ class Inventory(object):
self._hosts_cache = {}
self._groups_list = {}
+ # to be set by calling set_playbook_basedir by ansible-playbook
+ self._playbook_basedir = None
+
# the inventory object holds a list of groups
self.groups = []
@@ -372,3 +375,16 @@ class Inventory(object):
if not self.is_file():
return None
return os.path.dirname(self.host_list)
+
+ def playbook_basedir(self):
+ """ returns the directory of the current playbook """
+ return self._playbook_basedir
+
+ def set_playbook_basedir(self, dir):
+ """
+ sets the base directory of the playbook so inventory plugins can use it to find
+ variable files and other things.
+ """
+ self._playbook_basedir = dir
+
+
diff --git a/lib/ansible/inventory/vars_plugins/group_vars.py b/lib/ansible/inventory/vars_plugins/group_vars.py
index d07c90ce58..405ee50f91 100644
--- a/lib/ansible/inventory/vars_plugins/group_vars.py
+++ b/lib/ansible/inventory/vars_plugins/group_vars.py
@@ -1,4 +1,4 @@
-# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2012-2013, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
@@ -23,45 +23,90 @@ import ansible.constants as C
class VarsModule(object):
+ """
+ Loads variables from group_vars/<groupname> and host_vars/<hostname> in directories parallel
+ to the inventory base directory or in the same directory as the playbook. Variables in the playbook
+ dir will win over the inventory dir if files are in both.
+ """
+
def __init__(self, inventory):
+
+ """ constructor """
+
self.inventory = inventory
def run(self, host):
- # return the inventory variables for the host
+
+ """ main body of the plugin, does actual loading """
inventory = self.inventory
- #hostrec = inventory.get_host(host)
+ self.pb_basedir = inventory.playbook_basedir()
+ # sort groups by depth so deepest groups can override the less deep ones
groupz = sorted(inventory.groups_for_host(host.name), key=lambda g: g.depth)
groups = [ g.name for g in groupz ]
- basedir = inventory.basedir()
-
- if basedir is None:
- # could happen when inventory is passed in via the API
- return
+ inventory_basedir = inventory.basedir()
results = {}
+ scan_pass = 0
+
+ # look in both the inventory base directory and the playbook base directory
+ for basedir in [ inventory_basedir, self.pb_basedir ]:
+
+
+ # this can happen from particular API usages, particularly if not run
+ # from /usr/bin/ansible-playbook
+ if basedir is None:
+ continue
+
+ scan_pass = scan_pass + 1
+
+ # it's not an eror if the directory does not exist, keep moving
+ if not os.path.exists(basedir):
+ continue
+
+ # save work of second scan if the directories are the same
+ if inventory_basedir == self.pb_basedir and scan_pass != 1:
+ continue
+
+ # load vars in dir/group_vars/name_of_group
+ for x in groups:
- # load vars in inventory_dir/group_vars/name_of_group
- for x in groups:
- p = os.path.join(basedir, "group_vars/%s" % x)
+ p = os.path.join(basedir, "group_vars/%s" % x)
+
+ # the file can be <groupname> or end in .yml or .yaml
+ # currently ALL will be loaded, even if more than one
+ paths = [p, '.'.join([p, 'yml']), '.'.join([p, 'yaml'])]
+
+ for path in paths:
+
+ if os.path.exists(path) and not os.path.isdir(path):
+ data = utils.parse_yaml_from_file(path)
+ if type(data) != dict:
+ raise errors.AnsibleError("%s must be stored as a dictionary/hash" % path)
+
+ # combine vars overrides by default but can be configured to do a hash
+ # merge in settings
+
+ results = utils.combine_vars(results, data)
+
+ # group vars have been loaded
+ # load vars in inventory_dir/hosts_vars/name_of_host
+ # these have greater precedence than group variables
+
+ p = os.path.join(basedir, "host_vars/%s" % host.name)
+
+ # again allow the file to be named filename or end in .yml or .yaml
paths = [p, '.'.join([p, 'yml']), '.'.join([p, 'yaml'])]
+
for path in paths:
+
if os.path.exists(path) and not os.path.isdir(path):
data = utils.parse_yaml_from_file(path)
if type(data) != dict:
raise errors.AnsibleError("%s must be stored as a dictionary/hash" % path)
results = utils.combine_vars(results, data)
- # load vars in inventory_dir/hosts_vars/name_of_host
- p = os.path.join(basedir, "host_vars/%s" % host.name)
- paths = [p, '.'.join([p, 'yml']), '.'.join([p, 'yaml'])]
- for path in paths:
- if os.path.exists(path) and not os.path.isdir(path):
- data = utils.parse_yaml_from_file(path)
- if type(data) != dict:
- raise errors.AnsibleError("%s must be stored as a dictionary/hash" % path)
- results = utils.combine_vars(results, data)
-
+ # all done, results is a dictionary of variables for this particular host.
return results