Best way to build a configurable when statement ?

In order to get instances matching some criteria, I wrote the following tasks file:

---
# Required variables :
# - deployment_type: "vm" or "container"
# - cmp_operator: '<', '>', '<=', '>=' or '=='
# - cmp_days: number of days (positive or negative) from today to obtain the comparison date
#
# Output variable :
# - matching_instances

- name: Get comparaison date
  ansible.builtin.set_fact:
    __test_date: "{{ lookup('ansible.builtin.pipe', 'date -d \"' + cmp_days + ' days\" +%d-%m-%Y') }}"

- name: Call REST API to list all instances
  ansible.builtin.uri:
    url: "XXXXXXXXXXXXXXXXXXXXXXXX"
    method: GET
    status_code: 200
    body_format: json
  register: __all_instances

- name: Init return variable
  ansible.builtin.set_fact:
    matching_instances: []

- name: Built return variable
  ansible.builtin.set_fact:
    matching_instances: "{{ matching_instances + [item] }}"
  when: >
    item.{{ deployment_type }}_deployment is defined and
    item.{{ deployment_type }}_deployment.end_date is defined and
    (item.{{ deployment_type }}_deployment.end_date | to_datetime("%d-%m-%Y")) {{ cmp_operator }} (__test_date | to_datetime("%d-%m-%Y"))
  loop: "{{ __all_instances.json.results }}"
  loop_control:
    label: "{{ item.name }}"

It can be used the following way:

- name: Get expired VM instances
  ansible.builtin.include_tasks: get_instances_by_end_date_task.yml
  vars:
    deployment_type: "vm"
    cmp_operator: "<"
    cmp_days: "0"

or

- name: Get container instances that will end in 2 weeks
  ansible.builtin.include_tasks: get_instances_by_end_date_task.yml
  vars:
    deployment_type: "container"
    cmp_operator: "=="
    cmp_days: "+14"

I did some tests and it works: the matching_instances variable is filled with expected instances. But I got the following warning: [WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. about the statement in the tasks file.

The way I used jinja in the when statement is not usual. So I don’t know whether I should take into account or ignore this warning (whose purpose seems to be to prevent another problem as in when statements should not include jinja2 templating delimiters). Is it risky to ignore it in my case?

More generally, what is the best way to build a configurable when statement?

Can you try something like this instead:

  when: >
    item[deployment_type % '_deployment'] is defined and
    item[deployment_type % '_deployment']['end_date'] is defined and
    (item[deployment_type % '_deployment']['end_date'] | to_datetime("%d-%m-%Y")) == (__test_date | to_datetime("%d-%m-%Y")) if cmp_operator == '==' else ... # <- you have to add all possible `cmp_operator` values here.

This is the only way I can think of that removes templating. Yeah, the operator part is quite ugly.

I’d probably create a user-defined test plugin to help reducing the ugliness.

1 Like