module

Krikri::LookupPlugins

Controller-side lookup plugin helpers shared by every template engine (paths, config defaults, url/sequence/csvfile/ini/password lookups). Plain String in, plain values out, so no engine's value type leaks in.

Constants

PASSWORD_CHARS = ((("a".."z").to_a + ("A".."Z").to_a) + ("0".."9").to_a) + [".", ",", ":", "-", "_"]
PASSWORD_LENGTH = 20

Class methods

ansible_config_typed_value(name : String, plugin_kwargs : Hash(String, String) = {} of String => String) : JSON::Any

The config lookup's value with ansible's own TYPE casting applied: pathspec options come back as a real JSON array, everything else as the plain string. *plugin_kwargs carries the call's key=value keyword arguments (strings already unquoted) - remote_tmp is only resolvable as a plugin-scoped option (plugin_type/plugin_name), so a bare lookup('config', 'remote_tmp') with no plugin kwargs stays on the unknown-option "" fallback rather than inventing a value real rejects with "No config definition exists".

Source
csvfile_lookup(raw_arg : String) : String | Nil

lookup('csvfile', 'key file=data.csv delimiter=, col=1') - same logic as ExpressionEvaluator's own #evaluate_csvfile_lookup.

Source
expand_home(path : String) : String

Ansible's file-family lookups run the term through os.path.expanduser BEFORE the search-path walk, so a leading ~ names the controller user's home, not a role-relative files/~/.ssh/... (issue #52: the andrewrothstein.ssh-user-keygen idiom lookup('file', '~/.ssh/id_rsa.pub') reads fine in ansible-playbook but raised "Unable to access the file" here). Only a bare ~ or ~/-prefixed term expands; ~user/... stays untouched (it implies a controller userdb lookup with no parallel in this engine).

Source
fetch_url_lines(url : String, redirects_left : Int32 = 5, split_lines : Bool = true) : Array(String) | Nil

Mirrors ExpressionEvaluator's own #fetch_url_lines (redirect- following GET, stripped/blank-rejected lines), returning a real Array(String)? here instead of JSON array text - nil on any failure (unreachable host, non-2xx, too many redirects). split_lines=False matches Ansible's url lookup's own option: the WHOLE response body comes back as one untouched string (no strip, no line splitting, newlines preserved) - diodonfrost.puppet_agent feeds a PGP key through it into apt_key, and comma-joining the armor lines breaks the key import.

Source
ini_lookup(raw_arg : String, role_path : String | Nil = nil) : String | Nil

lookup('ini', 'value section=section1 file=file.ini') - same logic as ExpressionEvaluator's own #evaluate_ini_lookup.

Source
password_lookup(raw_arg : String, role_path : String | Nil) : String

lookup('password', 'path [length=N]') - generates a random password ONCE and persists it to path (Ansible's own behavior: a later run/lookup reads the same file back rather than generating a new value every time). Same logic as ExpressionEvaluator's own #evaluate_password_lookup.

Source
resolve_first_found_roots(path : String, role_path : String | Nil) : Array(String)

A relative first_found paths: entry can resolve against either the role's own ROOT directory OR (buluma.confluence's own paths: ['../vars'] idiom, Ansible resolves this relative to tasks/, not role_path itself) its tasks/ subdirectory - same two-root search ExpressionEvaluator's own #resolve_first_found_roots applies (see that method's comment for the full story and the round165 repro that found this gap independently on this, separate, Crinja-backed evaluator).

Source
resolve_lookup_path(path : String, role_path : String | Nil) : String

Real file lookup's find_file_in_search_path probe order, observed against ansible-playbook (pgvillage.linux, issue #308): the role's files/ dir, then the role ROOT, then the directory of the task file doing the lookup (roles/<r>/tasks/ for an ordinary role task). A role's query('file', 'os-specifics-Debian.yml') naming a file that lives in its own tasks/ dir returns the content in real, where files/-forced resolution missed it and handed the caller None (and | length then died: "object of type 'NoneType' has no len()"). files/ stays the no-candidate default so missing-file outcomes - and the password lookup's persist target - keep landing where they did before the search widened.

Source
resolve_template_lookup_path(path : String, role_path : String | Nil) : String

Real template lookup's file search: find_file_in_search_path( variables, 'templates', term) - the role's templates/ directory comes FIRST, then the rest of the role-relative search path (files/, role root). resolve_lookup_path above only ever looked under files/, so a lookup('template', 'redis.conf.j2') inside a role never found the role's own template and its missing-file fallback got written straight into task targets (hifis.redis, round 1300014: blockinfile wrote the literal string "undefined" into /etc/redis/redis.conf, and redis-server then refused to start with "Bad directive or wrong number of arguments").

Source
sequence_lookup(raw_arg : String) : Array(String)
Source