07_ansible, conditional selection, loading customer events, applying 'when' statement on roles and includes, conditional import, selecting files and templates based on variables, registering variables

10. Conditional selection
10.1. When statement
10.2. Load customer events
10.3. Apply 'when' statement on roles and includes
10.4. Conditional import
10.5. Select files and templates based on variables
10.6. Register variables

10. Condition selection

Reposted from: http://www.ansible.com.cn/docs/playbooks_conditionals.html#id3

Often, the outcome of a play depends on the value of a variable, an event (events received from a remote system), or the result of a previous task. In some cases, the value of these variables also depends on other variables. Furthermore, It is possible to create redundant groups to manipulate hosts based on whether or not those hosts meet certain criteria, Ansible provides many different options for controlling execution flow. Let's take a closer look at what these are all about.

10.1. When statement

Sometimes users may need a host to skip a specific step. This process can be as simple as missing a package on a specific version of the system or performing a cleanup operation on a full file system Same. These operations whenare very simple on Ansible if you use statements. When statements contain Jinja2 expressions (see: doc:playbooks_variables). It's actually really simple:

tasks:
  - name: "shutdown Debian flavored systems"
    command: /sbin/shutdown -t now
    when: ansible_os_family == "Debian"

A series of Jinja2 "filters" can also be used in the when statement, but some are unique to Ansible. For example, if we want to ignore an error and make a decision based on the success or failure of the execution, we can do it like this:

tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped

I know it's a bit too advanced to discuss the 'register' statement command here, we'll get to that a bit later in the speaker.

Friendly reminder, if you want to check which events are allowed in a specific system, you can execute the following command:

ansible hostname.example.com -m setup

Tip: Sometimes you get a return parameter whose value is a string, and you want to use mathematical operations to compare it, then you can perform the following operations:

tasks:
  - shell: echo "only on Red Hat 6, derivatives, and later"
    when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6

Note:
The above example requires the lsb_release package to be installed on the target host to return the ansible_lsb.major_release event.

Variables defined in both playbooks and inventory can be used. The following example determines whether a task is executed based on a boolean value:

vars:
   epic: true

A conditional select implementation might look like this:

tasks:
   - shell: echo "This certainly is epic!"
    when: epic

or like this:

tasks:
   - shell: echo “This certainly isn’t epic !
    when: not epic

If a variable does not exist, you can use Jinja2 definedcommands to skip or ignore. For example:

tasks:
    - shell: echo "I've got '{
    
    { foo }}' and am not afraid to use it!"
      when: foo is defined

    - fail: msg="Bailing out. this play requires 'bar'"
      when: bar is not defined

This mechanism is sometimes particularly useful when choosing to import variable files, as detailed below.

note When whenhe is used at the same with_itemstime (see: doc:playbooks_loops for details), the note whenstatement will be processed separately for different projects. This is from the original design:

tasks:
   - command: echo {
    
    {
    
     item }}
with_items: [0, 2, 4, 6, 8, 10]
when: item > 5

10.2. Loading client events

Loading the client's own event is actually very simple, and it will be introduced in detail in: doc:developing_modules. Just call the client's own event, and then put all the modules at the top of the task list, and the return value of the variable can be accessed in the future:

tasks:
    - name: gather site specific fact data
      action: site_facts
    - command: /usr/bin/thingy
      when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'

10.3. Applying 'when' statements to roles and includes

Note, if many of your tasks share the same conditional statement, you can add the inlcudes statement after the select statement, see the example below. This feature does not apply to the includes of the playbook, only the includes of the task. All tasks will be checked , the selection will be applied to all tasks:

- include: tasks/sometasks.yml
  when: "'reticulating splines' in output"

Or apply to role:

- hosts: webservers
  roles:
     - {
    
     role: debian_stock_config, when: ansible_os_family == 'Debian' }

When using this method in the system but not matching certain criteria, you will find that in Ansible, there are many default 'skipped' results. For details, see: the 'group_by' module in the doc:modules document, you will find more pleasing method to solve this problem.

10.4. Conditional imports

Note:
This is an advanced but frequently used topic. Of course you can skip this section.

You may want to do the same thing differently in a playbook based on certain criteria. Using a playbook on different platforms or operating systems is a good example.

For example, the package named Apache may be different in CentOS and Debian systems, but this problem can be solved by Ansible Playbook with some simple syntax:

---
- hosts: all
  remote_user: root
  vars_files:
    - "vars/common.yml"
- [ "vars/{
    
    { ansible_os_family }}.yml", "vars/os_defaults.yml" ]
  tasks:
- name: make sure apache is running
service: name={
    
    {
    
     apache }} state=running

Note:
'ansible_os_family' is already imported into the list of filenames defined for vars_files.

As a reminder, there are many different YAML files that simply contain keys and values:

---
# for vars/CentOS.yml
apache: httpd
somethingelse: 42

How does this specific thing work? If the operating system is 'CentOS', the first file imported by Ansible will be 'vars/CentOS.yml', followed by '/var/os_defaults.yml', if this file does not exist. And it is not found in the list, An error will be reported. In Debian, the first look will be 'vars/Debian.yml' instead of 'vars/CentOS.yml', if not found, then look for the default file 'vars/os_defaults.yml' is very simple. If you use For this conditional import feature, you need to install facter or ohai before running the playbook. Of course, if you like, you can also push this to Ansible:

# for factor
ansible -m yum -a "pkg=facter state=present"
ansible -m yum -a "pkg=ruby-json state=present"

# for ohai
ansible -m yum -a "pkg=ohai state=present"

The way of setting in Ansible ——— separate the parameters from the task, so as to avoid too many complicated statements such as ugly nested if in the code. This can make the configuration entries more smooth and pleasing to the eye —— especially because of this Decision points can be minimized.

10.5. Selecting files and templates based on variables

Note:

This is an advanced topic that is often discussed. Articles can also be skipped.

Sometimes, you want to copy a configuration file, or a template based on parameters. The following structure selects the variable file given by the first host, which can be much simpler than putting many if options in the template. The following The example shows how to make a configuration file template according to different systems, such as CentOS, Debian:

- name: template a file
   template: src={
    
    {
    
     item }} dest=/etc/myapp/foo.conf
   with_first_found:
     - files:
        - {
    
    {
    
     ansible_distribution }}.conf
        - default.conf
       paths:
        - search_location_one/somedir/
        - /opt/other_location/somedir/

10.6. Register variables

Often in a playbook, it is useful to store the result of a command in a variable for later access. Using the command module in this way can remove site idiosyncrasies in many ways. According to the example you can detect a specific Does the program exist

The 'register' keyword determines which variable to store the result in. The result parameter can be used in templates, action items, or when statements. Like this (this is a trivial example):

- name: test play
  hosts: all

  tasks:
      - shell: cat /etc/motd
        register: motd_contents

      - shell: echo "motd contains the word hi"
        when: motd_contents.stdout.find('hi') != -1

As shown above, the content of the registered parameter is the string 'stdout' and can be accessed. The result of this registration, if shown above, can be converted into a list (or already a list), It can be used in "with_items" in the task. "stdout_lines" is already accessible in the object. Of course, if you like, you can also call "home_dirs.stdout.split()", or you can use other fields to split:

- name: registered variable usage as a with_items list
  hosts: all

  tasks:
      - name: retrieve the list of home directories
        command: ls /home
        register: home_dirs

      - name: add home dirs to the backup spooler
        file: path=/mnt/bkspool/{
    
    {
    
     item }} src=/home/{
    
    {
    
     item }} state=link
        with_items: home_dirs.stdout_lines
        # same as with_items: home_dirs.stdout.split()

Guess you like

Origin blog.csdn.net/toto1297488504/article/details/132231486