|
| 1 | +## The `Puppet::LookupContext` object |
| 2 | + |
| 3 | +To support caching and other needs, Hiera provides backends a special `Puppet::LookupContext` object, which has several methods you can call for various effects. |
| 4 | + |
| 5 | +* In [Ruby functions](./functions_ruby_overview.html), this is a normal Ruby object of class `Puppet::LookupContext`, and you can call methods with standard Ruby syntax (like `context.not_found`). |
| 6 | +* In [Puppet language functions](./lang_write_functions_in_puppet.html), the context object appears as a special data type (Object) that has methods attached. Right now, there isn't anything else in the Puppet language that acts like this. |
| 7 | + |
| 8 | + You can call its methods using Puppet's [chained function call syntax](./lang_functions.html#chained-function-calls) with the method name instead of a normal function --- for example, `$context.not_found`. For methods that take a block, use Puppet's lambda syntax (parameters outside block) instead of Ruby's block syntax (parameters inside block). |
| 9 | + |
| 10 | +The following methods are available: |
| 11 | + |
| 12 | +* [`not_found()`][method_not], for bailing out of a lookup. |
| 13 | +* [`interpolate(value)`][method_interpolate], for handing Hiera interpolation tokens in values. |
| 14 | +* [`environment_name()`][method_env], to find out which environment this is. |
| 15 | +* [`module_name()`][method_module], to find out which module this is. |
| 16 | +* [`cache(key, value)`][method_cache], for caching information between function runs. |
| 17 | +* [`cache_all(hash)`][method_cache_all], for caching several things at once. |
| 18 | +* [`cached_value(key)`][method_cached], for retrieving cached values. |
| 19 | +* [`cache_has_key(key)`][method_haskey], for checking the cache. |
| 20 | +* [`cached_entries()`][method_allcached], for dumping the whole cache. |
| 21 | +* [`cached_file_data(path) {|content| ...}`][method_cached_file], for high-performance reading of data files. |
| 22 | +* [`explain() || { 'message' }`][method_explain], for helpful debug messages. |
| 23 | + |
| 24 | + |
| 25 | +### `not_found()` |
| 26 | + |
| 27 | +[method_not]: #notfound |
| 28 | + |
| 29 | +Tells Hiera to move on to the next data source. Call this method when your function can't find a value for a given lookup. **This method does not return.** |
| 30 | + |
| 31 | +For `data_hash` backends, use this when the requested data source doesn't exist. (If it exists and is empty, return an empty hash.) Missing data sources aren't an issue when using `path`/`glob` settings, but are important for backends that locate their own data sources. |
| 32 | + |
| 33 | +For `lookup_key` and `data_dig` backends, use this when a requested key isn't present in the data source or the data source doesn't exist. Don't return `undef`/`nil` for missing keys, since that's a legal value that can be set in data. |
| 34 | + |
| 35 | +### `interpolate(value)` |
| 36 | + |
| 37 | +[method_interpolate]: #interpolatevalue |
| 38 | + |
| 39 | +Returns the provided value, but with any Hiera interpolation tokens (like `%{variable}` or `%{lookup('key')}`) replaced by their value. This lets you opt-in to allowing Hiera-style interpolation in your backend's data sources. Works recursively on arrays and hashes; hashes can interpolate into both keys and values. |
| 40 | + |
| 41 | +In `data_hash` backends, interpolation is automatically supported and you don't need to call this method. |
| 42 | + |
| 43 | +In `lookup_key` and `data_dig` backends, you **must** call this method if you want to support interpolation; if you don't, Hiera assumes you have your own thing going on. |
| 44 | + |
| 45 | +### `environment_name()` |
| 46 | + |
| 47 | +[method_env]: #environmentname |
| 48 | + |
| 49 | +Returns the name of the environment whose hiera.yaml called the function. Returns `undef` (in Puppet) or `nil` (in Ruby) if the function was called by the global or module layer. |
| 50 | + |
| 51 | +### `module_name()` |
| 52 | + |
| 53 | +[method_module]: #modulename |
| 54 | + |
| 55 | +Returns the name of the module whose hiera.yaml called the function. Returns `undef` (in Puppet) or `nil` (in Ruby) if the function was called by the global or environment layer. |
| 56 | + |
| 57 | +### `cache(key, value)` |
| 58 | + |
| 59 | +[method_cache]: #cachekey-value |
| 60 | + |
| 61 | +Caches a value, in a per-data-source private cache; also returns the cached value. |
| 62 | + |
| 63 | +On future lookups in this data source, you can retrieve values with `cached_value(key)`. Cached values are immutable, but you can replace the value for an existing key. Cache keys can be anything valid as a key for a Ruby hash. (Notably, this means you can use `nil` as a key.) |
| 64 | + |
| 65 | +For example, on its first invocation for a given YAML file, the built-in `eyaml_lookup_key` backend reads the whole file and caches it, and then decrypts only the specific value that was requested. On subsequent lookups into that file, it gets the encrypted value from the cache instead of reading the file from disk again. It also caches decrypted values, so that it won't have to decrypt again if the same key is looked up repeatedly. |
| 66 | + |
| 67 | +The cache is also useful for storing session keys or connection objects for backends that access a network service. |
| 68 | + |
| 69 | +#### Cache lifetime and scope |
| 70 | + |
| 71 | +Each `Puppet::LookupContext` cache only lasts for the duration of the current catalog compilation; a node can't access values cached for a previous node. |
| 72 | + |
| 73 | +Hiera creates a separate cache for each *combination of inputs for a function call,* including inputs like `name` that are configured in hiera.yaml but not passed to the function. So not only does each hierarchy level have its own cache, but hierarchy levels that use multiple paths have a separate cache for each path. |
| 74 | + |
| 75 | +If any inputs to a function change (for example, a path interpolates a local variable whose value changes between lookups), Hiera uses a fresh cache. |
| 76 | + |
| 77 | + |
| 78 | +### `cache_all(hash)` |
| 79 | + |
| 80 | +[method_cache_all]: #cacheallhash |
| 81 | + |
| 82 | +Caches all the key/value pairs from a given hash; returns `undef` (in Puppet) or `nil` (in Ruby). |
| 83 | + |
| 84 | +### `cached_value(key)` |
| 85 | + |
| 86 | +[method_cached]: #cachedvaluekey |
| 87 | + |
| 88 | +Returns a previously cached value from the per-data-source private cache. Returns `nil` or `undef` if no value with this name has been cached. See [`cache(key, value)`][method_cache] above for more info about how the cache works. |
| 89 | + |
| 90 | +### `cache_has_key(key)` |
| 91 | + |
| 92 | +[method_haskey]: #cachehaskeykey |
| 93 | + |
| 94 | +Checks whether the cache has a value for a given key yet. Returns `true` or `false`. |
| 95 | + |
| 96 | +### `cached_entries()` |
| 97 | + |
| 98 | +[method_allcached]: #cachedentries |
| 99 | + |
| 100 | +Returns everything in the per-data-source cache, as an iterable object. Note that this iterable object isn't a hash; if you want a hash, you can use `Hash($context.all_cached())` (in the Puppet language) or `Hash[context.all_cached()]` (in Ruby). |
| 101 | + |
| 102 | +### `cached_file_data(path) {|content| ...}` |
| 103 | + |
| 104 | +[method_cached_file]: #cachedfiledatapath-content- |
| 105 | + |
| 106 | +> **Note:** The header above uses Ruby's block syntax. To call this method in the Puppet language, you would use `cached_file_data(path) |content| { ... }`. |
| 107 | +
|
| 108 | +For best performance, use this method to read files in Hiera backends. |
| 109 | + |
| 110 | +Returns the content of the specified file, as a string. If an optional block is provided, it passes the content to the block and returns the block's return value. For example, the built-in JSON backend uses a block to parse JSON and return a hash: |
| 111 | + |
| 112 | +``` ruby |
| 113 | + context.cached_file_data(path) do |content| |
| 114 | + begin |
| 115 | + JSON.parse(content) |
| 116 | + rescue JSON::ParserError => ex |
| 117 | + # Filename not included in message, so we add it here. |
| 118 | + raise Puppet::DataBinding::LookupError, "Unable to parse (#{path}): #{ex.message}" |
| 119 | + end |
| 120 | + end |
| 121 | +``` |
| 122 | + |
| 123 | +On repeated access to a given file, Hiera checks whether the file has changed on disk. If it hasn't, Hiera uses cached data instead of reading and parsing the file again. |
| 124 | + |
| 125 | +This method **does not** use the same per-data-source caches as `cache(key, value)` and friends. It uses a separate cache that lasts across multiple catalog compilations, and is tied to [Puppet Server's environment cache]({{puppetserver}}/admin-api/v1/environment-cache.html). |
| 126 | + |
| 127 | +Since the cache can outlive a given node's catalog compilation, do not do any node-specific pre-processing (like calling `context.interpolate`) in this method's block. |
| 128 | + |
| 129 | +### `explain() { 'message' }` |
| 130 | + |
| 131 | +[method_explain]: #explain--message- |
| 132 | + |
| 133 | +> **Note:** The header above uses Ruby's block syntax. To call this method in the Puppet language, you would use `explain() || { 'message' }`. In both cases, the provided block must take zero arguments. |
| 134 | +
|
| 135 | +Adds a message, which appears in debug messages or when using `puppet lookup --explain`. The block provided to this function must return a string. |
| 136 | + |
| 137 | +This is meant for complex lookups where a function tries several different things before arriving at the value. Note that the built-in backends don't use the `explain` method, and they still have relatively verbose explanations; this is for when you need to go above and beyond that. |
| 138 | + |
| 139 | +Feel free to not worry about performance when constructing your message; Hiera never executes the explain block unless debugging is enabled. |
| 140 | + |
| 141 | + |
0 commit comments