My goal is to create a registered variable that I can use to search through and register other variables based on it. Mostly it is a find module that is searching for files which then, based upon the filename, should be registered in other variables. Here is an example of what I have but it is not filtering out the variables properly:
- name: Register all files
find:
paths: ./files/
patterns: '*.pkg,*.dmg'
file_type: file
register: installers
- name: Find Slack Installers
find:
paths: "{{ item }}"
patterns: "*slack*"
loop: "{{ installers.files|map(attribute='path')|map('basename')|list }}"
register: slack_installers
- debug:
msg: "{{ slack_installers }}"
This then outputs the following:
TASK [Find Slack Installers] *******************************************************************************************************************************
ok: [localhost] => (item=slack.19.5.dmg)
ok: [localhost] => (item=slack.19.6.pkg)
ok: [localhost] => (item=box.1.2.3.dmg)
(ignore the versions of things, these are just fake names/versions but I'm just testing the find functionality)
As you can see the "Find Slack Installers" task is just registering everything within the "installers" variable rather than actually finding only things with the slack pattern.
EDIT FOR extended question:
set_fact:
"{{ item.item|basename|lower }}_installers": "{{ installers.files|map(attribute='path')|map('basename')|list|select('search', '{{ item.item|basename|lower }}') }}"
loop: "{{ selected_installers.results }}"
loop_control:
label: "{{ item.item|basename }}"
when: item.user_input == 'y' and
item.item == ( item.item|basename )
Using the find
module twice in a row does not make sense.
The find
module is to find files in a folder and its subfolders, but not to filter a list (even if file names are in this list), as you tried here. Have a look at the examples for find
in the Ansible docs.
However, you have two possibilities.
find
with using the search word slack
in pattern:Add the search word slack
directly as pattern in the find
module: *slack*.pkg,*slack*.dmg
.
- name: Register all files
find:
paths: ./files/
patterns: '*slack*.pkg,*slack*.dmg'
file_type: file
register: installers
- debug:
msg: "{{ installers.files|map(attribute='path')|map('basename')|list }}"
Result:
TASK [Register all files] **************
ok: [localhost]
TASK [debug] ***************************
ok: [localhost] => {
"msg": [
"slack.19.5.dmg",
"slack.19.6.pkg"
]
}
find
to search only for the packages, then filtering your list:Using select('regex', 'slack')
you can filter the list by specific words in regex syntax, in your case specifying slack
is enough.
- name: Register all files
find:
paths: ./files/
patterns: '*.pkg,*.dmg'
file_type: file
register: installers
- debug:
msg: "{{ installers.files|map(attribute='path')|map('basename')|list|select('regex', 'slack') }}"
Result:
TASK [Register all files] **************
ok: [localhost]
TASK [debug] ***************************
ok: [localhost] => {
"msg": [
"slack.19.5.dmg",
"slack.19.6.pkg"
]
}
Nested jinja expressions are not allowed and not required.
If you want to specify a variable or a filter expression, just write it without using another jinja expression with {{
and }}
.
Try the following select:
select('search', item.item|basename|lower )
Tip
If you use several operators and are not sure which operator binds stronger, you can also use parentheses like in mathematics.
The parenthesis should not be necessary at this point, but it does not interfere.
select('search', (item.item|basename|lower) )
But if you want to get e.g. the second element (index=1) of your list, then the term looks like this:
( installers.files|map(attribute='path')|map('basename')|list )[1]
At this point, the parentheses are important so that the inner expression is evaluated first, and then the corresponding element can be accessed.