Puppet::DB - Object for easily getting Puppet DB data (e.g. facts, reports, etc)
version 0.001
This module provides methods to make it easy to connect to the Puppet DB and to put the data into a form where it can be manipulated more readily.
It can extract anything from the Puppet DB that is supported by the API. See the Puppet docs for more information on the API: https://puppet.com/docs/puppetdb/latest/api/index.html. Although this module tries to make it easier and more approachable by abstracting away some complexity, it still requires a basic understanding of how the API works. There is a bunch of Perl scripts I have created that consumes this and other Puppet Perl modules I have written. They provide some examples of what can be done. They are distributed in a Puppet module as they are generally only useful in a Puppet environment. Consequently the best way to install them is via the module. The module can be found here: https://github.com/Q-Technologies/puppet-utility_scripts.
Here is an example of how to use Puppet::DB:
Puppet::DB
use Puppet::DB; my $puppet_db = Puppet::DB->new; $puppet_db->refresh_facts; my $facts = $puppet_db->allfacts_by_certname; say $facts->{testhost.example.com}{osfamily};
Would output Suse if there was a SLES system called testhost.example.com
Suse
testhost.example.com
The AST query system of the Puppet DB is supported: https://puppet.com/docs/puppetdb/latest/api/query/v4/ast.html. Rather than specifying it in JSON, specify it as Perl data structures. This module will convert it to JSON when it communicates with the Puppet DB. Some sample queries:
use Puppet::DB; use Data::Dumper; my $mode = "facts"; my $fact = 'osfamily'; my $value = 'RedHat'; my $rule = { 'query' => [ "and", ["=","name", $fact], ["~", "value", $value ] ], "order_by" => [{"field" => "certname"}] }; my $puppet_db = Puppet::DB->new; $puppet_db->refresh($mode, $rule); print Dumper( $puppet_db->results ); my $fact = 'os.family'; $mode = "fact-contents"; $rule = { 'query' => [ "and", ["=","path", [split( /\./, $fact)] ], ["~", "value", $value ] ], "order_by" => [{"field" => "certname"}] }; $puppet_db->refresh($mode, $rule); print Dumper( $puppet_db->results );
The second example demonstrates how to search via a complex fact.
This is how to access the reports:
$rule = ['=', 'job_id', $opt_j ]; $puppet_db->refresh( "reports", $rule ); print Dumper( $puppet_db->results ); $node_rule = ['=', 'certname', 'testhost.example.com' ]; $rule = [ 'and', ['=', 'latest_report?', 'true' ], $node_rule, ]; $puppet_db->refresh( "reports", $rule ); print Dumper( $puppet_db->results );
Create a new Puppet::DB object connecting to http://localhost:8080:
my $puppet_db = Puppet::DB->new;
or, Connect to a Puppet DB host called puppet
my $puppet_db = Puppet::DB->new( 'puppet' );
or, connect to a non standard port:
my $puppet_db = Puppet::DB->new( server_name => 'puppet', server_port => '1234');
If you did not specify the server to connect when the object was created you can set it with this method. The default value is localhost.
localhost
$puppet_db->server_name( 'puppet' );
This can be changed at any time for subsequent queries if you need to connect to another Puppet DB.
If you did not specify the port to connect when the object was created you can set it with this method. The default value is 8080.
8080
$puppet_db->server_port( '1234' );
This method needs to be called to populate the Puppet::DB object with data from the Puppet DB. This needs to be called everytime you change the query.
$puppet_db->refresh( 'facts' );
or
my $query = { 'query' => ["~","certname", '.*\.example.com'], "order_by" => [{"field" => "certname"}] }; $puppet_db->refresh( 'facts', $query );
No data will be returned. The data can be accessed through one of the accessor methods.
This method can to be called to populate the Puppet::DB object with facts data from the Puppet DB. It does the same as $puppet_db->refresh( 'facts' ); $puppet_db->facts( $puppet_db->results ); - i.e. it populates the facts property as well as the results property.
$puppet_db->refresh( 'facts' ); $puppet_db->facts( $puppet_db->results );
$puppet_db->refresh_facts; # Load all facts from the Puppet DB (will be slow for a large instance)
my $query = { 'query' => ["~","certname", '.*\.example.com'], "order_by" => [{"field" => "certname"}] }; $puppet_db->refresh_facts( $query );
Return all the results gathered from the last "refresh" (including anything that calls refresh indirectly - i.e. it can only be trusted if used immediately after calling refresh).
my $results = $puppet_db->results;
Return all the facts gathered from the last "refresh_facts"
my $facts = $puppet_db->facts;
This returns the data in the form that the Puppet DB provides it as. The other fact accessor methods manipulate it for easier consumption.
Get all the facts for the specified certname.
certname
$puppet_db->allfacts_by_certname( 'testhost.example.com' );
The facts will be returned as complex data (i.e hash ref).
Get all the facts for the specified hostname.
hostname
$puppet_db->allfacts_by_hostname( 'testhost.example.com' );
Note that it will match the last hostname found by looking at the first field in the certname. Basically, if you have two nodes with a different certname, but the same hostname, you may not get the intended host. If this is a risk, then always use the certname.
This will return a fact value matching the specified certname and fact. It is a shortcut for "get_fact_by_certname".
fact
$puppet_db->get_fact( 'testhost.example.com', 'osfamily' );
The fact value may be a string or complex data (i.e hash or array ref).
This will return a fact value matching the specified certname and fact.
$puppet_db->get_fact_by_certname( 'testhost.example.com', 'osfamily' );
This will return a fact value matching the specified hostname and fact. Note that it will match the first hostname found by looking at the first field in the certname.
$puppet_db->get_fact_by_short_hostname( 'testhost', 'osfamily' );
The fact value may be a string or complex data (i.e hash or array).
This will return true or false based on whether the specified certname can be found in the Puppet DB.
$puppet_db->is_certname_in_puppetdb( 'testhost.example.com' );
This will return true or false based on whether the specified node can be found in the Puppet DB. This is a synonym of "is_certname_in_puppetdb".
$puppet_db->is_node_in_puppetdb( 'testhost.example.com' );
This will return the certname if the hostname of a node can be found in the Puppet DB. It will match the first certname where the first field matches the hostname.
$puppet_db->is_hostname_in_puppetdb( 'testhost' );
If a hostname is provided with dots in it, it will be assumed to be a certname and simply returned back if it is found in the PuppetDB.
False (i.e. 0) is returned if it is not found in the PuppetDB.
Puppet DB time is always stored and reported as GM time in a text string. This method will convert it into a time(2) value in seconds since the system epoch (Midnight, January 1, 1970 GMT on Unix).
my $time = parse_puppetdb_time( '2016-02-08T02:21:04.417Z' );
Please report any bugs or feature requests in the issues section of GitHub: https://github.com/Q-Technologies/perl-Puppet-DB. Ideally, submit a Pull Request.
Matthew Mallard <mqtech@cpan.org>
This software is copyright (c) 2019 by Matthew Mallard.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Puppet::DB, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Puppet::DB
CPAN shell
perl -MCPAN -e shell install Puppet::DB
For more information on module installation, please visit the detailed CPAN module installation guide.