Iteration and Conditionals
Iteration and Conditionals
$ cd $INTRO_ANSIBLE_DIR/working-with-playbooks
.
├── ansible.cfg
├── hosts
├── playbook-dict.yml
├── playbook-lists.yml
Step through an array
Each element in iteration is assigned to item variable
vars:
list_of_files:
- file1.txt
- file2.txt
.
.
tasks:
- name: Process a list of items
copy:
src: "/path/to/local/{{ item }}"
dest: "/path/to/remote/{{ item }}"
with_items: "{{ list_of_files }}"
Configuring our fake application myapp
Have a look at playbook-lists.yml
Run the playbook and then have a look in /etc/myapp/config
Playbook adds lines to a configuration file for a fake app
There are a number of things we can optimise
Exercise: Remove repetitive allowed_host tasks from playbook
Use with_items
to refactor tasks
Replace all allowed host tasks with
- name: Add allowed_hosts entries
lineinfile:
path: /etc/myapp/config
line: "allow_from: {{ item }}"
insertafter: EOF
with_items:
- "{{ allowed_host1 }}"
- "{{ allowed_host2 }}"
- "{{ allowed_host3 }}"
Exercise: Remove repetitive listen tasks from playbook
Use with_items
to simply listen tasks
Replace all the listen tasks with:
- name: Add listen port entries
lineinfile:
path: /etc/myapp/config
line: "listen: {{ item }}"
insertafter: EOF
with_items: "{{ listen_ports }}"
Nesting Loops with_nested
It is possible to loop over two lists at once
- name: Add allowed ports for each host
lineinfile:
path: /etc/myapp/config
line: "host: {{ item[0] }}:{{ item[1] }}"
insertafter: EOF
with_nested:
- [ "{{ allowed_host1 }}", "{{ allowed_host2 }}", "{{ allowed_host3 }}"]
- "{{ listen_ports }}"
Iterating through dictionaries with_dict
Takes a dictionary argument
Each item has
- name: Task that iterates over a dictionary
somemodule:
arg: "{{ item.key }}"
arg2: "{{ item.value }}"
with_dict: "{{ dictionary }}"
More configuration for myapp
`playbook-dict.yml` sets up database config for our fake application
Adds each element of database variable to config
Run the playbook and have a look at /etc/myapp/app_config
ansible-playbook playbook-dict.yml
Exercise: Remove repetition from playbook-dict.yml
Refactor the playbook using with_dict
to remove repetitive tasks
- name: Add database config to /etc/myapp/config
lineinfile:
path: /etc/myapp/app_config
line: "database_{{ item.key }}={{ item.value }}"
regexp: '^database_{{ item.key}}.*'
with_dict: "{{ database[env_name] }}"
The main way to conditionally do something in Ansible is by using the when
clause
`when` has identical semantics to a Python _if_ block
`when: some_variable is defined`
`when: env_name == 'staging'`
- name: Some task
command: do something
when : <condition is true>
Exercise: Make our tasks conditional
Tasks in playbook-dict.yml
assume a staging environment
vars:
.
env_name: staging
Add a conditional to the lineinfile
tasks
Only execute if env_name
is production
Re-run the playbook
- name: Add database config to /etc/myapp/config
lineinfile:
.
.
when: env_name == 'production'
Exercise: Override default env_name to run tasks
env_name is set to staging by default
Override this to be production and re-run playbook
Hint: What type of variable has precedence in this situation?
ansible-playbook playbook-dict.yml -e env_name=production