Krikri::ConditionalEvaluator
Constants
The whole-expression bare lookup('env', LITERAL) whose real 2.19.11
lineage origin is the tagged "<environment variable 'LITERAL'>" -
the only lookup origin shape this engine emits in strict-conditional
error wording (both quote styles accept either arg spelling; the
arg group is picked by which capture matched).
Precompiled regular expressions for condition parsing.
Eliminates runtime regex compilation in hot when: and test paths.
version_compare is Ansible's older alias for the version
test and is still accepted by ansible-core 2.19 (verified live,
round173). Missing it here was benign while conditionals were
lenient - the expression fell through to the generic comparison
splitter, which mistook the >= INSIDE the quoted operator
argument for a real comparison operator and quietly evaluated
false. Once 0.9.548 made a bare undefined reference RAISE, that
same misparse started hard-failing the task ("'')' is undefined")
for the extremely common x is version_compare(min, '>=')
version-gate idiom.
Class methods
Compile-time-invalid filter/test name check for the strict-undefined PROBE (Krikri.strict_undefined_probe_message): true when the condition carries a name the evaluators cannot resolve. ansible-core COMPILES the whole template before evaluating any operand, so real fails such an expression with the Syntax error wording no matter which clause would have been reached first - the probe must decline (not raise an undefined-value message over it) so #evaluate_measured's own validate_filter_names/validate_test_names wording surfaces unchanged.
Ansible never pre-renders {{ }} out of a conditional: both
when: and assert's that: items are compiled as raw Jinja
EXPRESSIONS (Templar.evaluate_expression -> Parser(state="variable")),
so a balanced {{ ... }} anywhere outside a string literal is a
TemplateSyntaxError and create_template_error(is_expression=True)
composes "Syntax error in expression." + " Template delimiters are
not supported in expressions." + ": " + Jinja's own parse message
(the message property drops the trailing period when joining the
cause - live-verified byte for byte vs ansible-playbook 2.19.11:
when: 1 >= {{ 1 }} and assert: that: [a.b >= {{ x }}] both fatal
"Syntax error in expression. Template delimiters are not supported
in expressions: expected token ':', got '}'", found via
chriswayg.mailcow's and rockandska.rabbitmq's own assert preflight
tasks, rounds 1500413/1500208, where this engine rendered the
delimiters away and PASSED the task).
Returns the composed message, or nil when the conditional is fine:
- whole-template conditionals (
{{ x }}and nothing else) take Ansible's legacy all-template path instead - deprecation warning, then render (live-verified:when: "{{ 1 == 1 }}"warns and passes), so they are excluded here exactly the way the caller's maybe_conditional_delimiters_deprecation detects them; - a
{{ }}inside a string literal (that: name == '{{ x }}') is a CONST template Jinja parses fine - quoted spans are skipped; - the parse message is Jinja's for this shape: a balanced
{{ }}misparses as a nested dict literal, so the parse dies at the inner}expecting the dict's:; an unclosed{{runs off the end of the template.{% %}/{# #}in a conditional is likewise a Jinja parse error in real, but its message is position/content-dependent and not emulated here yet.
Whether the WHOLE condition is a single is defined-family test
(optionally over a filter chain feeding the test). The strict-
undefined probe declines this shape: real Ansible never fails a
conditional on it - the test's tolerance covers the entire chain
feeding it (live-verified vs 2.19.4: when: d['missing'] is defined skips, never errors; and hwwilliams.duplicati's
when: duplicati_release_url_list | list | first is defined,
issue #730, likewise skips with an undefined head where the
probe's strict evaluation raised) - and the is-defined handlers
below answer the test leniently instead.