Make ohai and facter work via module_utils Fact classes rather than in the setup module
This commit is contained in:
parent
5a1e35224b
commit
512825455e
9 changed files with 135 additions and 104 deletions
|
@ -71,7 +71,7 @@ Facts
|
|||
Facts are simply things that are discovered about remote nodes. While they can be used in playbooks and templates just like variables, facts
|
||||
are things that are inferred, rather than set. Facts are automatically discovered by Ansible when running plays by executing the internal 'setup'
|
||||
module on the remote nodes. You never have to call the setup module explicitly, it just runs, but it can be disabled to save time if it is
|
||||
not needed or to reduce to a subset. For the convenience of users who are switching from other configuration management systems, the fact module will also pull in facts from the 'ohai' and 'facter' tools if they are installed, which are fact libraries from Chef and Puppet, respectively. You can also ignore them and save time at runtime execution.
|
||||
not needed or you can tell ansible to collect only a subset of the full facts via the `gather_subset:` option. For the convenience of users who are switching from other configuration management systems, the fact module will also pull in facts from the 'ohai' and 'facter' tools if they are installed, which are fact libraries from Chef and Puppet, respectively. (These may also be disabled via `gather_subset:`)
|
||||
|
||||
Filter Plugin
|
||||
+++++++++++++
|
||||
|
@ -398,7 +398,7 @@ An optional conditional statement attached to a task that is used to determine i
|
|||
Van Halen
|
||||
+++++++++
|
||||
|
||||
For no particular reason, other than the fact that Michael really likes them, all Ansible releases are codenamed after Van Halen songs. There is no preference given to David Lee Roth vs. Sammy Lee Hagar-era songs, and instrumentals are also allowed. It is unlikely that there will ever be a Jump release, but a Van Halen III codename release is possible. You never know.
|
||||
For no particular reason, other than the fact that Michael really likes them, all Ansible 0.x and 1.x releases are codenamed after Van Halen songs. There is no preference given to David Lee Roth vs. Sammy Lee Hagar-era songs, and instrumentals are also allowed. It is unlikely that there will ever be a Jump release, but a Van Halen III codename release is possible. You never know.
|
||||
|
||||
Vars (Variables)
|
||||
++++++++++++++++
|
||||
|
|
|
@ -355,22 +355,29 @@ This option can be useful for those wishing to save fact gathering time. Both 's
|
|||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
You can specify a subset of gathered facts using the following options::
|
||||
You can specify a subset of gathered facts using the following option::
|
||||
|
||||
gather_subset = all
|
||||
|
||||
:all: gather all subsets
|
||||
:min: gather a very limited set of facts
|
||||
:network: gather min and network facts
|
||||
:hardware: gather min and hardware facts (longest facts to retrieve)
|
||||
:virtual: gather min and virtual facts
|
||||
:all: gather all subsets (the default)
|
||||
:network: gather network facts
|
||||
:hardware: gather hardware facts (longest facts to retrieve)
|
||||
:virtual: gather facts about virtual machines hosted on the machine
|
||||
:ohai: gather facts from ohai
|
||||
:facter: gather facts from facter
|
||||
|
||||
You can combine them using comma separated list (ex: min,network,virtual)
|
||||
You can combine them using a comma separated list (ex: network,virtual,facter)
|
||||
|
||||
You can also disable puppet facter or chef ohai facts collection using following options::
|
||||
You can also disable specific subsets by prepending with a `!` like this::
|
||||
|
||||
ignore_ohai = True
|
||||
ignore_facter = True
|
||||
# Don't gather hardware facts, facts from chef's ohai or puppet's facter
|
||||
gather_subset = !hardware,!ohai,!facter
|
||||
|
||||
A set of basic facts are always collected no matter which additional subsets
|
||||
are selected. If you want to collect the minimal amount of facts, use
|
||||
`!all`::
|
||||
|
||||
gather_subset = !all
|
||||
|
||||
hash_behaviour
|
||||
==============
|
||||
|
|
|
@ -33,19 +33,16 @@
|
|||
|
||||
# by default retrieve all facts subsets
|
||||
# all - gather all subsets
|
||||
# min - gather a very limited set of facts
|
||||
# network - gather min and network facts
|
||||
# hardware - gather hardware facts (longest facts to retrieve)
|
||||
# virtual - gather min and virtual facts
|
||||
# You can combine them using comma (ex: min,network,virtual)
|
||||
# facter - import facts from facter
|
||||
# ohai - import facts from ohai
|
||||
# You can combine them using comma (ex: network,virtual)
|
||||
# You can negate them using ! (ex: !hardware,!facter,!ohai)
|
||||
# A minimal set of facts is always gathered.
|
||||
#gather_subset = all
|
||||
|
||||
# by default run ohai
|
||||
#ignore_ohai = False
|
||||
|
||||
# by default run facter
|
||||
#ignore_facter = False
|
||||
|
||||
# additional paths to search for roles in, colon separated
|
||||
#roles_path = /etc/ansible/roles
|
||||
|
||||
|
|
|
@ -157,8 +157,6 @@ DEFAULT_JINJA2_EXTENSIONS = get_config(p, DEFAULTS, 'jinja2_extensions', 'ANSIBL
|
|||
DEFAULT_EXECUTABLE = get_config(p, DEFAULTS, 'executable', 'ANSIBLE_EXECUTABLE', '/bin/sh')
|
||||
DEFAULT_GATHERING = get_config(p, DEFAULTS, 'gathering', 'ANSIBLE_GATHERING', 'implicit').lower()
|
||||
DEFAULT_GATHER_SUBSET = get_config(p, DEFAULTS, 'gather_subset', 'ANSIBLE_GATHER_SUBSET', 'all').lower()
|
||||
DEFAULT_IGNORE_OHAI = get_config(p, DEFAULTS, 'ignore_ohai', 'ANSIBLE_IGNORE_OHAI', False, boolean=True)
|
||||
DEFAULT_IGNORE_FACTER = get_config(p, DEFAULTS, 'ignore_facter', 'ANSIBLE_IGNORE_FACTER', False, boolean=True)
|
||||
DEFAULT_LOG_PATH = get_config(p, DEFAULTS, 'log_path', 'ANSIBLE_LOG_PATH', '', ispath=True)
|
||||
DEFAULT_FORCE_HANDLERS = get_config(p, DEFAULTS, 'force_handlers', 'ANSIBLE_FORCE_HANDLERS', False, boolean=True)
|
||||
DEFAULT_INVENTORY_IGNORE = get_config(p, DEFAULTS, 'inventory_ignore_extensions', 'ANSIBLE_INVENTORY_IGNORE', ["~", ".orig", ".bak", ".ini", ".cfg", ".retry", ".pyc", ".pyo"], islist=True)
|
||||
|
|
|
@ -153,18 +153,10 @@ class PlayIterator:
|
|||
|
||||
# Default options to gather
|
||||
gather_subset = C.DEFAULT_GATHER_SUBSET
|
||||
ignore_ohai = C.DEFAULT_IGNORE_OHAI
|
||||
ignore_facter = C.DEFAULT_IGNORE_FACTER
|
||||
|
||||
# Retrieve subset to gather
|
||||
if self._play.gather_subset is not None:
|
||||
gather_subset = self._play.gather_subset
|
||||
# ignore ohai
|
||||
if self._play.ignore_ohai is not None:
|
||||
ignore_ohai = self._play.ignore_ohai
|
||||
# ignore puppet facter
|
||||
if self._play.ignore_facter is not None:
|
||||
ignore_facter = self._play.ignore_facter
|
||||
|
||||
setup_block = Block(play=self._play)
|
||||
setup_task = Task(block=setup_block)
|
||||
|
@ -172,8 +164,6 @@ class PlayIterator:
|
|||
setup_task.tags = ['always']
|
||||
setup_task.args = {
|
||||
'gather_subset': gather_subset,
|
||||
'ignore_ohai' : ignore_ohai,
|
||||
'ignore_facter': ignore_facter,
|
||||
}
|
||||
setup_task.set_loader(self._play._loader)
|
||||
setup_block.block = [setup_task]
|
||||
|
|
|
@ -163,7 +163,10 @@ class Facts(object):
|
|||
|
||||
self.module = module
|
||||
self.facts = {}
|
||||
|
||||
### TODO: Eventually, these should all get moved to populate(). But
|
||||
# some of the values are currently being used by other subclasses (for
|
||||
# instance, os_family and distribution). Have to sort out what to do
|
||||
# about those first.
|
||||
if load_on_init:
|
||||
self.get_platform_facts()
|
||||
self.get_distribution_facts()
|
||||
|
@ -2981,6 +2984,52 @@ class SunOSVirtual(Virtual):
|
|||
except ValueError:
|
||||
pass
|
||||
|
||||
class Ohai(Facts):
|
||||
"""
|
||||
This is a subclass of Facts for including information gathered from Ohai.
|
||||
"""
|
||||
|
||||
def populate(self):
|
||||
self.run_ohai()
|
||||
return self.facts
|
||||
|
||||
def run_ohai(self):
|
||||
ohai_path = self.module.get_bin_path('ohai')
|
||||
if ohai_path is None:
|
||||
return
|
||||
rc, out, err = self.module.run_command(ohai_path)
|
||||
try:
|
||||
self.facts.update(json.loads(out))
|
||||
except:
|
||||
pass
|
||||
|
||||
class Facter(Facts):
|
||||
"""
|
||||
This is a subclass of Facts for including information gathered from Facter.
|
||||
"""
|
||||
def populate(self):
|
||||
self.run_facter()
|
||||
return self.facts
|
||||
|
||||
def run_facter(self):
|
||||
facter_path = self.module.get_bin_path('facter', opt_dirs=['/opt/puppetlabs/bin'])
|
||||
cfacter_path = self.module.get_bin_path('cfacter', opt_dirs=['/opt/puppetlabs/bin'])
|
||||
# Prefer to use cfacter if available
|
||||
if cfacter_path is not None:
|
||||
facter_path = cfacter_path
|
||||
|
||||
if facter_path is None:
|
||||
return
|
||||
|
||||
# if facter is installed, and we can use --json because
|
||||
# ruby-json is ALSO installed, include facter data in the JSON
|
||||
rc, out, err = self.module.run_command(facter_path + " --puppet --json")
|
||||
try:
|
||||
self.facts = json.loads(out)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def get_file_content(path, default=None, strip=True):
|
||||
data = default
|
||||
if os.path.exists(path) and os.access(path, os.R_OK):
|
||||
|
@ -3009,76 +3058,70 @@ def get_file_lines(path):
|
|||
ret = []
|
||||
return ret
|
||||
|
||||
def ansible_facts(module):
|
||||
# Retrieve module parameters
|
||||
gather_subset = ('all',)
|
||||
if 'gather_subset' in module.params:
|
||||
gather_subset = module.params['gather_subset']
|
||||
|
||||
# Retrieve all facts elements
|
||||
if 'all' in gather_subset:
|
||||
gather_subset = FACT_SUBSETS.keys()
|
||||
else:
|
||||
# Check subsets and forbid unallowed name
|
||||
for subset in gather_subset:
|
||||
if subset not in FACT_SUBSETS.keys():
|
||||
raise TypeError("Bad subset '%s' given to Ansible. gather_subset options allowed: all, %s" % (subset, ", ".join(FACT_SUBSETS.keys())))
|
||||
|
||||
def ansible_facts(module, gather_subset):
|
||||
facts = {}
|
||||
facts['gather_subset'] = gather_subset
|
||||
facts['gather_subset'] = list(gather_subset)
|
||||
facts.update(Facts(module).populate())
|
||||
for subset in gather_subset:
|
||||
facts.update(FACT_SUBSETS[subset](module).populate())
|
||||
return facts
|
||||
|
||||
# ===========================================
|
||||
# TODO: remove this dead code?
|
||||
def get_all_facts(module):
|
||||
|
||||
setup_options = dict(module_setup=True)
|
||||
facts = ansible_facts(module)
|
||||
|
||||
# Retrieve module parameters
|
||||
gather_subset = module.params['gather_subset']
|
||||
|
||||
# Retrieve all facts elements
|
||||
additional_subsets = set()
|
||||
exclude_subsets = set()
|
||||
for subset in gather_subset:
|
||||
if subset == 'all':
|
||||
additional_subsets.update(VALID_SUBSETS)
|
||||
continue
|
||||
if subset.startswith('!'):
|
||||
subset = subset[1:]
|
||||
if subset == 'all':
|
||||
exclude_subsets.update(VALID_SUBSETS)
|
||||
continue
|
||||
exclude = True
|
||||
else:
|
||||
exclude = False
|
||||
|
||||
if subset not in VALID_SUBSETS:
|
||||
raise TypeError("Bad subset '%s' given to Ansible. gather_subset options allowed: all, %s" % (subset, ", ".join(FACT_SUBSETS.keys())))
|
||||
|
||||
if exclude:
|
||||
exclude_subsets.add(subset)
|
||||
else:
|
||||
additional_subsets.add(subset)
|
||||
|
||||
if not additional_subsets:
|
||||
additional_subsets.update(VALID_SUBSETS)
|
||||
|
||||
additional_subsets.difference_update(exclude_subsets)
|
||||
|
||||
# facter and ohai are given a different prefix than other subsets
|
||||
if 'facter' in additional_subsets:
|
||||
additional_subsets.difference_update(('facter',))
|
||||
facter_ds = FACT_SUBSETS['facter'](module, load_on_init=False).populate()
|
||||
if facter_ds:
|
||||
for (k, v) in facter_ds.items():
|
||||
setup_options['facter_%s' % k.replace('-', '_')] = v
|
||||
|
||||
if 'ohai' in additional_subsets:
|
||||
additional_subsets.difference_update(('ohai',))
|
||||
ohai_ds = FACT_SUBSETS['ohai'](module, load_on_init=False).populate()
|
||||
if ohai_ds:
|
||||
for (k, v) in ohai_ds.items():
|
||||
setup_options['ohai_%s' % k.replace('-', '_')] = v
|
||||
|
||||
facts = ansible_facts(module, additional_subsets)
|
||||
|
||||
for (k, v) in facts.items():
|
||||
setup_options["ansible_%s" % k.replace('-', '_')] = v
|
||||
|
||||
# Look for the path to the facter, cfacter, and ohai binaries and set
|
||||
# the variable to that path.
|
||||
|
||||
facter_path = module.get_bin_path('facter')
|
||||
cfacter_path = module.get_bin_path('cfacter')
|
||||
ohai_path = module.get_bin_path('ohai')
|
||||
|
||||
# Prefer to use cfacter if available
|
||||
if cfacter_path is not None:
|
||||
facter_path = cfacter_path
|
||||
# if facter is installed, and we can use --json because
|
||||
# ruby-json is ALSO installed, include facter data in the JSON
|
||||
|
||||
if facter_path is not None:
|
||||
rc, out, err = module.run_command(facter_path + " --json")
|
||||
facter = True
|
||||
try:
|
||||
facter_ds = json.loads(out)
|
||||
except:
|
||||
facter = False
|
||||
if facter:
|
||||
for (k,v) in facter_ds.items():
|
||||
setup_options["facter_%s" % k] = v
|
||||
|
||||
# ditto for ohai
|
||||
|
||||
if ohai_path is not None:
|
||||
rc, out, err = module.run_command(ohai_path)
|
||||
ohai = True
|
||||
try:
|
||||
ohai_ds = json.loads(out)
|
||||
except:
|
||||
ohai = False
|
||||
if ohai:
|
||||
for (k,v) in ohai_ds.items():
|
||||
k2 = "ohai_%s" % k.replace('-', '_')
|
||||
setup_options[k2] = v
|
||||
|
||||
setup_result = { 'ansible_facts': {} }
|
||||
|
||||
for (k,v) in setup_options.items():
|
||||
|
@ -3090,10 +3133,13 @@ def get_all_facts(module):
|
|||
|
||||
return setup_result
|
||||
|
||||
### Note: have to define this at the bottom as it references classes defined earlier in this file
|
||||
# Allowed fact subset for gather_subset options and what classes they use
|
||||
# Note: have to define this at the bottom as it references classes defined earlier in this file
|
||||
FACT_SUBSETS = dict(
|
||||
hardware=Hardware,
|
||||
network=Network,
|
||||
virtual=Virtual,
|
||||
ohai=Ohai,
|
||||
facter=Facter,
|
||||
)
|
||||
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
|
||||
|
|
|
@ -65,8 +65,6 @@ class Play(Base, Taggable, Become):
|
|||
# Connection
|
||||
_gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True)
|
||||
_gather_subset = FieldAttribute(isa='list', default=None, always_post_validate=True)
|
||||
_ignore_facter = FieldAttribute(isa='bool', default=None, always_post_validate=True)
|
||||
_ignore_ohai = FieldAttribute(isa='bool', default=None, always_post_validate=True)
|
||||
_hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True)
|
||||
_name = FieldAttribute(isa='string', default='', always_post_validate=True)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ VAULT_PASSWORD_FILE = vault-password
|
|||
CONSUL_RUNNING := $(shell python consul_running.py)
|
||||
EUID := $(shell id -u -r)
|
||||
|
||||
all: setup test_test_infra parsing test_var_precedence unicode test_templating_settings environment non_destructive destructive includes blocks pull check_mode test_hash test_handlers test_group_by test_vault test_tags test_lookup_paths no_log test_connection
|
||||
all: setup test_test_infra parsing test_var_precedence unicode test_templating_settings environment non_destructive destructive includes blocks pull check_mode test_hash test_handlers test_group_by test_vault test_tags test_lookup_paths no_log test_connection test_gathering_facts
|
||||
|
||||
test_test_infra:
|
||||
[ "$$(ansible-playbook -i $(INVENTORY) test_test_infra.yml -e @$(VARS_FILE) $(CREDENTIALS_ARG) $(TEST_FLAGS) | fgrep works | xargs)" = "msg: fail works (True) msg: assert works (True)" ]
|
||||
|
@ -70,6 +70,9 @@ unicode: setup
|
|||
test_templating_settings: setup
|
||||
ansible-playbook test_templating_settings.yml -i $(INVENTORY) -e outputdir=$(TEST_DIR) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -v $(TEST_FLAGS)
|
||||
|
||||
test_gathering_facts: setup
|
||||
ansible-playbook test_gathering_facts.yml -i $(INVENTORY) -e outputdir=$(TEST_DIR) -e @$(VARS_FILE) -v $(TEST_FLAGS)
|
||||
|
||||
environment: setup
|
||||
ansible-playbook test_environment.yml -i $(INVENTORY) -e outputdir=$(TEST_DIR) -e @$(VARS_FILE) $(CREDENTIALS_ARG) $(TEST_FLAGS)
|
||||
|
||||
|
|
|
@ -3,20 +3,16 @@
|
|||
- hosts: localhost
|
||||
tags: [ 'min' ]
|
||||
connection: local
|
||||
gather_subset: "min"
|
||||
ignore_facter: yes
|
||||
ignore_ohai: yes
|
||||
gather_subset: "!all"
|
||||
gather_facts: yes
|
||||
tasks:
|
||||
- debug: var={{item}}
|
||||
with_items: [ 'ansible_user_id', 'ansible_interfaces', 'ansible_mounts', 'ansible_virtualization_role' ]
|
||||
with_items: [ 'ansible_user_id', 'ansible_interfaces', 'ansible_mounts', 'ansible_virtualization_role' ]
|
||||
|
||||
- hosts: localhost
|
||||
tags: [ 'network' ]
|
||||
connection: local
|
||||
gather_subset: "network"
|
||||
ignore_facter: yes
|
||||
ignore_ohai: yes
|
||||
gather_facts: yes
|
||||
tasks:
|
||||
- debug: var={{item}}
|
||||
|
@ -26,8 +22,6 @@
|
|||
tags: [ 'hardware' ]
|
||||
connection: local
|
||||
gather_subset: "hardware"
|
||||
ignore_facter: yes
|
||||
ignore_ohai: yes
|
||||
gather_facts: yes
|
||||
tasks:
|
||||
- debug: var={{item}}
|
||||
|
@ -37,8 +31,6 @@
|
|||
tags: [ 'virtual' ]
|
||||
connection: local
|
||||
gather_subset: "virtual"
|
||||
ignore_facter: yes
|
||||
ignore_ohai: yes
|
||||
gather_facts: yes
|
||||
tasks:
|
||||
- debug: var={{item}}
|
||||
|
|
Loading…
Reference in a new issue