Exploring YAQL Expressions

The Newton release of Heat adds support for a yaql
intrinsic function, which allows you to evaluate yaql expressions
in your Heat templates. Unfortunately, the existing yaql
documentation is somewhat limited, and does not offer examples of many
of yaql’s more advanced features.

I am working on a Fluentd composable service for TripleO. I
want to allow each service to specify a logging source configuration
fragment, for example:

This generally works, but several parts of this fragment are going to
be the same across all OpenStack services. I wanted to reduce the
above to just the unique attributes, which would look something like:

I want to iterate over this list, adding default values for attributes
that are not explicitly provided.

The yaql language has a select function, somewhat analagous to the
SQL select statement, that can be used to construct a new data
structure from an existing one. For example, given the above data in
a parameter called sources, I could write:

…and then within the yaql expression, insert the value of
default_type into items that don’t provide an explicit value for the
type attribute.

This is trickier than it might sound at first because within the
context of the select method, $ is bound to the local context,
which will be an individual item from the list. So while I can ask
for $.path, there’s no way to refer to items from the top-level
context. Or is there?

The operators documentation for yaql mentions the “context pass”
operator, ->, but doesn’t provide any examples of how it can be
used. It turns out that this operator will be the key to our solution.
But before we look at that in more detail, we need to introduce the
let statement, which can be used to define variables. The let
statement isn’t mentioned in the documentation at all, but it looks
like this:

let(var => value, ...)

By itself, this isn’t particularly useful. In fact, if you were to
type a bare let statement in a yaql evaluator, you would get an
error: