diff options
author | Michael DeHaan <michael@ansibleworks.com> | 2013-06-01 16:38:16 +0200 |
---|---|---|
committer | Michael DeHaan <michael@ansibleworks.com> | 2013-06-01 16:38:16 +0200 |
commit | 6cd3ba5b06578deda4aca19e77debb59d1d7df49 (patch) | |
tree | a8d2c7aa2eb2201eb2f31f4fcf4b13218ed1e77e /lib | |
parent | Merge pull request #3089 from kentfrazier/unsafe-extra-vars-fix (diff) | |
download | ansible-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__.py | 18 | ||||
-rw-r--r-- | lib/ansible/inventory/vars_plugins/group_vars.py | 87 |
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 |