1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3 4# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com> 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import absolute_import, division, print_function 8__metaclass__ = type 9 10 11DOCUMENTATION = ''' 12--- 13module: setup 14version_added: historical 15short_description: Gathers facts about remote hosts 16options: 17 gather_subset: 18 version_added: "2.1" 19 description: 20 - "If supplied, restrict the additional facts collected to the given subset. 21 Possible values: C(all), C(min), C(hardware), C(network), C(virtual), C(ohai), and 22 C(facter). Can specify a list of values to specify a larger subset. 23 Values can also be used with an initial C(!) to specify that 24 that specific subset should not be collected. For instance: 25 C(!hardware,!network,!virtual,!ohai,!facter). If C(!all) is specified 26 then only the min subset is collected. To avoid collecting even the 27 min subset, specify C(!all,!min). To collect only specific facts, 28 use C(!all,!min), and specify the particular fact subsets. 29 Use the filter parameter if you do not want to display some collected 30 facts." 31 default: "all" 32 gather_timeout: 33 version_added: "2.2" 34 description: 35 - Set the default timeout in seconds for individual fact gathering. 36 default: 10 37 filter: 38 version_added: "1.1" 39 description: 40 - If supplied, only return facts that match this shell-style (fnmatch) wildcard. 41 default: "*" 42 fact_path: 43 version_added: "1.3" 44 description: 45 - Path used for local ansible facts (C(*.fact)) - files in this dir 46 will be run (if executable) and their results be added to C(ansible_local) facts. 47 If a file is not executable it is read instead. 48 File/results format can be JSON or INI-format. The default C(fact_path) can be 49 specified in C(ansible.cfg) for when setup is automatically called as part of 50 C(gather_facts). 51 NOTE - For windows clients, the results will be added to a variable named after the 52 local file (without extension suffix), rather than C(ansible_local). 53 - Since Ansible 2.1, Windows hosts can use C(fact_path). Make sure that this path 54 exists on the target host. Files in this path MUST be PowerShell scripts C(.ps1) 55 which outputs an object. This object will be formatted by Ansible as json so the 56 script should be outputting a raw hashtable, array, or other primitive object. 57 default: /usr/local/etc/ansible/facts.d 58description: 59 - This module is automatically called by playbooks to gather useful 60 variables about remote hosts that can be used in playbooks. It can also be 61 executed directly by C(/usr/bin/ansible) to check what variables are 62 available to a host. Ansible provides many I(facts) about the system, 63 automatically. 64 - This module is also supported for Windows targets. 65notes: 66 - More ansible facts will be added with successive releases. If I(facter) or 67 I(ohai) are installed, variables from these programs will also be snapshotted 68 into the JSON file for usage in templating. These variables are prefixed 69 with C(facter_) and C(ohai_) so it's easy to tell their source. All variables are 70 bubbled up to the caller. Using the ansible facts and choosing to not 71 install I(facter) and I(ohai) means you can avoid Ruby-dependencies on your 72 remote systems. (See also M(community.general.facter) and M(community.general.ohai).) 73 - The filter option filters only the first level subkey below ansible_facts. 74 - If the target host is Windows, you will not currently have the ability to use 75 C(filter) as this is provided by a simpler implementation of the module. 76 - This module is also supported for Windows targets. 77 - This module should be run with elevated privileges on BSD systems to gather facts like ansible_product_version. 78 - Supports C(check_mode). 79author: 80 - "Ansible Core Team" 81 - "Michael DeHaan" 82''' 83 84EXAMPLES = """ 85# Display facts from all hosts and store them indexed by I(hostname) at C(/tmp/facts). 86# ansible all -m ansible.builtin.setup --tree /tmp/facts 87 88# Display only facts regarding memory found by ansible on all hosts and output them. 89# ansible all -m ansible.builtin.setup -a 'filter=ansible_*_mb' 90 91# Display only facts returned by facter. 92# ansible all -m ansible.builtin.setup -a 'filter=facter_*' 93 94# Collect only facts returned by facter. 95# ansible all -m ansible.builtin.setup -a 'gather_subset=!all,!any,facter' 96 97- name: Collect only facts returned by facter 98 ansible.builtin.setup: 99 gather_subset: 100 - '!all' 101 - '!any' 102 - facter 103 104# Display only facts about certain interfaces. 105# ansible all -m ansible.builtin.setup -a 'filter=ansible_eth[0-2]' 106 107# Restrict additional gathered facts to network and virtual (includes default minimum facts) 108# ansible all -m ansible.builtin.setup -a 'gather_subset=network,virtual' 109 110# Collect only network and virtual (excludes default minimum facts) 111# ansible all -m ansible.builtin.setup -a 'gather_subset=!all,!any,network,virtual' 112 113# Do not call puppet facter or ohai even if present. 114# ansible all -m ansible.builtin.setup -a 'gather_subset=!facter,!ohai' 115 116# Only collect the default minimum amount of facts: 117# ansible all -m ansible.builtin.setup -a 'gather_subset=!all' 118 119# Collect no facts, even the default minimum subset of facts: 120# ansible all -m ansible.builtin.setup -a 'gather_subset=!all,!min' 121 122# Display facts from Windows hosts with custom facts stored in C(C:\\custom_facts). 123# ansible windows -m ansible.builtin.setup -a "fact_path='c:\\custom_facts'" 124""" 125 126# import module snippets 127from ..module_utils.basic import AnsibleModule 128 129from ansible.module_utils._text import to_text 130from ansible.module_utils.facts import ansible_collector, default_collectors 131from ansible.module_utils.facts.collector import CollectorNotFoundError, CycleFoundInFactDeps, UnresolvedFactDep 132from ansible.module_utils.facts.namespace import PrefixFactNamespace 133 134 135def main(): 136 module = AnsibleModule( 137 argument_spec=dict( 138 gather_subset=dict(default=["all"], required=False, type='list'), 139 gather_timeout=dict(default=10, required=False, type='int'), 140 filter=dict(default="*", required=False), 141 fact_path=dict(default='/usr/local/etc/ansible/facts.d', required=False, type='path'), 142 ), 143 supports_check_mode=True, 144 ) 145 146 gather_subset = module.params['gather_subset'] 147 gather_timeout = module.params['gather_timeout'] 148 filter_spec = module.params['filter'] 149 150 # TODO: this mimics existing behavior where gather_subset=["!all"] actually means 151 # to collect nothing except for the below list 152 # TODO: decide what '!all' means, I lean towards making it mean none, but likely needs 153 # some tweaking on how gather_subset operations are performed 154 minimal_gather_subset = frozenset(['apparmor', 'caps', 'cmdline', 'date_time', 155 'distribution', 'dns', 'env', 'fips', 'local', 156 'lsb', 'pkg_mgr', 'platform', 'python', 'selinux', 157 'service_mgr', 'ssh_pub_keys', 'user']) 158 159 all_collector_classes = default_collectors.collectors 160 161 # rename namespace_name to root_key? 162 namespace = PrefixFactNamespace(namespace_name='ansible', 163 prefix='ansible_') 164 165 try: 166 fact_collector = ansible_collector.get_ansible_collector(all_collector_classes=all_collector_classes, 167 namespace=namespace, 168 filter_spec=filter_spec, 169 gather_subset=gather_subset, 170 gather_timeout=gather_timeout, 171 minimal_gather_subset=minimal_gather_subset) 172 except (TypeError, CollectorNotFoundError, CycleFoundInFactDeps, UnresolvedFactDep) as e: 173 # bad subset given, collector, idk, deps declared but not found 174 module.fail_json(msg=to_text(e)) 175 176 facts_dict = fact_collector.collect(module=module) 177 178 module.exit_json(ansible_facts=facts_dict) 179 180 181if __name__ == '__main__': 182 main() 183