The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Puppet::DB - Object for easily getting Puppet DB data (e.g. facts, reports, etc)

VERSION

version 0.001

SYNOPSIS

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:

    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

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 );

METHODS

new

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');

server_name

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.

    $puppet_db->server_name( 'puppet' );

This can be changed at any time for subsequent queries if you need to connect to another Puppet DB.

server_port

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.

    $puppet_db->server_port( '1234' );

This can be changed at any time for subsequent queries if you need to connect to another Puppet DB.

Data Loading Methods

refresh

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.

refresh_facts

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; # Load all facts from the Puppet DB (will be slow for a large instance)

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.

Accessor Methods

results

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;

facts

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.

allfacts_by_certname

Get all the facts for the specified certname.

    $puppet_db->allfacts_by_certname( 'testhost.example.com' );

The facts will be returned as complex data (i.e hash ref).

allfacts_by_hostname

Get all the facts for the specified hostname.

    $puppet_db->allfacts_by_hostname( 'testhost.example.com' );

The facts will be returned as complex data (i.e hash ref).

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.

get_fact

This will return a fact value matching the specified certname and fact. It is a shortcut for "get_fact_by_certname".

    $puppet_db->get_fact( 'testhost.example.com', 'osfamily' );

The fact value may be a string or complex data (i.e hash or array ref).

get_fact_by_certname

This will return a fact value matching the specified certname and fact.

    $puppet_db->get_fact_by_certname( 'testhost.example.com', 'osfamily' );

The fact value may be a string or complex data (i.e hash or array ref).

get_fact_by_short_hostname

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).

is_certname_in_puppetdb

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' );

is_node_in_puppetdb

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' );

is_hostname_in_puppetdb

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.

FUNCTIONS

parse_puppetdb_time

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' );

BUGS/FEATURES

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.

AUTHOR

Matthew Mallard <mqtech@cpan.org>

COPYRIGHT AND LICENSE

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.