Fact and task control
1, Ansible management facts
ansible fact description
-
Ansible is actually a variable that ansible automatically detects on the managed host
-
The fact contains host related information that can be used like regular variables, conditions, loops in play, or any other statement that depends on values collected from managed hosts
-
Some facts collected for managed hosts may include: host name, kernel version, network interface, IP address, operating system version, various environment variables, number of CPU s, memory provided or available, available disk space, and so on
-
With the help of facts, the state of the managed host can be easily retrieved and the operation to be performed can be determined according to the state
For example:- You can restart the server by running the conditional task based on the fact that it contains the current kernel version of the managed host
- MySQL configuration files can be customized based on available memory through fact reporting
- You can set the IPV4 address used in the configuration file according to the value of the fact
-
Before performing the first task, each play will automatically collect facts with the retrograde setup module
An example of an ansible fact
fact | variable |
---|---|
Short host name | ansible_facts['hostname'] |
Fully qualified domain name | ansible_facts['fqdn'] |
IPv4 address | ansible_facts['default_ipv4'] ['address'] |
Name list of all network interfaces | ansible_facts['interfaces'] |
/Size of dev/vda1 disk partition | ansible_facts['devices'] ['vda'] ['partitions'] ['vda1'] ['size'] |
DNS server list | ansible_facts['dns'] ['nameservers'] |
Currently running kernel version | ansible_facts['kernel'] |
If the value of a variable is of hash / dictionary type, two syntax can be used to get its value. For example:
- ansible_facts ['default_ipv4'] ['address'] can also be written as ansible_facts.default_ipv4.address
- ansible_facts ['DNS'] [' nameservers'] can also be written as ansible_facts.dns.nameservers
View the IP address of node2 host
//Write playbook --- - hosts: all tasks: - name: print ip debug: msg: the IPv4 address of {{ ansible_facts.fqdn }} is {{ ansible_facts.all_ipv4_addresses }}
//Execute playbook [root@node1 test]# ansible-playbook fact.yml PLAY [all] ************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************** ok: [192.168.100.110] TASK [print ip] ********************************************************************************************************************* ok: [192.168.100.110] => { "msg": "the IPv4 address of node2 is ['192.168.100.110']" } PLAY RECAP ************************************************************************************************************************** 192.168.100.110 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Turn off fact collection
Usually we turn off fact collection to:
- Not prepared to use any facts
- Hope to speed up play
- You want to reduce the load caused by play on the managed host
- The managed host cannot run the setup module for some reason
- You need to install some necessary software before you collect facts
2, Write loop and conditional tasks
1. Introduction to loop in ansible
When writing playbook, we inevitably have to perform some repetitive operations, such as installing software packages, creating users in batch, operating all files in a directory, etc. Because ansible is a simple automation language, it also has the basic elements of process control and loop statements
1.1 loop
Use the loop in the playbook and use the loop keyword directly
As follows:
[root@node1 test]# vim test1.yml --- - hosts: 192.168.100.110 gather_facts: no tasks: - name: start service service: name: "{{ item }}" state: started loop: - httpd - php-fpm
You can also assign the list of loop loops to a variable in advance, and then call it in the loop statement:
[root@node1 test]# vim test_service.yml test_services: - postfix - httpd [root@node1 test]# vim test1.yml - name: start services hosts: test vars_files: - test_services.yml tasks: - name: start service service: name: "{{ item }}" state: started loop: "{{ test_services }}"
The results are as follows:
[root@node1 test]# ansible-playbook test1.yml PLAY [192.168.100.110] ************************************************************************************************************** TASK [stop service] ***************************************************************************************************************** ok: [192.168.100.110] => (item=httpd) ok: [192.168.100.110] => (item=php-fpm) PLAY RECAP ************************************************************************************************************************** 192.168.100.110 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1.2 register variables in loop statements
The register keyword can also capture the output of a circular task. The following code snippet shows the structure of the register variable in a circular task:
[root@node1 test]# vim loop_register.yml --- - hosts: 192.168.100.110 gather_facts: no tasks: - name: looping echo task shell: 'echo this is my item: {{ item }}' loop: - one - two register: echo_results - name: show echo_results variable debug: var: echo_results
After executing the statement, you can see that the returned result of the variable is a dictionary list
[root@node1 test]# ansible-playbook loop_register.yml PLAY [192.168.100.110] ************************************************************************************************************** TASK [looping echo task] ************************************************************************************************************ changed: [192.168.100.110] => (item=one) changed: [192.168.100.110] => (item=two) TASK [show echo_results variable] *************************************************************************************************** ok: [192.168.100.110] => { "echo_results": { "changed": true, "msg": "All items completed", "results": [ { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "ansible_loop_var": "item", "changed": true, "cmd": "echo this is my item: one", "delta": "0:00:00.003536", "end": "2021-07-25 05:07:34.249739", "failed": false, "invocation": { "module_args": { "_raw_params": "echo this is my item: one", "_uses_shell": true, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "stdin_add_newline": true, "strip_empty_ends": true, "warn": true } }, "item": "one", "rc": 0, "start": "2021-07-25 05:07:34.246203", "stderr": "", "stderr_lines": [], "stdout": "this is my item: one", "stdout_lines": [ "this is my item: one" ] }, { "ansible_loop_var": "item", "changed": true, "cmd": "echo this is my item: two", "delta": "0:00:00.003148", "end": "2021-07-25 05:07:34.550064", "failed": false, "invocation": { "module_args": { "_raw_params": "echo this is my item: two", "_uses_shell": true, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "stdin_add_newline": true, "strip_empty_ends": true, "warn": true } }, "item": "two", "rc": 0, "start": "2021-07-25 05:07:34.546916", "stderr": "", "stderr_lines": [], "stdout": "this is my item: two", "stdout_lines": [ "this is my item: two" ] } ] } } PLAY RECAP ************************************************************************************************************************** 192.168.100.110 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1.3 list of old cycles
In ansible2 Previously, playbook implemented different loops through different loop statements, which used with_ As a prefix. These grammars are still compatible, but will be phased out in a future version
Circular statement keyword | describe |
---|---|
with_items | Simple list loop |
with_nested | Nested loop |
with_dict | Circular dictionary |
with_fileglob | Loops through all files in the specified directory |
with_lines | Loop through all lines in a file |
with_sequence | Generate a sequence of self increasing integers. You can specify the start value, end value and step size. The parameter is specified in the form of key=value, and format specifies the output format. Numbers can be decimal, hexadecimal, octal |
with_subelement | Traversal of child elements |
with_together | Traversing parallel data sets |
Before learning to use loops, if you want to create four files on the same host, you might write the following playbook
[root@server4 ~]# vim test2.yml --- - hosts: 192.168.100.110 gather_facts: no tasks: - file: path: "/opt/a" state: touch - file: path: "/opt/b" state: touch - file: path: "/opt/c" state: touch - file: path: "/opt/d" state: touch
We repeatedly wrote the file module four times. In fact, we only changed the value of the parameter path each time. If we use a loop, it can be rewritten as follows
[root@server4 ~]# vim test2.yml --- - hosts: 192.168.100.110 gather_facts: no tasks: - file: path: "{{ item }}" state: touch loop: - a - b - c - d