I recently had a need to find the OS versions of all 32-bit hosts within an environment. Knowing PuppetDB has a REST API, I set out to query the DB for this information.

There is decent information on how to use the API, but it can be tricky to understand the nuances necessary to construct a proper query as some of it is non-intuitive. I will attempt to describe exactly how my query works here. See "Resources" below for links to the PuppetDB API docs I used.

Query

I used curl as a simple way to query the PuppetDB. The easiest way to construct the query is to do it in a text editor and the run the resulting file as a script. Here is my query command:

curl -s -X GET http://localhost:8080/v2/facts --data-urlencode \
'query=["and",
  ["=", "name", "operatingsystemrelease"],
  ["in", "certname",
    ["extract", "certname",
      ["select-facts",
        ["and",
          ["=", "name", "architecture"],
          ["=", "value", "i386"]
        ]
      ]
    ]
  ]
]'

The results of running this query are as follows:

$ ./get_p_ver
[ {
  "certname" : "host1.local",
  "name" : "operatingsystemrelease",
  "value" : "5.3"
}, {
  "certname" : "host2.local",
  "name" : "operatingsystemrelease",
  "value" : "5.3"
}, {
  "certname" : "host3.local",
  "name" : "operatingsystemrelease",
  "value" : "5.3"
} ]

Query Breakdown

Endpoint

curl -s -X GET http://localhost:8080/v2/facts --data-urlencode

Query Data String

'query=["and",
  ["=", "name", "operatingsystemrelease"],
  ["in", "certname",
    ["extract", "certname",
      ["select-facts",
        ["and",
          ["=", "name", "architecture"],
          ["=", "value", "i386"]
        ]
      ]
    ]
  ]
]'

Output

[ {
  "certname" : "host1.local",
  "name" : "operatingsystemrelease",
  "value" : "5.3"
}, {
  "certname" : "host2.local",
...
} ]

Note that the output is JSON and can be manipulated as such.

Single fact one-line query

It's also possible to simply query for a single fact directly via the facts API endpoint. The following returns the certname, fact name & fact value for each host in the DB as JSON:

curl -s -X GET http://localhost:8080/v2/facts/architecture

To limit the results to only hosts with the i386 architecture, supply the fact value as an additional component to the URL:

curl -s -X GET http://localhost:8080/v2/facts/architecture/i386

Conclusion

Again, the query syntax is a bit awkward, but if you break it down it's not too bad. There are PuppetDB querying libraries for both Ruby as well as Python (and I'm sure other languages) which could make programmatically querying various information relatively easy.