Page MenuHomePhabricator

Cumin: add multi-query support
Closed, ResolvedPublic

Description

As already pre-announced in https://wikitech.wikimedia.org/wiki/Cumin#Host_selection pretty much since the beginning, it's about time to add the support for multiple queries into Cumin. I've already had a chat with @Joe about it and this summary includes also his suggestions.

This will allow to:

  • mix results from different backends (like puppetdb and a future conftool/etcd backend)
  • overcome backend's limitations (like mixing fact and resource queries in the puppetdb backend)
  • simplify the alias management

This of course as a cost for the user given that now it will need to give the information about which backend should be queried for each block. There are basically two approaches:

  1. force the user to specify always which backend to use, even for the simplest query
    • PROs: explicit, the user doesn't need to know/remember which is the default backend
    • CONs: non-backward compatible, more verbose (see below for possible implementations)
  2. keep the default backend setting in the configuration file and try to parse the query with that backend first, if it doesn't parse use the general multi-query grammar.
    • PROs: backward compatible (current working queries will continue to work), hence more usable
    • CONs: implicit, the user needs to know which is the default backend (seems pretty obvious right now for us with puppetdb but this assumption might not be true in general)

My first choice would be towards (1) being more generic and clean, and assuming that the alias support will reduce sensibly the necessity to write queries each time. But (2) has the big advantage of being backward compatible and less verbose, so probably a better choice.
Given the young nature of the tool I would just like to avoid to make choices now that might be regretted later. I'd rather do some drastic change now than later on.

Regarding the grammar syntax itself my proposal would be to use a letter to identify the backend, P for puppetdb, D for direct (it could be more than one char but I would like to keep it short) and curly braces to enclose the subqueries, this because parentheses and square brackets are already used by existing grammars.

Here some examples:

# Full complex query with all the grammar features
(P{R:Class = Foo::Bar and R:Class%param = value} and P{F:has_ipmi = true and F:is_virtual = false} and not A:hosts_down) or D{special_host.wikimedia.org}

# Simple all hosts in puppetdb, if we go for option (1)
P{*}

Any comment and feedback is appreciated.

Event Timeline

I'd add another PRO to the second option (which I prefer for backwards compatibility): it allows us to be more concise.

While I do the occasional fancy query, 95% of my cumin queries are

R:class = some_class and *.some-site.wmnet

or similar. I would very much appreciate not having to wrap those around with 'P{}'. Writing cumin queries is verbose enough as it is - aliases are going to help a lot in this respect, admittedly, but still.

Yeah, this

I'd add another PRO to the second option (which I prefer for backwards compatibility): it allows us to be more concise.

While I do the occasional fancy query, 95% of my cumin queries are

R:class = some_class and *.some-site.wmnet

or similar. I would very much appreciate not having to wrap those around with 'P{}'. Writing cumin queries is verbose enough as it is - aliases are going to help a lot in this respect, admittedly, but still.

Yeah, this was what I was thinking too, so that would be my preference as well.

For option 2, how do you resolve ambiguities? Would letters be unique to backends (i.e. F/R are claimed by PuppetDB and can't be claimed by another backend, period) or would they be claimed on a first-come first-served basis, in which case the order of backend inclusion matters? I'd strongly prefer the former, but this means that letters need to be reserved across/above backends, right?

For option 2, how do you resolve ambiguities? Would letters be unique to backends (i.e. F/R are claimed by PuppetDB and can't be claimed by another backend, period) or would they be claimed on a first-come first-served basis, in which case the order of backend inclusion matters? I'd strongly prefer the former, but this means that letters need to be reserved across/above backends, right?

If we keep the main grammar non-conflicting with the inner grammars of each backend, neither of those is needed.
I can try to parse the query string with the default backend (from config) and if it fail to parse it, it get's then parsed by the main grammar that accepts the P{...}... syntax. The only things to forbid in the backend-specific grammars are the A: for the aliases and the use of curly braces, if not inside quoted strings.
Inside the P{...} the backend-specific grammar has full freedom and they will not clash within each other.

The implemented proposal (CR will be sent later today) is pretty much what listed as (2) in the task description:

  • have an optional default_backend parameter in the configuration that will cause:
    • if set: try to parse the query with the default backend first, if it fails parsing try with the multi-query global grammar
    • if not set: run directly with the multi-query global grammar
  • have aliases only in the global grammar, they need to use the global multi-query grammar and can be specified as A:alias_name
  • aliases are recursively replaced with their value, so an alias can be a composition of other aliases
  • Each query block can be aggregated with the others with the boolean operators: and, or, and not, xor

I'm asking in advance sorry for the large CR, but given the big refactor I didn't see any simple way to split it into working pieces.
For what is worth, the integration tests are passing without touching their code, just adding the default_backend: direct to their configuration.
I'll add additional integration tests for the new syntax in a follow up CR.
I would like to start with a single aliases file, but we can add later on very quickly the possibility to load an additional custom aliases file too.

Change 366736 had a related patch set uploaded (by Volans; owner: Volans):
[operations/software/cumin@master] Transports: convert hosts to ClusterShell's NodeSet

https://gerrit.wikimedia.org/r/366736

Change 366737 had a related patch set uploaded (by Volans; owner: Volans):
[operations/software/cumin@master] Query: add multi-query support

https://gerrit.wikimedia.org/r/366737

Change 366736 merged by jenkins-bot:
[operations/software/cumin@master] Transports: convert hosts to ClusterShell's NodeSet

https://gerrit.wikimedia.org/r/366736

Volans triaged this task as High priority.Aug 2 2017, 10:01 AM

Change 366737 merged by jenkins-bot:
[operations/software/cumin@master] Query: add multi-query support

https://gerrit.wikimedia.org/r/366737

Volans moved this task from In Code Review to Done on the SRE-tools board.
Volans removed a project: Patch-For-Review.