fork YML and update it to work with TOML... also clean up formatting

This commit is contained in:
Zane C. B-H 2021-10-19 16:34:11 -05:00
parent 23e409085b
commit 847b8c2d72
3 changed files with 285 additions and 108 deletions

View File

@ -4,42 +4,46 @@ use warnings;
use ExtUtils::MakeMaker;
my %WriteMakefileArgs = (
NAME => 'Rex::CMDB::TOML',
AUTHOR => q{Zane C. Bowers-Hadley <vvelox@vvelox.net>},
VERSION_FROM => 'lib/Rex/CMDB/TOML.pm',
ABSTRACT_FROM => 'lib/Rex/CMDB/TOML.pm',
LICENSE => 'apache_2_0',
MIN_PERL_VERSION => '5.006',
CONFIGURE_REQUIRES => {
'ExtUtils::MakeMaker' => '0',
},
TEST_REQUIRES => {
'Test::More' => '0',
},
PREREQ_PM => {
#'ABC' => '1.6',
#'Foo::Bar::Module' => '5.0401',
},
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
clean => { FILES => 'Rex-CMDB-TOML-*' },
NAME => 'Rex::CMDB::TOML',
AUTHOR => q{Zane C. Bowers-Hadley <vvelox@vvelox.net>},
VERSION_FROM => 'lib/Rex/CMDB/TOML.pm',
ABSTRACT_FROM => 'lib/Rex/CMDB/TOML.pm',
LICENSE => 'apache_2_0',
MIN_PERL_VERSION => '5.006',
CONFIGURE_REQUIRES => {
'ExtUtils::MakeMaker' => '0',
},
TEST_REQUIRES => {
'Test::More' => '0',
},
PREREQ_PM => {
'Rex::Logger' => '0',
'Rex::Commands' => '0',
'Data::Dumper' => '0',
'Hash::Merge' => '0',
'Rex::Commands::File' => '0',
'TOML' => '0',
},
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
clean => { FILES => 'Rex-CMDB-TOML-*' },
);
# Compatibility with old versions of ExtUtils::MakeMaker
unless (eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 }) {
my $test_requires = delete $WriteMakefileArgs{TEST_REQUIRES} || {};
@{$WriteMakefileArgs{PREREQ_PM}}{keys %$test_requires} = values %$test_requires;
unless ( eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 } ) {
my $test_requires = delete $WriteMakefileArgs{TEST_REQUIRES} || {};
@{ $WriteMakefileArgs{PREREQ_PM} }{ keys %$test_requires } = values %$test_requires;
}
unless (eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 }) {
my $build_requires = delete $WriteMakefileArgs{BUILD_REQUIRES} || {};
@{$WriteMakefileArgs{PREREQ_PM}}{keys %$build_requires} = values %$build_requires;
unless ( eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 } ) {
my $build_requires = delete $WriteMakefileArgs{BUILD_REQUIRES} || {};
@{ $WriteMakefileArgs{PREREQ_PM} }{ keys %$build_requires } = values %$build_requires;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
delete $WriteMakefileArgs{MIN_PERL_VERSION}
unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
delete $WriteMakefileArgs{LICENSE}
unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };
unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };
WriteMakefile(%WriteMakefileArgs);

View File

@ -1,16 +1,7 @@
Rex-CMDB-TOML
The README is used to introduce the module and provide instructions on
how to install the module, any machine dependencies it may have (for
example C compilers and installed libraries) and any other information
that should be provided before the module is installed.
A README file is required for CPAN modules since CPAN extracts the README
file from a module distribution so that people browsing the archive
can use it to get an idea of the module's uses. It is usually a good idea
to provide version information here so that people can decide whether
fixes for the module are worth downloading.
A fork of Rex::CMDB::YAML to add TOML support
as well as roles.
INSTALLATION

View File

@ -1,105 +1,287 @@
#
# (c) Jan Gehring <jan.gehring@gmail.com>
# (c) Zane C. Bowers-Hadley
package Rex::CMDB::TOML;
use 5.006;
use 5.010001;
use strict;
use warnings;
our $VERSION = '0.0.1'; # VERSION
use base qw(Rex::CMDB::Base);
use Rex::Commands -no => [qw/get/];
use Rex::Logger;
use TOML qw(from_toml);
use Data::Dumper;
use Hash::Merge qw/merge/;
require Rex::Commands::File;
sub new {
my $that = shift;
my $proto = ref($that) || $that;
my $self = {@_};
$self->{merger} = Hash::Merge->new();
if ( !defined $self->{merge_behavior} ) {
$self->{merger}->specify_behavior(
{
SCALAR => {
SCALAR => sub { $_[0] },
ARRAY => sub { $_[0] },
HASH => sub { $_[0] },
},
ARRAY => {
SCALAR => sub { $_[0] },
ARRAY => sub { $_[0] },
HASH => sub { $_[0] },
},
HASH => {
SCALAR => sub { $_[0] },
ARRAY => sub { $_[0] },
HASH => sub { Hash::Merge::_merge_hashes( $_[0], $_[1] ) },
},
},
'REX_DEFAULT',
); # first found value always wins
$self->{merger}->set_behavior('REX_DEFAULT');
}
else {
if ( ref $self->{merge_behavior} eq 'HASH' ) {
$self->{merger}->specify_behavior( $self->{merge_behavior}, 'USER_DEFINED' );
$self->{merger}->set_behavior('USER_DEFINED');
}
else {
$self->{merger}->set_behavior( $self->{merge_behavior} );
}
}
bless( $self, $proto );
return $self;
}
sub get {
my ( $self, $item, $server ) = @_;
$server = $self->__get_hostname_for($server);
my $result = {};
if ( $self->__cache->valid( $self->__cache_key() ) ) {
$result = $self->__cache->get( $self->__cache_key() );
}
else {
my @files = $self->_get_cmdb_files( $item, $server );
Rex::Logger::debug( Dumper( \@files ) );
# configuration variables
my $config_values = Rex::Config->get_all;
my %template_vars;
for my $key ( keys %{$config_values} ) {
if ( !exists $template_vars{$key} ) {
$template_vars{$key} = $config_values->{$key};
}
}
$template_vars{environment} = Rex::Commands::environment();
for my $file (@files) {
Rex::Logger::debug("CMDB - Opening $file");
if ( -f $file ) {
my $content = eval { local ( @ARGV, $/ ) = ($file); <>; };
my $t = Rex::Config->get_template_function();
$content .= "\n"; # for safety
$content = $t->( $content, \%template_vars );
my $ref = from_toml($content);
$result = $self->{merger}->merge( $result, $ref );
}
}
}
if ( defined $item ) {
return $result->{$item};
}
else {
return $result;
}
}
sub _get_cmdb_files {
my ( $self, $item, $server ) = @_;
$server = $self->__get_hostname_for($server);
my @files;
if ( !ref $self->{path} ) {
my $env = Rex::Commands::environment();
my $server_file = "$server.toml";
my $default_file = 'default.toml';
@files = (
File::Spec->join( $self->{path}, $env, $server_file ),
File::Spec->join( $self->{path}, $env, $default_file ),
File::Spec->join( $self->{path}, $server_file ),
File::Spec->join( $self->{path}, $default_file ),
);
}
elsif ( ref $self->{path} eq "CODE" ) {
@files = $self->{path}->( $self, $item, $server );
}
elsif ( ref $self->{path} eq "ARRAY" ) {
@files = @{ $self->{path} };
}
my $os = Rex::Hardware::Host->get_operating_system();
@files = map { $self->_parse_path( $_, { hostname => $server, operatingsystem => $os, } ) } @files;
return @files;
}
1;
__END__
=head1 NAME
Rex::CMDB::TOML - The great new Rex::CMDB::TOML!
Rex::CMDB::TOML - TOML-based CMDB provider for Rex
=head1 VERSION
Version 0.01
=cut
our $VERSION = '0.01';
=head1 DESCRIPTION
This module collects and merges data from a set of TOML files to provide configuration
management database for Rex.
=head1 SYNOPSIS
Quick summary of what the module does.
use Rex::CMDB;
set cmdb => {
type => 'TOML',
path => [ 'cmdb/{hostname}.toml', 'cmdb/default.toml', ],
merge_behavior => 'LEFT_PRECEDENT',
};
task 'prepare', 'server1', sub {
my %all_information = get cmdb;
my $specific_item = get cmdb('item');
my $specific_item_for_server = get cmdb( 'item', 'server' );
};
Perhaps a little code snippet.
=head1 CONFIGURATION AND ENVIRONMENT
use Rex::CMDB::TOML;
=head2 path
my $foo = Rex::CMDB::TOML->new();
...
=head1 EXPORT
A list of functions that can be exported. You can delete this section
if you don't export anything, such as for a purely object-oriented module.
=head1 SUBROUTINES/METHODS
=head2 function1
=cut
sub function1 {
}
=head2 function2
=cut
sub function2 {
}
=head1 AUTHOR
Zane C. Bowers-Hadley, C<< <vvelox at vvelox.net> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-rex-cmdb-toml at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Rex-CMDB-TOML>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Rex::CMDB::TOML
You can also look for information at:
The path used to look for CMDB files. It supports various use cases depending on the
type of data passed to it.
=over 4
=item * RT: CPAN's request tracker (report bugs here)
=item * Scalar
L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Rex-CMDB-TOML>
set cmdb => {
type => 'TOML',
path => 'path/to/cmdb',
};
=item * CPAN Ratings
If a scalar is used, it tries to look up a few files under the given path:
L<https://cpanratings.perl.org/d/Rex-CMDB-TOML>
path/to/cmdb/{environment}/{hostname}.toml
path/to/cmdb/{environment}/default.toml
path/to/cmdb/{hostname}.toml
path/to/cmdb/default.toml
=item * Search CPAN
=item * Array reference
L<https://metacpan.org/release/Rex-CMDB-TOML>
set cmdb => {
type => 'TOML',
path => [ 'cmdb/{hostname}.yml', 'cmdb/default.yml', ],
};
If an array reference is used, it tries to look up the mentioned files in the given
order.
=item * Code reference
set cmdb => {
type => 'TOML',
path => sub {
my ( $provider, $item, $server ) = @_;
my @files = ( "$server.yml", "$item.yml" );
return @files;
},
};
If a code reference is passed, it should return a list of files that would be looked
up in the same order. The code reference gets the CMDB provider instance, the item,
and the server as parameters.
=back
When the L<0.51 feature flag|Rex#0.51> or later is used, the default value of the
C<path> option is:
=head1 ACKNOWLEDGEMENTS
[qw(
cmdb/{operatingsystem}/{hostname}.toml
cmdb/{operatingsystem}/default.toml
cmdb/{environment}/{hostname}.toml
cmdb/{environment}/default.toml
cmdb/{hostname}.toml
cmdb/default.toml
)]
The path specification supports macros enclosed within curly braces, which are
dynamically expanded during runtime. By default, the valid macros are L<Rex::Hardware>
variables, C<{server}> for the server name of the current connection, and C<{environment}>
for the current environment.
=head1 LICENSE AND COPYRIGHT
Please note that the default environment is, well, C<default>.
This software is Copyright (c) 2021 by Zane C. Bowers-Hadley.
You can define additional CMDB paths via the C<-O> command line option by using a
semicolon-separated list of C<cmdb_path=$path> key-value pairs:
This is free software, licensed under:
rex -O 'cmdb_path=cmdb/{domain}.toml;cmdb_path=cmdb/{domain}/{hostname}.toml;' taskname
The Apache License, Version 2.0, January 2004
Those additional paths will be prepended to the current list of CMDB paths (so the last one
specified will get on top, and thus checked first).
=head2 merge_behavior
This CMDB provider looks up the specified files in order, and returns the requested data. If
multiple files specify the same data for a given item, then the first instance of the data
will be returned by default.
Rex uses L<Hash::Merge> internally to merge the data found on different levels of the CMDB
hierarchy. Any merge strategy supported by that module can be specified to override the
default one. For example one of the built-in strategies:
set cmdb => {
type => 'TOML',
path => 'cmdb',
merge_behavior => 'LEFT_PRECEDENT',
};
Or even custom ones:
set cmdb => {
type => 'TOML',
path => 'cmdb',
merge_behavior => {
SCALAR => sub {},
ARRAY => sub {},
HASH => sub {},
};
For the full list of options, please see the documentation of Hash::Merge.
=cut
1; # End of Rex::CMDB::TOML