diff --git a/library/system/setup b/library/system/setup index 0ef28e652a0..6edebc40997 100644 --- a/library/system/setup +++ b/library/system/setup @@ -30,6 +30,9 @@ import struct import datetime import getpass import subprocess +import ConfigParser +import StringIO + DOCUMENTATION = ''' --- @@ -42,6 +45,15 @@ options: - if supplied, only return facts that match this shell-style (fnmatch) wildcard. required: false default: '*' + fact_path: + version_added: "1.3" + description: + - path used for local ansible facts (*.fact) - files in this dir + will be run (if executable) and their results be added to ansible_local facts + if a file is not executable it is read. + File/results format can be json or ini-format + required: false + default: '/etc/ansible/facts.d' description: - This module is automatically called by playbooks to gather useful variables about remote hosts that can be used in playbooks. It can also be @@ -131,6 +143,7 @@ class Facts(object): self.get_lsb_facts() self.get_date_time_facts() self.get_user_facts() + self.get_local_facts() def populate(self): return self.facts @@ -169,6 +182,51 @@ class Facts(object): self.facts['architecture'] = data[0] + def get_local_facts(self): + + fact_path = module.params.get('fact_path', None) + if not fact_path or not os.path.exists(fact_path): + return + + local = {} + for fn in sorted(glob.glob(fact_path + '/*.fact')): + # where it will sit under local facts + fact_base = os.path.basename(fn).replace('.fact','') + if os.access(fn, os.X_OK): + # run it + # try to read it as json first + # if that fails read it with ConfigParser + # if that fails, skip it + rc, out, err = module.run_command(fn) + else: + out = open(fn).read() + + # load raw json + fact = 'loading %s' % fact_base + try: + fact = json.loads(out) + except ValueError, e: + # load raw ini + cp = ConfigParser.ConfigParser() + try: + cp.readfp(StringIO.StringIO(out)) + except ConfigParser.Error, e: + fact="error loading fact - please check content" + else: + fact = {} + #print cp.sections() + for sect in cp.sections(): + if sect not in fact: + fact[sect] = {} + for opt in cp.options(sect): + val = cp.get(sect, opt) + fact[sect][opt]=val + + local[fact_base] = fact + if not local: + return + self.facts['local'] = local + # platform.dist() is deprecated in 2.6 # in 2.6 and newer, you should use platform.linux_distribution() def get_distribution_facts(self): @@ -2044,6 +2102,7 @@ def main(): module = AnsibleModule( argument_spec = dict( filter=dict(default="*", required=False), + fact_path=dict(default='/etc/ansible/facts.d', required=False), ), supports_check_mode = True, )