Krikri::VariableSubstitutor::VariableLookup
VariableLookup - Handles all forms of variable access
- Simple: {{ myvar }}
- Nested: {{ user.name.first }}
- Indexed: {{ array[0] }}, {{ dict['key'] }}
Constants
Chars whose presence in a bracket index means the index is a Jinja
EXPRESSION ansible evaluates to the real key before subscripting
(string concat item ~ '.service', arithmetic a + b, call
parens f(x)), not a literal/identifier key. A subscript like
"services[item ~ '.service']" previously fell through this
lookup's literal-key branch with the whole unevaluated text as the
dict key and answered undefined even for an existing service
(guidugli.firewall's "Disable conflicting firewall services when
present" loop skipped its nftables item while real ansible ran
it). A fully-quoted literal can never reach this check (returned
earlier), and any engine failure or non-key-shaped result keeps
the long-standing literal-key fall-through unchanged.
Constructors
Instance methods
Applies a dotted/method-call SUFFIX (e.g. "splitlines()", the
text after a lookup(...) call's own closing paren) to an
already-resolved value - used by ExpressionEvaluator's
filter_chain_special_head for lookup(...).method() chained
directly with no | filter in between (round 199, bodsch.tomcat).
Renders a variable's value the way Ansible/Jinja2 does when it's
interpolated directly into template text - notably, Python's
capitalized True/False for booleans, not Crystal's lowercase
true/false (verified against ansible-playbook: a {{ boolvar }}
in a copy/template content string renders "True"/"False"). Public
(not just used internally) so FilterEngine's caller can render a
filter chain's final JSON::Any result the same way a plain variable
lookup would be.
The FINAL, user-facing rendering of a {{ }} span's value:
identical to #format_value except that a container comes out in
Python's repr form, which is what Ansible produces
({{ ['a', 'b'] }} renders ['a', 'b'] there, and rendered
["a","b"] here). Only the outermost substitution may use this -
anything internal needs #format_value's JSON, per its comment.
Indexed access (array or hash) Example: mylist[0], mydict['key']
Nested variable access Example: user.name, config.database.host
Python's repr for a JSON::Any, used to render containers the
way Ansible does. Scalars follow Python's own spellings
(True/False/None); strings follow its quote choice: single
quotes normally, double quotes when the string contains a single
quote and no double quote, and single quotes with \' escapes
when it contains both (verified against Ansible's output
for all three shapes).
Resolves any of the three access forms above to its raw JSON::Any
value (nil if undefined) rather than a pre-stringified String - used
by FilterEngine so a filter chain ({{ x | sort | join(',') }}) can
carry real array/hash structure from one filter to the next instead
of collapsing to a string after every single filter.
Public re-render entry for consumers that fetch a value by NAME at
runtime (the vars lookup plugin) rather than through a written
{{ }} reference: Ansible's vars lookup runs the found value
through the templar, so a lazily-templated role var renders at the
lookup instead of surfacing as raw {{ }} text (round 5250000,
sscheib.openwrt_extroot's assert loop validating
lookup('ansible.builtin.vars', '_ext_quiet_assert')).
Walks a dotted/indexed suffix (.stat.exists, "[0].name",
".days") against an already-resolved value, for a caller that
computed the base value itself (ExpressionEvaluator's
parenthesized-sub-expression handling: ( a - b ).days needs to
look .days up on the result of a - b, not on some variable
named "( a - b )") rather than looking it up from @vars the way
resolve/resolve_indexed/resolve_nested always do. An empty suffix
returns start unchanged.