preamble
In this article, we'll continue to cover the various uses of roles in ansible-playbook.
environmental preparation
assemblies | releases |
---|---|
operating system | Ubuntu 22.04.4 LTS |
ansible | 2.17.6 |
basic usage
file structure
.
├──
├──
└── roles
└── base
└── tasks
└──
Defining global public variables
Add a new group_vars directory and add new files
.
├──
├──
├── group_vars
│ └──
└── roles
└── base
└── tasks
└──
▶ cat group_vars/
info: IT paiqiu
▶ cat roles/base/tasks/
- name: first
debug:
msg: "hello world {{ info }}"
Running:
▶ ansible-playbook -i
...
TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
"msg": "hello world IT paiqiu"
}
...
Defining role-level variables
Can override global variables
In the rolebase
The following is a new vars directory and a new file
.
├──
├──
├── group_vars
│ └──
└── roles
└── base
├── tasks
│ └──
└── vars
└──
▶ cat roles/base/tasks/
- name: first
debug:
msg: "hello world {{ info }}"
▶ cat roles/base/vars/
info:
name: wilson
addr: cd
Running:
▶ ansible-playbook -i
...
TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
"msg": "hello world {'name': 'wilson', 'addr': 'cd'}"
}
...
Define the static file directory
This is equivalent to defining the root directory at the role level to better manage files that need to be transferred in the rolebase
Create a directory belowfiles
and in thefiles
Below is the file to be transferred
.
├──
├──
├── group_vars
│ └──
└── roles
└── base
├── files
│ └──
├── tasks
│ └──
└── vars
└──
transportTo target machine
- name: first
copy: src= dest=/tmp/
The default is to go back to roles/base/files, so you don't need to add a path in front of it.
The copy module automatically checks the md5 of the file to be transferred, and if it hasn't changed, then it won't be transferred anymore
Defining a template
Each time a file is transferred it is re-rendered through the input variables before transferring it, in the rolebase
Create a directory belowtemplates
and create a file
.
├──
├──
├── group_vars
│ └──
└── roles
└── base
├── files
│ └──
├── tasks
│ └──
├── templates
│ └──
└── vars
└──
There are two variables defined in the template file, a manually set variable called version and the ansible built-in variable called inventory_hostname.
▶ cat roles/base/templates/
{{ version }}
{{ inventory_hostname }}
▶ cat roles/base/tasks/
- name: first
template: src= dest=/tmp/ mode=0644
Running:
▶ ansible-playbook -i -e version=2
PLAY [deploy] ****************************************************************************************************
TASK [base : first] **********************************************************************************************
changed: [10.22.11.166]
PLAY RECAP *******************************************************************************************************
10.22.11.166 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Log in to the target machine to view it:
▶ cat
2
10.22.11.166
2
is the variable passed in for this task.10.22.11.166
is the ip address of the target machine
Defining event-driven
Usually used for actions that need to be triggered after certain tasks have been completed, e.g., restarting a service after publishing a configuration file. In the rolebase
Create a directory underhandlers
and create a file
.
├──
├──
├── group_vars
│ └──
└── roles
└── base
├── files
│ └──
├── handlers
│ └──
├── tasks
│ └──
├── templates
│ └──
└── vars
└──
Creating Eventsfirst handler
▶ cat roles/base/handlers/
- name: first handler
debug:
msg: echo 'hello world'
▶ cat roles/base/tasks/
- name: first
template: src= dest=/tmp/ mode=0644
notify: first handler
Running:
▶ ansible-playbook -i -e version=2
PLAY [deploy] ****************************************************************************************************
TASK [base : first] **********************************************************************************************
changed: [10.22.11.166]
RUNNING HANDLER [base : first handler] ***************************************************************************
ok: [10.22.11.166] => {
"msg": "echo 'hello world'"
}
PLAY RECAP *******************************************************************************************************
10.22.11.166 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Similarly, if the event precursor doesn't happen, then the event notification won't happen, for example, if the event precursor is the transfer of a file, and if the file doesn't change, it won't be transferred again, then the event won't happen again either
Add more tasks
Currently onlyIn addition, a task dedicated to the transfer of files is being added.
▶ cat roles/base/tasks/
- name: main
include_tasks:
vars:
app_version: 0.2
▶ cat roles/base/tasks/
- name: first
debug:
msg: "version: {{ app_version }}"
Running:
▶ ansible-playbook -i
PLAY [deploy] ****************************************************************************************************
TASK [base : main] ***********************************************************************************************
included: /home/wilson/workspace/ansible/roles/base/tasks/ for 10.22.11.166
TASK [base : first] **********************************************************************************************
ok: [10.22.11.166] => {
"msg": "version: 0.2"
}
PLAY RECAP *******************************************************************************************************
10.22.11.166 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
If there are too many files, they can be handled by looping:
- name: main
include_tasks: "{{ yaml_items }}"
loop:
-
-
loop_control:
loop_var: yaml_items
vars:
app_version: 0.2
To add a few common commands
execute a commandshell
- name: display
shell: echo 'hello world'
Transmission of documentscopy
The copy module automatically checks the md5 of the file to be transferred, and if it hasn't changed, then it won't be transferred anymore
- name: copy file
copy: src= dest=/tmp/
Modify the contents of the document (one line)lineinfile
- path: Specify the path of the file to be operated (required)
- line: defines the complete line to be inserted or replaced (optional)
- regexp: Regular expression to match existing lines. Used in conjunction with line, matching lines will be replaced with
- state:
- present (default): Ensures that the specified line exists.
- absent: remove matching rows
- create: Whether to create the file if it does not exist (default yes)
- insertafter: specifies the location of the insertion line (default EOF)
- EOF: End of File
- BOF: Beginning of File
- Regular expression: inserts after matching line
insertbefore: similar to insertafter, but inserted before the matching line
Modify the current line after matching the line with a regular
- name: modify
lineinfile: dest=/tmp/ regexp='^DC' line="DC=hello" state=present
Modify file contents (multiple lines/blocks)blockinfile
- path: Specify the path of the file to be manipulated (required)
- block: defines the content of the text to be inserted (required)
- marker: Specify the start and end strings of the marker block, default is # {mark} ANSIBLE MANAGED BLOCK
- state:
- present (default): ensures that the block exists
- absent: remove block
- create: Whether to create the file if it does not exist (default yes)
- insertafter: specifies the location of the insertion block (default EOF)
- Available values:
- EOF: End of File
- BOF: Beginning of File
- Regular expression: insert after matching line
- Available values:
- insertbefore: Similar to insertafter, but inserts before the matching line.
1) Add new content below a line and mark the added content
- name: add new content with markers
blockinfile:
path: /tmp/
marker: "# {mark} by wilson"
insertafter: '^DC'
block: |
name: wilson
city: cd
View the results after running
▶ cat /tmp/
DC=hello
# BEGIN by wilson
name: wilson
city: cd
# END by wilson
2) Delete marked content
- name: Remove the managed block
blockinfile:
marker: "# {mark} by wilson"
path: /tmp/
state: absent
Adding blocks of content and marking them up makes it easy to modify and delete them.
Using templates
- name: hostname config
template: src=etc/hostname dest=/etc/hostname
Setting File Permissionsfile
- name: change file 755
file:
path: /tmp/
owner: wilson
group: wilson
state: file
mode: 755
Using loopswith_items
with_items
Modify permissions for multiple directories
- name: change directory 755
file:
path: '{{ }}'
owner: wilson
group: wilson
state: directory
mode: '{{ }}'
with_items:
- { dir: '/tmp/1', mode: '0755'}
- { dir: '/tmp/2', mode: '0755'}
loop
surelywith_items
replace withloop
It's possible.
- name: change directory 755
file:
path: '{{ }}'
owner: wilson
group: wilson
state: directory
mode: '{{ }}'
with_items:
- { dir: '/tmp/1', mode: '0755'}
- { dir: '/tmp/2', mode: '0755'}
nested loopwith_nested
Output each combination, equivalent to the Cartesian product
- name: nested loop
debug:
msg: "{{ item[0] }} {{ item[1] }}"
with_nested:
- [ "hello1", "hello2"]
- [ "world1", "world2"]
Output results:
TASK [base : nested loop] ****************************************************************************************
ok: [127.0.0.1] => (item=['hello1', 'world1']) => {
"msg": "hello1 world1"
}
ok: [127.0.0.1] => (item=['hello1', 'world2']) => {
"msg": "hello1 world2"
}
ok: [127.0.0.1] => (item=['hello2', 'world1']) => {
"msg": "hello2 world1"
}
ok: [127.0.0.1] => (item=['hello2', 'world2']) => {
"msg": "hello2 world2"
}
File Content Loopwith_file
Printing the contents of a file line by line
- name: display file content
debug:
msg: "{{ item }}"
with_file:
- /tmp/
idempotence (math.)
When using roles to manage multiple devices, scripts should always be written with idempotency in mind, i.e., each execution should be guaranteed to produce the same result.
Contact me
Contact me for an in-depth chat
This concludes this article
I'm not very knowledgeable, so if there is any soup leakage, please do not hesitate to give me advice...