Comparison Numeric Tests
Back in the collections chapter, select('even') and selectattr('status', 'equalto', 'running') used named tests without explaining why they exist as words instead of ordinary operators. This chapter closes that loop.
is equalto
when: status is equalto 'running'Functionally identical to status == 'running'. So why does a named version exist at all? Because select and selectattr need to accept a comparison as an argument — you can’t hand a filter an inline == expression, but you can hand it the string 'equalto' plus a value to compare against. Named tests are what make that possible.
is gt, is ge, is lt, is le
Named equivalents of >, >=, <, <= — same reasoning, same purpose:
when: age is gt 18vars:
ports: [22, 80, 443, 3000, 8080]
tasks:
- name: Select high ports
ansible.builtin.debug:
msg: "{{ ports | select('gt', 1024) | list }}"[3000, 8080]Here’s the full picture behind that Chapter 5 example, finally explained: select('gt', 1024) couldn’t be written as select(port > 1024) — there’s no single value to compare against yet at that point, just a filter waiting for a test name and an argument. 'gt' plus 1024 is exactly that.
is even And is odd
The same tests used unexplained back in the collections chapter:
msg: "{{ [1, 2, 3, 4, 5, 6] | select('even') | list }}"[2, 4, 6]Using These Same Tests With when:
Nothing stops you from using named tests directly in a when:, even outside a filter:
when: retry_count is gt 3
when: port_number is evenWhether you reach for is gt 3 or > 3 in a plain when: is mostly a matter of taste — both work identically there. Where named tests stop being optional is inside select/selectattr/reject/rejectattr, which have no other way to accept a comparison at all.
Revisiting select/selectattr Now That You Know What’s Inside
vars:
servers:
- name: web1
port: 8080
- name: db1
port: 22
tasks:
- name: Select servers with high ports
ansible.builtin.debug:
msg: "{{ servers | selectattr('port', 'gt', 1024) | map(attribute='name') | list }}"["web1"]Same pipeline shape as the collections chapter’s selectattr + map example — now with a full understanding of what 'gt' inside it actually is.
A Gotcha: Numeric Tests On Strings
This is the same trap from the numbers and lists chapters, showing up again in a third place:
vars:
port_str: "500"
tasks:
- name: This fails
ansible.builtin.debug:
msg: "{{ port_str is gt 100 }}"Comparing a string to a number fails, exactly the way sorting a mixed-type list failed back in the lists chapter. Convert first:
msg: "{{ port_str | int is gt 100 }}"TrueBest Practices
- Use named tests (
equalto,gt, and so on) when a comparison needs to be passed as an argument — insideselect,selectattr,reject, orrejectattr. In a plainwhen:, ordinary operators (==,>) work just as well and are often more familiar. - Convert with
| int/| floatbefore a numeric test, exactly the same discipline established for arithmetic — a numeric-looking string is still a string until you say otherwise.