I am attempting to create an installation ansible playbook that automates the installation of many different installers. I am able to figure out the installation of these programs just fine, but I'm having a tough time creating a selector to select which installers to use.
In a previous playbook I was able to find a trick by using a vars_prompt
which then creates a variable with a value that you type in which looks like this:
vars_prompt:
- name: "san_location"
prompt: "\nWhat SAN(s) do you want to mount?\n1- SAN1\n2- SAN2\n3- Both\n"
private: no
tasks:
- name: Add SAN1 MDC1 to host file
lineinfile:
state: present
path: '/etc/hosts'
line: 192.168.x.x SAN1
when: ( san_location == "1" ) or
( san_location == "3" )
This allows you to select a 1, 2, or 3 and execute tons of tasks based upon a user input/selection. Now I am trying to do this but by taking a playbook that has a "find" module in it that looks for all of the installers in a directory and lists them to be selected to install.
Here is the find task:
tasks:
- name: Register all files
find:
paths: "{{ installer_path }}"
patterns: '*.pkg,*.dmg'
file_type: file
register: installers
Is there any built in way in Ansible to make a list of these files selectable and then execute tasks based upon that?
For example, given the directory
shell> tree installers/
installers/
├── A
├── B
└── C
The playbook below
shell> cat pb.yml
- hosts: localhost
tasks:
- pause:
prompt: "Select installer {{ item|basename }}? [y/n]"
register: out
loop: "{{ query('fileglob', 'installers/*')|sort }}"
loop_control:
label: "{{ item|basename }}"
- debug:
msg: "install {{ item.item|basename }}"
loop: "{{ out.results }}"
loop_control:
label: "{{ item.item|basename }}"
when: item.user_input == 'y'
select the first two installers (A, B) and skip the last one (C)
shell> ansible-playbook pb.yml
PLAY [localhost] *****************************************************************************
TASK [pause] *********************************************************************************
[pause]
Select installer A? [y/n]:
y^Mok: [localhost] => (item=A)
[pause]
Select installer B? [y/n]:
y^Mok: [localhost] => (item=B)
[pause]
Select installer C? [y/n]:
n^Mok: [localhost] => (item=C)
TASK [debug] *********************************************************************************
ok: [localhost] => (item=A) =>
msg: install A
ok: [localhost] => (item=B) =>
msg: install B
skipping: [localhost] => (item=C)
PLAY RECAP ***********************************************************************************
localhost: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
If you want to use the module find
the playbook below gives the same results
- hosts: localhost
tasks:
- find:
paths: "{{ playbook_dir }}/installers"
recurse: true
register: installers
- pause:
prompt: "Select installer {{ item|basename }}? [y/n]"
register: out
loop: "{{ installers.files|map(attribute='path')|sort }}"
loop_control:
label: "{{ item|basename }}"
- debug:
msg: "install {{ item.item|basename }}"
loop: "{{ out.results }}"
loop_control:
label: "{{ item.item|basename }}"
when: item.user_input == 'y'
The next option is to select a single installer
- hosts: localhost
vars:
installers: "{{ _find.files|map(attribute='path')|sort }}"
tasks:
- find:
paths: "{{ playbook_dir }}/installers"
recurse: true
register: _find
- pause:
prompt: |
Select installer [{{ range(1, installers|length + 1)|join(',') }}]
{% for i in installers %}
{{ loop.index }} ... {{ i|basename }}
{% endfor %}
register: out
- debug:
msg: "install {{ installers[out.user_input|int - 1]|basename }}"