L4 Ansible Variable Management
1. Jinja and templates
template – Template a file out to a remote server
Templates are processed by the Jinja2 templating language.
1-1 task2-8jinja2.yaml
---
- hosts: all
tasks:
- name: deploy a simple template file
template:
src: templates/2-8-template.j2
dest: $HOME/tmp/2-8-template.txt
tags:
- create
- name: remove templated file
file:
dest: $HOME/tmp/2-8-template.txt
state: absent
tags:
- destroy
1-2 templates/2-8-template.j2
This file is a template on {{hostvars[inventory_hostname]['ansible_fqdn']}}
backup_file {% if backup_file is defined %} is defined {% else %} is not defined {% endif %}
$ ansible-playbook -i ../inventory.ini task2-8jinja2.yaml --tags create
TASK [deploy a simple template file] *****************************************************
changed: [githost]
changed: [k8s-jx]
changed: [k8s-jx2]
changed: [k8s-jx1]
PLAY RECAP *******************************************************************************
githost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-jx : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-jx1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-jx2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
jabox
This file is a template on jabox
backup_file is not defined
jabox-node1
This file is a template on jabox-node1
backup_file is not defined
jabox-node2
This file is a template on jabox-node2
backup_file is not defined
ansible-playbook -i ../inventory.ini task2-8jinja2.yaml --tags destroy
2. Host facts for conditional
execution
---
- hosts: web
tasks:
- name: create
file:
dest: $HOME/tmp/k8s-master-on-githost
state: '{{file_state}}'
when: hostvars[inventory_hostname]['inventory_hostname'] == 'githost'
#where the file gonna be created
- name: create
file:
dest: $HOME/tmp/githost-on-k8s-master
state: '{{file_state}}'
when: inventory_hostname == 'k8s-jx'
#where the file gonna becreated
2-1 Conditionals
Sometimes you will want to skip a particular step on a particular host.
This could be something as simple as not installing a certain package if the operating system is a particular version, or it could be something like performing some cleanup steps if a filesystem is getting full.
This is easy to do in Ansible with the when clause, which contains a raw Jinja2 expression
without double curly braces. It’s actually pretty simple:
---
- hosts: web
tasks:
- name: create
file:
dest: $HOME/tmp/k8s-master-on-githost
state: '{{file_state}}'
when: hostvars[inventory_hostname]['inventory_hostname'] == 'githost' #where the file gonna be created
- name: create
file:
dest: $HOME/tmp/githost-on-k8s-master
state: '{{file_state}}'
when: inventory_hostname == 'k8s-jx' #where the file gonna becreated
when: hostvars[inventory_hostname]['inventory_hostname']
when: inventory_hostname == 'k8s-jx'
ansible -m debug -i ../inventory.ini -a "var=hostvars['k8s-jx1']" k8s-jx2
2-2 debug module
This is information that I could use on the k8s-jx2
host, basically in k8s-jx2
host plays, but that's coming from k8s-jx1
. gather k8s-jx2
fact from all ther machine
ansible-playbook -i ../inventory.ini task2-9fact.yaml -e file_state=touch
TASK [create] ****************************************************************************************
skipping: [k8s-jx]
changed: [githost]
TASK [create] ****************************************************************************************
skipping: [githost]
changed: [k8s-jx]
PLAY RECAP *******************************************************************************************
githost : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
k8s-jx : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
- On
githost
:k8s-master-on-githost
- On
k8s-master
:githost-on-k8s-master
ansible-playbook -i ../inventory.ini task2-9fact.yaml -e file_state=absent
3. Looping tasks with variable lists
3-1 task2-10loopvar.yaml
---
- hosts: all
vars:
packages: [git,vim,ruby]
tasks:
- name: install packages for Debian style OSs
apt:
name: '{{item}}'
state: '{{pkg_state}}'
with_items: '{{packages}}'
when: ansible_os_family == "Debian"
sudo: yes
tags:
- handle-pkg
- name: install pacakges for Redhat style OSs
yum:
name: '{{item}}'
state: '{{pkg_state}}'
with_items: '{{packages}}'
when: ansible_os_family == "RedHat"
sudo: yes
tags:
- handle-pkg
- name: create files based on package names
file:
dest: $HOME/tmp/{{item}}
state: '{{file_state}}'
with_items: '{{packages}}'
when: ansible_os_family == "RedHat"
tags:
- handle-files
$ ansible-playbook -i ../inventory.ini task2-10loopvar.yaml -e file_state=touch -e pkg_state=latest
$ ansible-playbook -i ../inventory.ini task2-10loopvar.yaml -e file_state=absent -e pkg_state=absent
$ ansible-playbook -i ../inventory.ini task2-10loopvar.yaml --skip-tags handle-pkg --tags handle-files -e file_state=absent
- ansible list variable
vars:
packages: [git,vim,ruby]
- Loops in ansible
with_items
is replaced by loop
and the flatten
filter.
loop: "{{ items|flatten(levels=1) }}"
with_items: '{{packages}}'
ansible_os_family
https://riptutorial.com/ansible/example/12268/-when--condition----ansible-os-family--lists
- when: ansible_os_family == "CentOS"
- when: ansible_os_family == "Redhat"
- when: ansible_os_family == "Darwin"
- when: ansible_os_family == "Debian"
-
when: ansible_os_family == "Windows"
-
sudo: yes
https://docs.ansible.com/ansible/latest/user_guide/become.html#understanding-privilege-escalation
apt.state:
andyum.state:
yum state: absent
, installed
, latest
, present
, removed
Whether to install (present
or installed
, latest
), or remove (absent
or removed
) a package.
present
andinstalled
will simply ensure that a desired package is installed.
latest
will update the specified package if it's not of the latest available version.
absent
and removed will remove the specified package.
Default
is None, however in effect the default action is present unless the autoremove option is enabled for this module, thenabsent
is inferred.
# [DEPRECATION WARNING]: Invoking "apt" only once while using a loop via squash_actions is deprecated. Instead of using a loop to supply multiple
# items and specifying `name: "{{item}}"`, please use `name: '{{packages}}'` and remove the loop. This feature will be removed in version 2.11.
# Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
- name: "Install dependencies"
apt:
pkg:
- libnss3
- libasound2
- xcb
- xinit
state: present
4. Looping tasks with dictionaries
---
- hosts: all
vars:
animals:
cats:
tabby:
color: grey
persnickityness: high
calico:
color: orange
persnickityness: medium
dogs:
doberman:
color: black
persnickityness: extreme
retriever:
color: golden
persnickityness: low
tasks:
- name: iterate over animal array
file:
name: '$HOME/tmp/{{item.key}}-{{item.value.color}}'
state: '{{file_state}}'
with_dict: '{{animals.cats}}'
- name: iterate over animals array
file:
name: '$HOME/tmp/{{item.key}}-{{item.value.color}}'
state: '{{file_state}}'
with_dict: '{{animals.dogs}}'
when: 'item.value.persnickityness == "low"'
- dictionary variable
vars:
animals:
cats:
...
dogs:
...
-
dict key and value:
{{item.key}}-{{item.value.color}}'
-
with_dict: '{{animals.cats}}
with_dict: '{{animals.dogs}}'
when: 'item.value.persnickityness == "low"'
$ ansible-playbook -i ../inventory.ini task2-11loopdict.yaml -e file_state=touch
$ ansible-playbook -i ../inventory.ini task2-11loopdict.yaml -e file_state=absent
Alphabetical order
calico-orange
retriever-golden
tabby-grey
5. Looping in templates with variable lists
---
- hosts: all
vars:
packages: [git,vim,ruby]
tasks:
- name: deploy a template file with a loop
template:
src: templates/2-12-template.j2
dest: $HOME/tmp/2-12-template.txt
tags:
- create
- name: remove the templated file
file:
dest: $HOME/tmp/2-12-template.txt
state: absent
tags:
- destroy
5-1 templates/2-12-template.j2
We are on host {{inventory_hostname}}
We installed: {% for package in packages %}{{package}}{% if not loop.last %}, {% endif %}{% endfor %}
ansible-playbook -i ../inventory.ini task2-12looptemplist.yaml --tags create
ansible-playbook -i ../inventory.ini task2-12looptemplist.yaml --tags absent
We are on host k8s-jx
We installed: git, vim, ruby
We are on host githost
We installed: git, vim, ruby
6. Looping in templates with dictionaries
---
- hosts: all
vars:
animals:
cats:
tabby:
color: grey
persnickityness: high
calico:
color: orange
persnickityness: medium
dogs:
doberman:
color: black
persnickityness: extreme
retriever:
color: golden
persnickityness: low
tasks:
- name: deploy a dictionary looping template file
template:
src: templates/2-13-template.j2
dest: $HOME/tmp/2-13-template.txt
tags:
- create
- name: remove the templated file
file:
dest: $HOME/tmp/2-13-template.txt
state: absent
tags:
- destroy
6-1 templates/2-13-template.j2
We are in groups: {% for group in hostvars[inventory_hostname]['group_names'] %}{{group}}{% if not loop.last %}, {% endif %}{% endfor %}
We like both {% for key,value in animals.items() %}{{key}}{% if not loop.last %} and {% endif %}{% endfor %}
W{% for key,value in animals.items() %}e like{% for animal,name in animals[key].items() %} {{name.color}} {{animal}}s{% if not loop.last %} and{% endif %}{% endfor %}{% if not loop.last %} and w{% endif %}{% endfor %}
$ ansible-playbook -i ../inventory.ini task2-13looptempdict.yaml --tags create
$ ansible-playbook -i ../inventory.ini task2-13looptempdict.yaml --tags destroy
# k8s-jx
# We are in groups: k8s_master, k8s_servers, web
# We like both cats and dogs
# We like grey tabbys and orange calicos and we like black dobermans and golden retrievers
# githost
# We are in groups: githost_servers, web
# We like both cats and dogs
# We like grey tabbys and orange calicos and we like black dobermans and golden retrievers
# k8s-jx1
# We are in groups: db, k8s_servers
# We like both cats and dogs
# We like grey tabbys and orange calicos and we like black dobermans and golden retrievers
# k8s-jx2
# We are in groups: backup, db, k8s_servers
# We like both cats and dogs
# We like grey tabbys and orange calicos and we like black dobermans and golden retrievers
7. Testing plays with check mode
2-14 Check mode Check Mode (“Dry Run”)
When ansible-playbook is executed with
--check
it will not make any changes on remote systems.check s a way of validating that our ansible is actually valid in advance of impacting our systems.