Ansible - Use when condition in a playbook for roles - ansible

I am trying to add a when condition in my ansible-playbook. However, I am not able to figure out the exact syntax/method to do it because my roles are using additional parameters. Below mentioned is my playbook
---
- name: Deploying application code
hosts: uat-aegis
roles:
- { role: roles/send_slack, slack_message_text: "*`Started : Deploying code for {{ module_name }} on {{ inventory_hostname }}`*"}
- { role: roles/application_code_backup, backup_directory_name: "NAME", repo_directory: "/path/to/repo" }
- { role: roles/application_copy_config, repo_directory: "/path/to/repo"}
- { role: roles/application_git_pull, repo_url: "git#code.git", repo_directory: "/path/to/repo", branch_name: "BRANCH_NAME"}
- { role: roles/application_pm2_restart, process_name: "NAME" }
- { role: roles/send_slack, slack_message_text: "*`=== Completed : Deploying code for {{ module_name }} on {{ inventory_hostname }} ===`*"}
Here I need to execute roles/application_copy_config only when a certain variable value is true. This variable value is passed as --extra-vars while executing the ansible-playbook from Jenkins(Boolean value parameter in Execute Script). I have tried using the below piece of code but it does not work.
---
- name: Deploying application code
hosts: uat-aegis
roles:
- { role: roles/send_slack, slack_message_text: "*`Started : Deploying code for {{ module_name }} on {{ inventory_hostname }}`*"}
- { role: roles/application_code_backup, backup_directory_name: "NAME", repo_directory: "/path/to/repo" }
- { role: roles/application_copy_config
when: "copy_config=true", repo_directory: "/path/to/repo"}
- { role: roles/application_git_pull, repo_url: "git#code.git", repo_directory: "/path/to/repo", branch_name: "BRANCH_NAME"}
- { role: roles/application_pm2_restart, process_name: "NAME" }
- { role: roles/send_slack, slack_message_text: "*`=== Completed : Deploying code for {{ module_name }} on {{ inventory_hostname }} ===`*"}
ansible-playbook command is as follows
ansible-playbook plays/deploy_application/code.yml --extra-vars "module_name=$MODULE_NAME config_copy_path=$CURRENT_PATH/ env=$ENVIRONMENT copy_config=$COPY_CONFIG"
Please help me to use the when condition in the ansible-playbook. This is required becuase I need to execute the role: roles/application_copy_config only when the variable value is true. I have used this reference for adding when condition in the role

Was able to apply the when condition for boolean values using bool filter as mentioned below
---
- name: Deploying application code
hosts: uat-aegis
roles:
- { role: roles/send_slack, slack_message_text: "*`Started : Deploying code for {{ module_name }} on {{ inventory_hostname }}`*"}
- { role: roles/application_code_backup, backup_directory_name: "NAME", repo_directory: "/path/to/repo", when: var1 | bool }
- { role: roles/application_copy_config, repo_directory: "/path/to/repo"}
- { role: roles/application_git_pull, repo_url: "git#code.git", repo_directory: "/path/to/repo", branch_name: "BRANCH_NAME", when: var2 | bool}
- { role: roles/application_pm2_restart, process_name: "NAME", when: not var3 | bool }
- { role: roles/send_slack, slack_message_text: "*`=== Completed : Deploying code for {{ module_name }} on {{ inventory_hostname }} ===`*"}
Use the below code to check true and false
when: var1 | bool ----> true
when: not var2 | bool ----> false

You can specify conditionals with different style:
- name: Deploying application code
hosts: uat-aegis
roles:
- role: roles/application_code_backup
vars:
backup_directory_name: "NAME"
repo_directory: "/path/to/repo"
when: var1 | bool

Related

Iterate over dict got from another dict

This is my Ansible task:
- name: Create all daemon supervisor files
ansible.builtin.template:
src: supervisor_daemon_template.j2
dest: /tmp/asd/{{item.brand}}_{{ item.daemon_name }}.conf
# this works
loop: "{{ app_daemons.app1 }}"
# But I want something like that:
# loop: "{{ lookup('ansible.builtin.vars', app_daemons, inventory_hostname ) }}"
vars:
app_daemons:
app1:
- { daemon_name: 'receiver', brand: 'nokia' }
- { daemon_name: 'parser', brand: 'nokia' }
app2:
- { daemon_name: 'receiver', brand: 'samsung' }
- { daemon_name: 'parser', brand: 'samsung' }
I want to create the files accordingly to the current {{ inventory_hostname }} that can be either app1 or app2.
How can I do this?

Ansible conditionals on list variables passed into a role

I have following ansible code
- hosts: localhost
roles:
- { role: roleone }
- { role: roletwo, myvariable : ["var1","var2"] }
I need to set this list variable based on conditional.
Below is what I have tried, although it does not work:
- hosts: localhost
roles:
- { role: roleone }
- { role: roletwo, myvariable : ["foo1","foo2"], when: init=="true", myvariable : ["bar1","bar2"], when: init == "false" }
I was able to achieve this by using following code:
---
- hosts: all
roles:
- { role: roleone }
- { role: roletwo, myvariable: "{{ ['var1','var2'] if (init == "true") else ['bar1','bar2'] }}" }

How to access vars outside item when using with_items?

I have a role which uses with_items:
- name: Create backup config files
template:
src: "config.yml.j2"
dest: "/tmp/{{ project }}_{{ env }}_{{ item.type }}.yml"
with_items:
- "{{ backups }}"
I can access the item.type, as usual, but not project or env which are defined outside the collection:
deploy/main.yml
- hosts: ...
vars:
project: ...
rails_env: qa
roles:
- role: ../../../roles/deploy/dolly
project: "{{ project }}"
env: "{{ rails_env }}"
backups:
- type: mysql
username: ...
password: ...
The error I get is:
Error was a <class 'ansible.errors.AnsibleError'>, original message: An unhandled exception occurred while templating '{{ project }}'
The template, config.j2.yml, is:
type: {{ item.type }}
project: {{ project }}
env: {{ env }}
database:
username: {{ item.username }}
password: {{ item.password }}
It turns out for can't redefine a var with the same name as an existing var, so project: {{ project }} will always fail with an error.
Instead project can be omitted and the existing definition, in vars, can be used.
- hosts: ...
vars:
project: ... # <- already defined here
roles:
- role: ../../../roles/deploy/dolly
backups:
- type: mysql
username: ...
password: ...
If the var is not defined in vars can be defined in the role:
- hosts: ...
vars:
name: ...
roles:
- role: ../../../roles/deploy/dolly
project: "{{ name }}" # <- define here
backups:
- type: mysql
username: ...
password: ...

How to change an existing user's password?

I'm trying to change the password of an existing user with Ansible, but only if the user is already present. I do not want to create any new users. Is there any good way?
vars:
myusers:
- { name: 'user1', update_pass: 'passwd' }
- { name: 'user2', update_pass: 'passwd' }
- { name: 'user3', update_pass: 'passwd' }
tasks:
- name: check exist
shell: /usr/sbin/usermod {{ item.name }}
with_items: myusers
register: result
failed_when: result.rc not in [6,2]
changed_when: result.rc != 6
- name: change passwd
user: name={{ item.name }} password={{ item.update_pass }} update_password=always
when: result|changed
with_items: myusers
vars_prompt:
- name: user_name
prompt: Enter the user name for password reset
private: no
- name: pass
prompt: Enter the password
tasks:
- name: Change {{ user_name }} password
user: name={{ user_name }} password={{ pass|password_hash('sha512') }} update_password=always
vars:
myusers:
- { name: 'user1', update_pass: 'passwd' }
- { name: 'user2', update_pass: 'passwd' }
- { name: 'user3', update_pass: 'passwd' }
# Contents of passwd will be stored in ansible_facts.getent_passwd as a dict
- name: Determine local user accounts
getent:
database: passwd
# Update password if user account is found in /etc/passwd
- name: change passwd
user: name={{ item.name }} password={{ item.update_pass }} update_password=always
with_items: myusers
when: item in ansible_facts.getent_passwd

Ansible: How to iterate over a role with an array?

Is it possible to call a role multiple times in a loop like this:
vars:
my_array:
- foo
- bar
- baz
roles:
- role: foobar
with_items: my_array
How can we do this?
Now supported as of Ansible 2.3.0:
- name: myrole
with_items:
- "aone"
- "atwo"
include_role:
name: myrole
vars:
thing: "{{ item }}"
There's no way to loop over a role currently but as mentioned in that Google Group discussion you can pass a list or dict to the role and then loop through that internally.
So instead you could do something like:
# loop_role/tasks/main.yml
- name: debug item
debug: var="{{ item }}"
with_items: my_array
And then use it like this:
- hosts: all
vars:
my_array:
- foo
- bar
- baz
roles:
- { role: loop_role, my_array: "{{ my_array }}" }
I used something like below on Ansible version 2.8
tasks:
- name: looping role to create multiple filesystem
include_role:
name: /opt/ansible/playbook/app_filesystem
vars:
vgname: "{{ item.vgname }}"
lvname: "{{ item.lvname }}"
lvsize: "{{ item.lvsize }}"
mountpoint: "{{ item.mountpoint }}"
loop:
- { vgname: 'vgapp', lvname: 'lvapp', lvsize: '30g', mountpoint: '/app' }
- { vgname: 'vgapp', lvname: 'lvappzk', lvsize: '64g', mountpoint: '/app/z' }
- { vgname: 'vgapp', lvname: 'lvappdatazk', lvsize: '+100%FREE', mountpoint: '/app/data/zookeeper' }
tasks:
- name: looping role to create multiple filesystem
include_role:
name: /opt/ansible/playbook/app_filesystem
vars:
vgname: "{{ item.vgname }}"
lvname: "{{ item.lvname }}"
lvsize: "{{ item.lvsize }}"
mountpoint: "{{ item.mountpoint }}"
loop:
- { vgname: 'vgapp', lvname: 'lvapp', lvsize: '30g', mountpoint: '/app' }
- { vgname: 'vgapp', lvname: 'lvappzk', lvsize: '64g', mountpoint: '/app/zookeeper' }
- { vgname: 'vgapp', lvname: 'lvappdatazk', lvsize: '+100%FREE', mountpoint: '/app/data/zookeeper' }
You can do so using the include_role module. See docs
According to the docs it was introduced in Ansible 2.2 already (not in 2.3 as others have stated).
The code would then look like
- name: Use role in loop
ansible.builtin.include_role:
name: my-role
vars:
some_role_variable: '{{ loop_var }}'
loop:
- '{{ roleinput1 }}'
- '{{ roleinput2 }}'
loop_control:
loop_var: loop_var
Here is a code sample for using include_role looping on my_array:
- name: Use role in loop
include_role:
name: myrole
loop: "{{ my_array }}"

Resources