I'm running a play against a number of servers where the first task performs a sql query to get the schema version for a database. The query returns "1"
(string) for instance when the schema version is 1. This is the structure of the response...
ok: [server.tld] => {
"db_result": {
"changed": false,
"executed_queries": [
"SELECT `value` FROM `registry` WHERE `setting` = 'schema_version'"
],
"failed": false,
"query_result": [
[
{
"value": "1"
}
]
],
"rowcount": [
1
]
}
}
In the next task I test to see if the schema version returned is less than the current version... in this case also 1
(int) but after a future upgrade we would test against 2
(int) which would cause all servers to run the patch that still return 1
. I use the Jinja filter | int
to cast to integer for a proper comparison.
- name: Copy schema update SQL file
copy: src=roles/db/files/{{ item.src }} dest=/tmp/{{ item.src }}
when: item.when
loop:
- src: schema_changes_v1.sql
when: "{{ db_result.query_result[0][0]['value'] | int }} < 1"
The problem is that even though the logical comparison is when: 1 < 1
which should resolve to false, it's still proceeding with the item in the loop rather than skipping to the next one....
changed: [server.tld] => (item={'src': 'schema_changes_v1.sql', 'when': '1 < 1'})
Why??
Ansible 2.12.2
The condition in when
is evaluated as it's already within the curly braces.
Edited:
But I didn't notice the most important thing in your example. The condition you're referring to is set as the value of when
key within the loop element - that means that it's evaluated as a string first. And a non-empty string in a real when
evaluates to true
- that's the reason why you task gets executed each time.
So, simply put the whole string into the curly braces so that you get a boolean instead of a string:
- name: Copy schema update SQL file
copy: src=roles/db/files/{{ item.src }} dest=/tmp/{{ item.src }}
when: item.when
loop:
- src: schema_changes_v1.sql
when: "{{ db_result.query_result[0][0]['value'] | int < 1 }}"