ansible
Contents
About
Installation
Configure
Initialize playbook structure
Initialize directory structure as stated in
docs.ansible.com - sample setup
1 install -m 755 -d \
2 group_vars host_vars \
3 inventory/prod/{group,host}_vars \
4 library module_utils \
5 filter_plugins roles
6
7 ansible-config init --disabled > ansible.cfg
8
9 FILES=( "inventory/prd.yml" "site.yml" "README.md" ".gitignore" )
10 for FILE in "${FILES[@]}"; do
11 install -m 644 /dev/null "$FILE";
12 done
13
14 git init
15 #git remote add …
16
Initialize role structure
Use
Jinja2 highlighting
Enable vim#Modelines and append to your jinja2-template
Check playbook
Dry-run with differences
When you run ansible-playbook without --ask-become-pass|-K with a template-task you may get a wrong error message: "Failed to get information on remote file".
Facts about host
Ad-hoc commands
Debugging types
Sometimes a Dict is not what it should be.
Debug the Dict
1 ['repo: "{\'os_releases\': [{\'provider\': \'core\', \'release\': \'trixie\', \'priority\': 400}, {\'provider\': \'core\', \'release\': \'bookworm\', \'priority\': 500}, {\'provider\': \'core\', \'release\': \'bullseye\', \'priority\': 300}, {\'provider\': \'core\', \'release\': \'sid\', \'priority\': 120}, {\'provider\': \'core\', \'release\': \'experimental\', \'priority\': 110}], \'3rd_party_repos\': [\'icinga2\', \'grafana\']}"\n', 'repo type: str']
2
It is of type str.
Please be careful when quoting
The double quotes "" cast the Dict to Str.
A more correct version
So please keep a look on the type.
Client
Jinja2
Macros
Boolean to "yes" or "no" else string
Many configs do not use booleans, instead they use "yes" or "no"
Comment undefined
Hints
General
truthy value should be one of [false, true] (lowercase) Ansible Docs - Using Variables Boolean variables
Jinja2 variables and filters should have spaces before and after e.g.
{{ variable | filter }}- fqcn-builtins: Use FQCN for builtin actions
(fully qualified collection names) e.g.
ansible.builtin.template - Put a newline on every file
- Correct count of lines, correct concatenation, simplifies diffs, required by some language standards
Pretty output
ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook …
./ansible.cfg
ansible-lint
Use ansible-lint to check your playbooks, roles and tasks!
Some handy commands to satisfy ansible-lint
1 ### WRITE THE LINTER OUTPUT TO A LOG FILE
2 LOG="/tmp/ansible-lint.log"
3 ansible-lint site.yml --nocolor > "$LOG"
4
5 ### YOU MAY ALSO SKIP SOME RULES
6 ansible-lint site.yml --nocolor \
7 --skip-list 'yaml[comments]' > "$LOG"
8
9 ### IDENTIFY FILES
10 grep -A1 -e 'trailing-spaces' "$LOG" \
11 |grep -v -e 'yaml' -e '--' \
12 |sed -r 's/:[0-9]+$//'0, ß
13
14 ### DELETE TRAILING SPACES
15 grep -A1 -e 'trailing-spaces' "$LOG" \
16 |grep -v -e 'yaml' -e '--' \
17 |sed -r 's/:[0-9]+$//'
18 |sort -u \
19 |xargs sed -ri 's/\s+$//'
20
21 ### REPLACE BOOLEAN VALUES INPLACE WITH true AND false
22 grep -A1 -e 'truthy value' "$LOG" \
23 |grep -v -e 'yaml' -e '--' \
24 |sed -r 's/:[0-9]+$//' \
25 |sort -u \
26 |xargs sed -ri \
27 -e 's/: (yes|on|True)$/: true/' \
28 -e 's/: (no|off|False)$/: false/'
29
30 ### TOO MANY SPACES AFTER COLON
31 grep -A1 -e 'too many spaces after colon' "$LOG" \
32 |grep -v -e 'yaml' -e '--' \
33 |sed -r 's/:[0-9]+$//' \
34 |sort -u \
35 |xargs sed -ri -e 's/: +/: /'
36
37 ### APPEND NEW LINE TO FILES
38 grep -A1 -e 'no new line character at the end of file' "$LOG" \
39 |grep -v -e 'yaml' -e '--' \
40 |sed -r 's/:[0-9]+$//' \
41 |sort -u \
42 |xargs -I{} bash -c 'echo -e '\n' >> {}'
43
44 ### EXAMINE IN VIM
45 grep -A1 -e 'wrong indentation' "$LOG" \
46 |grep -v -e 'yaml' -e '--' \
47 |sed -r 's/:[0-9]+$//' \
48 |sort -u \
49 |xargs vim -p
sudo NOPASSWD: (devel)
During the development of a ansible playbook on your test-VM you'll often have to type the sudo password, which disturbs the "flow" massively. It's probably simpler to temporarily disable the password prompt in sudoers and leave out --ask-become-pass|-K on the ansible-playbook command-line.
You can edit /etc/sudoers relatively safe using visudo, but consider leaving another root-shell open - just in case.
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
Speeds up development, but you shouldn't do this in production, imho.
Vaults
Use vaults!!!
- Protect your secrets when using version control
Save the vault password in pass
Generate a password
1 pass generate -nc RockstableIT/ansible/ansible-monitoring/vault-pass
Encrypt file
Use it with --ask-vault-pass
Or use it with --vault-password-file, that must not be stored in git (or it will probably get added someday). Please keep in mind, that any file may be read by a superuser …
Tags
Use tags!!!
- Identify each task or sequence of tasks with a possibly unique tag.
- Debug directly at the point.
Break long lines
Satisfy ansible- and yaml-linter.
Example first
1 - name: "apache2 - enable configurations"
2 become: true
3 command: a2enconf "{{ item }}"
4 register: a2enconf_result
5 loop:
6 - "{{ php_fpm.stdout }}"
7 - security
8 when: php_fpm.stdout is defined
9 changed_when: >-
10 'Enabling conf ' + php_fpm.stdout + '.'
11 in a2enconf_result.stdout_lines
12 notify:
13 - restart apache2
14 tags:
15 - apache2_a2enconf
Jinja2
Jinja2 templating in YAML breaks long lines and adds a tremendous amount of flexibility!
Conditional statements
Conditional statements like when: or changed_when: should not include jinja2 templating delimiters such as "{{ }}".
Boolean Tests
You don't need to compare with true and false, the evaluated variable is sufficient and shorter.
is the same as
YAML multiline
Use YAML Block Chomping and jinja2!
Directly from the YAML specification
8.1.1.2. Block Chomping Indicator
Chomping controls how final line breaks and trailing empty lines are interpreted. YAML provides three chomping methods:
Strip
- Stripping is specified by the “-” chomping indicator.
- In this case, the final line break and any trailing empty lines are excluded from the scalar’s content.
Clip
- Clipping is the default behavior used if no explicit chomping indicator is specified.
- In this case, the final line break character is preserved in the scalar’s content. However, any trailing empty lines are excluded from the scalar’s content.
Keep
- Keeping is specified by the “+” chomping indicator.
- In this case, the final line break and any trailing empty lines are considered to be part of the scalar’s content. These additional lines are not subject to folding.
The chomping method used is a presentation detail and must not be used to convey content information.
The interpretation of the final line break of a block scalar is controlled by the chomping indicator specified in the block scalar header.
ansible-galaxy
Install a role from ansible-galaxy
Manual installation
By default, Ansible downloads roles to the first writable directory in the default list of paths ~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles. This installs roles in the home directory of the user running ansible-galaxy.
Manual installation
Install using requirements.yml
Installation with a
requirements.yml
1 ---
2 # Please see:
3 # https://docs.ansible.com/ansible/latest/galaxy/user_guide.html#install-multiple-collections-with-a-requirements-file
4 # https://docs.ansible.com/ansible/latest/galaxy/user_guide.html#installing-multiple-roles-from-a-file
5 roles:
6 - name: grog.management-user
7 #src:
8 #scm:
9 #version:
10
11 #collections:
12 # With just the collection name
13 #- name:
14 # version:
15 # signatures:
16 # source:
17 # type:
18
Install
Remove roles
Remove installed ansible-galaxy role
1 ### REMOVE FROM SPECIFIC roles_path
2 cd roles
3 ansible-galaxy -vvv remove --roles-path . GROG.*
4
5 ### REMOVE FROM SPECIFIC roles_path
6 find roles \
7 -maxdepth 1 -type d \
8 -iname 'grog*' \
9 |xargs -L1 basename \
10 |xargs ansible-galaxy -vvv remove --roles_path roles
11
12 ### REMOVE FROM STANDARD INSTALLATION PATHS
13 find ~/.ansible/roles /usr/share/ansible/roles /etc/ansible/roles \
14 -maxdepth 1 -type d \
15 -iname 'grog*' \
16 |xargs -L1 basename \
17 |xargs ansible-galaxy -vvv remove