Merge pull request #3228 from skvidal/facts.d

first cut and docs for facts.d mechanism for setup module
This commit is contained in:
Michael DeHaan 2013-06-16 19:46:02 -07:00
commit 1ea46e814d

View file

@ -30,6 +30,9 @@ import struct
import datetime import datetime
import getpass import getpass
import subprocess import subprocess
import ConfigParser
import StringIO
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
@ -42,6 +45,15 @@ options:
- if supplied, only return facts that match this shell-style (fnmatch) wildcard. - if supplied, only return facts that match this shell-style (fnmatch) wildcard.
required: false required: false
default: '*' 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: description:
- This module is automatically called by playbooks to gather useful - This module is automatically called by playbooks to gather useful
variables about remote hosts that can be used in playbooks. It can also be 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_lsb_facts()
self.get_date_time_facts() self.get_date_time_facts()
self.get_user_facts() self.get_user_facts()
self.get_local_facts()
def populate(self): def populate(self):
return self.facts return self.facts
@ -169,6 +182,51 @@ class Facts(object):
self.facts['architecture'] = data[0] 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 # platform.dist() is deprecated in 2.6
# in 2.6 and newer, you should use platform.linux_distribution() # in 2.6 and newer, you should use platform.linux_distribution()
def get_distribution_facts(self): def get_distribution_facts(self):
@ -2044,6 +2102,7 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(
filter=dict(default="*", required=False), filter=dict(default="*", required=False),
fact_path=dict(default='/etc/ansible/facts.d', required=False),
), ),
supports_check_mode = True, supports_check_mode = True,
) )