I am trying to develop a Ansible playbook to select and display the list of datastores in vCenter, however for validation purpose I should not select the datastore that contains the local
or Local
in its name.
For example consider the following 4 datastores:
datastore:local8
TQAESXHOST05-Local01
vnx_dwcesxbl_ecom_lun7
tqaesx37d_1
It should only select:
vnx_dwcesxbl_ecom_lun7
tqaesx37d_1
Should not select:
datastore:local8
TQAESXHOST05-Local01
Here is the playbook
tasks:
- name: List of datastores with calculated values
set_fact:
ds_size_list: "{{ ds_size_list | default([]) [{ 'name' : item.name, 'capacity' : item.capacity, 'freeSpace' : item.freeSpace, 'freeSpaceAfter' : freeSpaceAfter | int, 'percentFreeAfter' : percentFreeAfter | int }] }}"
with_items: "{{ datastore_info.datastores }}"
vars:
freeSpaceAfter: "{{ item.freeSpace - (vm_size_b | int) }}"
percentFreeAfter: "{{ freeSpaceAfter | int / item.capacity * 100 }}"
when: item.accessible
when: when: item.name is regex(?!local) #should exclude datastores containing "local" word
Need suggestions on writing the regex expression to exclude the datastores containing the word local
.
CodePudding user response:
Using a regex for this is probably an overkill. You can use the in
test of Jinja to assert that a sub-string is contained in a string — since a string is just a sequence of characters, the in
test works on strings.
So, given:
- debug:
msg: "{{ item.name }}"
loop: "{{ datastore_info.datastores }}"
when:
- item.accessible
- "'Local' not in item.name"
- "'local' not in item.name"
loop_control:
label: "{{ item.name }}"
vars:
datastore_info:
datastores:
- name: datastore:local8
accessible: yes
- name: TQAESXHOST05-Local01
accessible: yes
- name: vnx_dwcesxbl_ecom_lun7
accessible: yes
- name: tqaesx37d_1
accessible: yes
This yield:
TASK [debug] ****************************************************************************
skipping: [localhost] => (item=datastore:local8)
skipping: [localhost] => (item=TQAESXHOST05-Local01)
ok: [localhost] => (item=vnx_dwcesxbl_ecom_lun7) =>
msg: vnx_dwcesxbl_ecom_lun7
ok: [localhost] => (item=tqaesx37d_1) =>
msg: tqaesx37d_1
And if you don't care about the casing of local
at all (Local
, lOcAl
, ...), you can even simplify it further with the lower
filter and do:
when:
- item.accessible
- "'local' not in item.name | lower"
CodePudding user response:
Q: "Exclude the datastores containing the word 'local' or 'Local'."
A: Reject the items where the attribute name can search Python regex '[lL]ocal'
. For example, given the data below for testing
datastores:
- {name: datastore:local8, capacity: 100, freeSpace: 10}
- {name: TQAESXHOST05-Local01, capacity: 200, freeSpace: 20}
- {name: vnx_dwcesxbl_ecom_lun7, capacity: 300, freeSpace: 30}
- {name: tqaesx37d_1, capacity: 400, freeSpace: 40}
the task
- set_fact:
ds_size_list: "{{ ds_size_list|default([])
[{'name': item.name,
'capacity': item.capacity,
'freeSpace' : item.freeSpace,
'percentFreeAfter': percentFreeAfter|int }] }}"
loop: "{{ datastores|rejectattr('name', 'search', '[lL]ocal') }}"
vars:
percentFreeAfter: "{{ item.freeSpace|int / item.capacity|int * 100 }}"
gives
ds_size_list:
- capacity: 300
freeSpace: 30
name: vnx_dwcesxbl_ecom_lun7
percentFreeAfter: 10
- capacity: 400
freeSpace: 40
name: tqaesx37d_1
percentFreeAfter: 10
If you want to keep all attributes of the items you can combine additional attributes. This simplifies the code. For example, the task below gives the same result
- set_fact:
ds_size_list: "{{ ds_size_list|default([])
[item|combine({'percentFreeAfter': percentFreeAfter|int})] }}"
loop: "{{ datastores|rejectattr('name', 'search', '[lL]ocal') }}"
vars:
percentFreeAfter: "{{ item.freeSpace|int / item.capacity|int * 100 }}"