Is it possible to reuse ansible tasks with some parameters override? - ansible

I want to create playbook to download only any package installed by ansible.
There is a lot of yum state=installed tasks in my ansible roles. Is there a way to include that roles without state=installed, but with download_only and download_dir instead?
ansible 2.8

No. It is not possible. Use variables. For example
- yum:
state: "{{ my_role1_yum_state|default(omit) }}"
download_only: "{{ my_role1_yum_download_only|default(omit) }}"
download_dir: "{{ my_role1_yum_download_dir|default(omit) }}"
...

Related

Is there a way to create different repository based on a condition in the same task in Ansible playbook?

I am trying to shorten the number of tasks I have in my playbook. I am creating a yum repository on Linux hosts and adding a different baseurl depending on the OS version.
It looks like this:
vars:
my_version: "{{ hostvars[inventory_hostname].ansible_distribution | int }}"
- name: create mcrepo yum repo
yum_repository:
name: mcrepo
description: mcrepo
baseurl: "{{ yum_repo_url }}"
gpgcheck: no
enabled: yes
sslverify: no
when: my_version is version('8.0', operator='lt')
- name: create mcrepo yum repo
yum_repository:
name: mcrepo
description: mcrepo
baseurl: "{{ yum_repo_url_8 }}"
gpgcheck: no
enabled: yes
sslverify: no
when: my_version is version('8.0', operator='ge')
Is there a way to combine these two tasks into just one so one of them doesn't always get skipped? On the linux hosts I have ansible 2.9 or 2.10.
I couldn't find a way to implement a case statement or something similar.
You could use an inline if in order to get the right variable containing the yum repository URL:
baseurl: >-
{{
yum_repo_url
if my_version is version('8.0', operator='lt')
else yum_repo_url_8
}}

In Ansible, can I re-use a role like a subroutine?

Ansible v2.11
I install a lot of applications on a Windows target, and most of them follow the same routine - download, unzip, for example.
- name: Download the zip file
win_url:
url_username: user
url_password: password
url: "{{ some_url }}"
dest: "C:\\temp\\{{ some_archive }}"
- name: Unzip the archive
win_unzip:
src: "C:\\temp\\{{ some_archive }}"
dest: "{{ archive_install_dir }}"
Is it possible to re-use the above role in "other roles" where I just pass in the some_archive and archive_install_dir variables for example? I set up my roles so each one has its own Git repository.
You can use include_role or import_role to pull it in.

Ansible import role run conditionally

I am writing a parent ansible role that runs another role though import_role. The idea that this sibling role (staticdev.pyenv) only runs when an argument pyenv_python_versions is passed, otherwise this is skipped.
According to the official documentation, I tried the following approach:
parent/tasks/main.yml
---
- name: Install pyenv
import_role:
name: staticdev.pyenv
vars:
pyenv_owner: "{{ ansible_env.USER }}"
pyenv_path: "{{ ansible_env.HOME }}/pyenv"
pyenv_global: "{{ pyenv_global }}"
pyenv_python_versions: "{{ pyenv_python_versions }}"
pyenv_virtualenvs: []
when: pyenv_python_versions
I am using currently ansible 4.1.0 (core 2.11.1), and when I test it on Debian 11 (image: cisagov/docker-debian11-ansible:latest) it executes the role anyway, even without any value for pyenv_python_versions. when is not being considered and I also tried with include_role. Complete logs can be found here.
Any idea?
UPDATE: changed condition when from to pyenv_python_versions as suggested by #lonetwin.
The problem was role import was replicating variables from the imported role (pyenv_global, pyenv_python_versions and pyenv_virtualenvs), in this case you solve it just by omitting imported role params (they will be overwritten if you create new defaults for them).
Solution:
---
- name: Install pyenv
import_role:
name: staticdev.pyenv
vars:
pyenv_owner: "{{ ansible_env.USER }}"
pyenv_path: "{{ ansible_env.HOME }}/pyenv"
when: pyenv_python_versions

include_role combined with_items for role name

I want to selectively execute roles based on a list of roles passed to the play book. However, this fails
- name: create container definitions for selected services
include_role:
name: "{{ item }}"
with_items: "{{ selected_service_list }}"
with
ERROR! 'item' is undefined
I gather it is impossible to use a list of role names to control when we execute roles. Let me know if you know how to do this
For ansible latest 2020-07 one can follow this (example from ansible documentation)
For ansible 2.3 one should upgrade or can use this approach
- { role: myservice, when: "'myservice' in selected_service_list" }

Ansible dictionary - Package validation by host, name and version

I have several packages (package-A, package-B, ...) installed through various hosts (host1, host2, ...).
I need to check if package-A with version 1.2.3, for example, is installed in host1, host2 and host3, need to check if package-B with version 3.2.1 is installed in host1, host3 and host9, ..., informing the user that they are installed or not with the specified version.
I have a playbook (validatorPlaybook.yml) who's purpose is to check and inform the user about installed versions in certain hosts defined in a dictionary in an outside playbook varsPlayBook1.yml:
#validation dictionary
packsDict:
pck1:
hosts: host1, host2, host3
version: 1.2.3
package_name: package-A
pck2:
hosts: host1, host3, host9
version: 3.2.1
package_name: package-B
(...)
This is the script I'm using in validatorPlaybook.yml:
---
- name: check if packages in dict are with the correct version
yum:
list="{{ item.package_name }}-{{ item.version }}"
loop: "{{ lookup('dict', packsDict) }}"
...
As you can see some packages are installed in one host and others are in another.
How can I run that yum list command by host? Is it possible?
Note: I will not discuss here the overall structure and goal of your current implementation. I think it can be greatly improved (by defining packages to check in inventory for example...)
The easiest solution I see from the existing script requires to transform your validation data a bit. Put the hosts in a list like so:
packsDict:
pck1:
hosts:
- host1
- host2
- host3
version: 1.2.3
package_name: package-A
pck2:
hosts:
- host1
- host3
- host9
version: 3.2.1
package_name: package-B
I take for granted that your actual playbook already runs on all needed hosts and that the names inside your validation dict are aligned to the names of hosts in your inventory. Modifying your task like the following should meet your requirement.
- name: check if packages in dict are with the correct version
yum:
list: "{{ item.package_name }}-{{ item.version }}"
loop: "{{ lookup('dict', packsDict) }}"
when: inventory_hostname in item.hosts

Resources