Hello all,
For quite some time we’ve been mentioning the idea of introducing a richer way to query data in the snap tooling. One good example of that is snap configuration, which today enables setting and changing arbitrary options for snap to consult, adapt to, and change if necessary.
For example, this works today:
$ snap set core example.one='[1,2,3]' example.two='[4,5,6]'
$ snap get core example
Key Value
example.one [1 2 3]
example.two [4 5 6]
Internally these values are stored as a JSON document, and they can also be queried as such:
$ snap get -d core example
{
"example": {
"one": [
1,
2,
3
],
"two": [
4,
5,
6
]
}
}
The default support of the current get command is very limited, though, and only allows retrieving sub-documents via the typical dotted notation, as in example.one
for instance. For more interesting use cases, we need to leverage the -d option and external tools, of which the most well known one nowadays is probably jq.
While that works, it creates a dependency on an external tool which may not necessarily be available, and being external also means the integration in snapd is weak, in the sense that we can’t expose such support in the API itself for all clients to use in a universal way. For example, if a snap needs to do just a single trivial query, it needs to depend on jq as well.
So for a while we’ve been thinking about how to solve that, and just recently I found an alternative which seems pretty good: JMESPath. This is a specification that has been around for several years, and also a set of libraries that conform to the specification. It tastes a bit like jq, but feels more limited, but also simpler and more consistent, which is good for our use case.
So, as a first step towards embedding this into our tooling, I would like to propose an experiment: I’ve just released a snap that leverages the Go jmespath implementation to work as a filter.
To get started, just do:
$ sudo snap install jmes
$ jmes -h
Usage: <command generating json or yaml> | jmes '<expression>'
The jmes command takes JSON or YAML in its standard input and
filters it using the JMESPath expression provided in the
command line. For example:
$ cat file.json | jmes 'items[].name'
See http://jmespath.org for details on the expressions.
Once installed, please try to use this for relevant tasks you may encounter, snap-related or not. The goal is learning more about the library and the language, and making sure we’re into the right track by the time we really adopt this. After we adopt, we cannot take it out without breaking people’s routines, which means we just can’t take it out.
So, please put this to some good use and let us know. If you are a jq user, try to use jmes instead when you can. And please feel free to ask any questions here, about JMESPath, or jmes, or its future use in snap. These exchanges will help guiding us in our upcoming decisions.
Here is a quick example operating on the JSON document above, flattening the two lists into one, and then sorting it:
$ snap get -d core example | jmes 'example.*[] | sort(@)'
[
1,
2,
3,
4,
5,
6
]
I’ve also started adding support for YAML in the tool, which means you can use the same logic to inspect snap.yaml and snapcraft.yaml. For instance:
$ cat /snap/lxd/current/meta/snap.yaml | jmes summary
LXD - the container lightervisor