class

Krikri::VariableSubstitutor::VariableLookup

Inherits Reference < Object

VariableLookup - Handles all forms of variable access

  • Simple: {{ myvar }}
  • Nested: {{ user.name.first }}
  • Indexed: {{ array[0] }}, {{ dict['key'] }}

Constants

COMPUTED_INDEX_CHARS = {'~', '+', '*', '/', '%', '(', ')'}

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.

REGEX_METHOD_FIND = /^find\(\s*(['"])(.*)\1\s*\)$/
REGEX_METHOD_LSTRIP = /^lstrip\(\s*(?:(['"])(.*)\1\s*)?\)$/
REGEX_METHOD_RSTRIP = /^rstrip\(\s*(?:(['"])(.*)\1\s*)?\)$/
REGEX_METHOD_SPLIT = /^split\(\s*(['"])(.*)\1\s*\)$/
REGEX_METHOD_STRIP = /^strip\(\s*(?:(['"])(.*)\1\s*)?\)$/

Constructors

Instance methods

apply_method_suffix(current : JSON::Any, suffix : String) : JSON::Any | Nil

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).

Source
format_value(value : JSON::Any) : String
Source
format_value_output(value : JSON::Any) : String

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.

Source
indexed(expr : String) : String

Indexed access (array or hash) Example: mylist[0], mydict['key']

Source
nested(expr : String) : String

Nested variable access Example: user.name, config.database.host

Source
python_repr(value : JSON::Any) : String

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).

Source
rerender_var_value(value : JSON::Any) : JSON::Any

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')).

Source
resolve(expr : String) : JSON::Any | Nil
Source
simple(name : String) : String

Simple variable lookup

Source
walk(start : JSON::Any, suffix : String) : JSON::Any | Nil

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.

Source