prefer ansible_facts namespace and dict notation (#44980)

* prefer ansible_facts namespace and dict notation

* fixed mistranslation
pull/45290/merge
Brian Coca 6 years ago committed by Alicia Cozine
parent 0d81386144
commit 44510448b0

@ -394,11 +394,12 @@ This makes a dynamic group of hosts matching certain criteria, even if that grou
---
# talk to all hosts just so we can learn about them
- hosts: all
- name: talk to all hosts just so we can learn about them
hosts: all
tasks:
- group_by:
key: os_{{ ansible_distribution }}
- name: Classify hosts depending on their OS distribution
group_by:
key: os_{{ ansible_facts['distribution'] }}
# now just on the CentOS hosts...
@ -426,7 +427,8 @@ Alternatively, if only variables are needed::
- hosts: all
tasks:
- include_vars: "os_{{ ansible_distribution }}.yml"
- name: Set OS distribution dependant variables
include_vars: "os_{{ ansible_facts['distribution'] }}.yml"
- debug:
var: asdf

@ -25,7 +25,7 @@ Blocks allow for logical grouping of tasks and in play error handling. Most of w
name: bar
state: started
enabled: True
when: ansible_distribution == 'CentOS'
when: ansible_facts['distribution'] == 'CentOS'
become: true
become_user: root

@ -28,17 +28,16 @@ It's actually pretty simple::
tasks:
- name: "shut down Debian flavored systems"
command: /sbin/shutdown -t now
when: ansible_os_family == "Debian"
# note that Ansible facts and vars like ansible_os_family can be used
# directly in conditionals without double curly braces
when: ansible_facts['os_family'] == "Debian"
# note that all variables can be directly in conditionals without double curly braces
You can also use parentheses to group conditions::
tasks:
- name: "shut down CentOS 6 and Debian 7 systems"
command: /sbin/shutdown -t now
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or
(ansible_distribution == "Debian" and ansible_distribution_major_version == "7")
when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
(ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")
Multiple conditions that all need to be true (a logical 'and') can also be specified as a list::
@ -46,8 +45,8 @@ Multiple conditions that all need to be true (a logical 'and') can also be speci
- name: "shut down CentOS 6 systems"
command: /sbin/shutdown -t now
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "6"
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"
A number of Jinja2 "tests" and "filters" can also be used in when statements, some of which are unique
and provided by Ansible. Suppose we want to ignore the error of one statement and then
@ -72,17 +71,18 @@ decide to do something conditionally based on success or failure::
.. note:: both `success` and `succeeded` work (`fail`/`failed`, etc).
As a reminder, to see what facts are available on a particular system, you can do the following::
To see what facts are available on a particular system, you can do the following in a playbook::
- debug: var=ansible_facts
ansible hostname.example.com -m setup
Tip: Sometimes you'll get back a variable that's a string and you'll want to do a math operation comparison on it. You can do this like so::
tasks:
- shell: echo "only on Red Hat 6, derivatives, and later"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release']|int >= 6
.. note:: the above example requires the lsb_release package on the target host in order to return the ansible_lsb.major_release fact.
.. note:: the above example requires the lsb_release package on the target host in order to return the 'lsb major_release' fact.
Variables defined in the playbooks or inventory can also be used. An example may be the execution of a task based on a variable's boolean value::
@ -170,7 +170,7 @@ Or with a role::
- hosts: webservers
roles:
- role: debian_stock_config
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'
You will note a lot of 'skipped' output by default in Ansible when using this approach on systems that don't match the criteria.
In many cases the ``group_by`` module (see :doc:`modules`) can be a more streamlined way to accomplish the same thing; see
@ -224,13 +224,13 @@ but it is easily handled with a minimum of syntax in an Ansible Playbook::
remote_user: root
vars_files:
- "vars/common.yml"
- [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ]
- [ "vars/{{ ansible_facts['os_family'] }}.yml", "vars/os_defaults.yml" ]
tasks:
- name: make sure apache is started
service: name={{ apache }} state=started
.. note::
The variable 'ansible_os_family' is being interpolated into
The variable "ansible_facts['os_family']" is being interpolated into
the list of filenames being defined for vars_files.
As a reminder, the various YAML files contain just keys and values::
@ -267,7 +267,7 @@ The following example shows how to template out a configuration file that was ve
loop: "{{ query('first_found', { 'files': myfiles, 'paths': mypaths}) }}"
vars:
myfiles:
- "{{ansible_distribution}}.conf"
- "{{ansible_facts['distribution']}}.conf"
- default.conf
mypaths: ['search_location_one/somedir/', '/opt/other_location/somedir/']
@ -338,10 +338,10 @@ The following Facts are frequently used in Conditionals - see above for examples
.. _ansible_distribution:
ansible_distribution
--------------------
ansible_facts['distribution']
-----------------------------
Possible values::
Possible values (sample, not complete list)::
Alpine
Altlinux
@ -366,17 +366,17 @@ Possible values::
.. _ansible_distribution_major_version:
ansible_distribution_major_version
----------------------------------
ansible_facts['distribution_major_version']
-------------------------------------------
This will be the major version of the operating system. For example, the value will be `16` for Ubuntu 16.04.
.. _ansible_os_family:
ansible_os_family
-----------------
ansible_facts['os_family']
--------------------------
Possible values::
Possible values (sample, not complete list)::
AIX
Alpine

@ -46,9 +46,9 @@ Other YAML files may be included in certain directories. For example, it is comm
# roles/example/tasks/main.yml
- name: added in 2.4, previously you used 'include'
import_tasks: redhat.yml
when: ansible_os_family|lower == 'redhat'
when: ansible_facts['os_family']|lower == 'redhat'
- import_tasks: debian.yml
when: ansible_os_family|lower == 'debian'
when: ansible_facts['os_family']|lower == 'debian'
# roles/example/tasks/redhat.yml
- yum:
@ -163,7 +163,7 @@ You can conditionally import a role and execute it's tasks::
tasks:
- include_role:
name: some_role
when: "ansible_os_family == 'RedHat'"
when: "ansible_facts['os_family'] == 'RedHat'"

@ -43,7 +43,7 @@ To match strings against a substring or a regex, use the "match" or "search" fil
url: "http://example.com/users/foo/resources/bar"
tasks:
- debug:
- debug:
msg: "matched pattern 1"
when: url is match("http://example.com/users/.*/resources/.*")
@ -67,14 +67,14 @@ Version Comparison
.. note:: In 2.5 ``version_compare`` was renamed to ``version``
To compare a version number, such as checking if the ``ansible_distribution_version``
To compare a version number, such as checking if the ``ansible_facts['distribution_version']``
version is greater than or equal to '12.04', you can use the ``version`` test.
The ``version`` test can also be used to evaluate the ``ansible_distribution_version``::
The ``version`` test can also be used to evaluate the ``ansible_facts['distribution_version']``::
{{ ansible_distribution_version is version('12.04', '>=') }}
{{ ansible_facts['distribution_version'] is version('12.04', '>=') }}
If ``ansible_distribution_version`` is greater than or equal to 12.04, this test returns True, otherwise False.
If ``ansible_facts['distribution_version']`` is greater than or equal to 12.04, this test returns True, otherwise False.
The ``version`` test accepts the following operators::

@ -161,11 +161,17 @@ Information discovered from systems: Facts
There are other places where variables can come from, but these are a type of variable that are discovered, not set by the user.
Facts are information derived from speaking with your remote systems.
Facts are information derived from speaking with your remote systems. You can find a complete set under the ``ansible_facts`` variable,
most facts are also 'injected' as top level variables preserving the ``ansible_`` prefix, but some are dropped due to conflicts.
This can be disabled via the :ref:INJECT_FACTS_AS_VARS setting.
An example of this might be the IP address of the remote host, or what the operating system is.
To see what information is available, try the following::
To see what information is available, try the following in a play::
- debug: var=ansible_facts
To see the 'raw' information as gathered::
ansible hostname -m setup
@ -406,15 +412,15 @@ This will return a large amount of variable data, which may look like this, as t
In the above the model of the first harddrive may be referenced in a template or playbook as::
{{ ansible_devices.sda.model }}
{{ ansible_facts['devices']['sda']['model'] }}
Similarly, the hostname as the system reports it is::
{{ ansible_nodename }}
{{ ansible_facts['nodename'] }}
and the unqualified hostname shows the string before the first period(.)::
{{ ansible_hostname }}
{{ ansible_facts['hostname'] }}
Facts are frequently used in conditionals (see :doc:`playbooks_conditionals`) and also in templates.
@ -475,11 +481,11 @@ And you will see the following fact added::
And this data can be accessed in a ``template/playbook`` as::
{{ ansible_local.preferences.general.asdf }}
{{ ansible_local['preferences']['general']['asdf'] }}
The local namespace prevents any user supplied fact from overriding system facts or variables defined elsewhere in the playbook.
.. note:: The key part in the key=value pairs will be converted into lowercase inside the ansible_local variable. Using the example above, if the ini file contained ``XYZ=3`` in the ``[general]`` section, then you should expect to access it as: ``{{ ansible_local.preferences.general.xyz }}`` and not ``{{ ansible_local.preferences.general.XYZ }}``. This is because Ansible uses Python's `ConfigParser`_ which passes all option names through the `optionxform`_ method and this method's default implementation converts option names to lower case.
.. note:: The key part in the key=value pairs will be converted into lowercase inside the ansible_local variable. Using the example above, if the ini file contained ``XYZ=3`` in the ``[general]`` section, then you should expect to access it as: ``{{ ansible_local['preferences']['general']['xyz'] }}`` and not ``{{ ansible_local['preferences']['general']['XYZ'] }}``. This is because Ansible uses Python's `ConfigParser`_ which passes all option names through the `optionxform`_ method and this method's default implementation converts option names to lower case.
.. _ConfigParser: https://docs.python.org/2/library/configparser.html
.. _optionxform: https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.optionxform
@ -526,7 +532,7 @@ Fact Caching
As shown elsewhere in the docs, it is possible for one server to reference variables about another, like so::
{{ hostvars['asdf.example.com']['ansible_os_family'] }}
{{ hostvars['asdf.example.com']['ansible_facts']['os_family'] }}
With "Fact Caching" disabled, in order to do this, Ansible must have already talked to 'asdf.example.com' in the
current play, or another play up higher in the playbook. This is the default configuration of ansible.
@ -615,11 +621,11 @@ We already described facts a little higher up in the documentation.
Some provided facts, like networking information, are made available as nested data structures. To access
them a simple ``{{ foo }}`` is not sufficient, but it is still easy to do. Here's how we get an IP address::
{{ ansible_eth0["ipv4"]["address"] }}
{{ ansible_facts["eth0"]["ipv4"]["address"] }}
OR alternatively::
{{ ansible_eth0.ipv4.address }}
{{ ansible_facts.eth0.ipv4.address }}
Similarly, this is how we access the first element of an array::
@ -641,7 +647,7 @@ or set of playbooks, you can still get the variables, but you will not be able t
If your database server wants to use the value of a 'fact' from another node, or an inventory variable
assigned to another node, it's easy to do so within a template or even an action line::
{{ hostvars['test.example.com']['ansible_distribution'] }}
{{ hostvars['test.example.com']['ansible_facts']['distribution'] }}
Additionally, ``group_names`` is a list (array) of all the groups the current host is in. This can be used in templates using Jinja2 syntax to make template source files that vary based on the group membership (or role) of the host
@ -666,7 +672,7 @@ A frequently used idiom is walking a group to find all IP addresses in that grou
.. code-block:: jinja
{% for host in groups['app_servers'] %}
{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }}
{% endfor %}
An example of this could include pointing a frontend proxy server to all of the app servers, setting up the correct firewall rules between servers, etc.

Loading…
Cancel
Save