def get_facts(
    state, name,
    args=None, sudo=False, sudo_user=None
):

    sudo = sudo or state.config.SUDO
    sudo_user = sudo_user or state.config.SUDO_USER
    ignore_errors = state.config.IGNORE_ERRORS

    if state.current_op_meta:
        sudo, sudo_user, ignore_errors = state.current_op_meta

    # Create an instance of the fact
    fact = FACTS[name]()

    # If we're inactive or  (pipelining & inside an op): just return the defaults
    if not state.active or (state.pipelining and state.in_op):
        return {
            host.name: fact.default
            for host in state.inventory
        }

    command = fact.command

    if args:
        command = command(*args)

    # Make a hash which keeps facts unique - but usable cross-deploy/threads. Locks are
    # used to maintain order.
    fact_hash = make_hash((name, command, sudo, sudo_user))

    # Lock!
    state.fact_locks.setdefault(fact_hash, Semaphore()).acquire()

    # Already got this fact? Unlock and return 'em
    if state.facts.get(fact_hash):
        state.fact_locks[fact_hash].release()
        return state.facts[fact_hash]

    # Execute the command for each state inventory in a greenlet
    greenlets = {
        host.name: state.pool.spawn(
            run_shell_command, state, host.name, command,
            sudo=sudo, sudo_user=sudo_user,
            print_output=state.print_fact_output
        )
        for host in state.inventory
    }

    hostname_facts = {}
    failed_hosts = set()

    # Collect the facts and any failures
    for hostname, greenlet in six.iteritems(greenlets):
        try:
            channel, stdout, stderr = greenlet.get()

            if stdout:
                data = fact.process(stdout)
            else:
                data = fact.default

            hostname_facts[hostname] = data

        except (timeout_error, SSHException):

            if ignore_errors:
                logger.warning('[{0}] {1}'.format(
                    hostname,
                    colored('Fact error (ignored)', 'yellow')
                ))
            else:
                failed_hosts.add(hostname)
                logger.error('[{0}] {1}'.format(
                    hostname,
                    colored('Fact error', 'red')
                ))

    log_name = colored(name, attrs=['bold'])

    if args:
        log = 'Loaded fact {0}: {1}'.format(log_name, args)
    else:
        log = 'Loaded fact {0}'.format(log_name)

    if state.print_fact_info:
        logger.info(log)
    else:
        logger.debug(log)

    # Check we've not failed
    if not ignore_errors:
        state.fail_hosts(failed_hosts)

    # Assign the facts
    state.facts[fact_hash] = hostname_facts

    # Release the lock, return the data
    state.fact_locks[fact_hash].release()
    return state.facts[fact_hash]
Get a single fact for all hosts in the state.
dataset/ETHPy150Open Fizzadar/pyinfra/pyinfra/api/facts.py/get_facts