view release on metacpan or search on metacpan
use Module::Build;
my $build = Module::Build->new
(
dist_version => '0.91',
module_name => 'Activator',
license => 'perl',
requires => {
'Data::Dumper' => 0,
'Log::Log4perl' => 0,
'Scalar::Util' => 0,
'IO::Capture' => 0,
'Exception::Class' => 0,
'Test::Exception' => 0,
'Test::Pod' => 0,
'Class::StrongSingleton' => 0,
'Hash::Merge' => 0,
'Time::HiRes' => 0,
'Exception::Class::TryCatch' => 0,
creation and rapid development of multi-developer distributed mixed
environment perl based software projects, especially Catalyst based
websites.
license: perl
resources:
license: http://dev.perl.org/licenses/
requires:
CGI::Cookie: 0
Class::StrongSingleton: 0
Crypt::CBC: 0
Data::Dumper: 0
Digest::SHA1: 0
Email::Send: 0
Exception::Class: 0
Exception::Class::DBI: 0
Exception::Class::TryCatch: 0
HTML::Entities: 0
Hash::Merge: 0
IO::Capture: 0
Log::Log4perl: 0
MIME::Base64: 0
Activator::DB
Activator::Dictionary
DEPENDENCIES
------------
Run: This module requires these other modules and libraries:
Data::Dumper
Log::Log4perl
Scalar::Util
IO::Capture
Exception::Class
Test::Exception
Test::Pod
Test::Harness
Class::StrongSingleton
Hash::Merge
Time::HiRes
bin/activator.pl view on Meta::CPAN
#!/usr/bin/perl
use strict;
use warnings;
use Activator::Registry;
use Activator::Config;
use Activator::Log qw( :levels );
use Exception::Class::TryCatch;
use Data::Dumper;
use Template;
use File::Find;
=head1 NAME
activator.pl - setup and manage services with an Activator project.
=head1 SYNOPSIS
activator.pl [OPTIONS] ACTION project-name
lib/Activator.pm view on Meta::CPAN
Make sure you edit all the configurations necessary when creating a new dev environment
=back
Activator solves all of the above, and many more problems. Read the L<Activator::Tutorial> to find out how.
=head1 DEPENDANCIES
Data::Dumper
Scalar::Util
IO::Capture
Exception::Class
Test::Exception
Test::Pod
Class::StrongSingleton
Hash::Merge
Time::HiRes
Exception::Class::TryCatch
Exception::Class::DBI
lib/Activator/Config.pm view on Meta::CPAN
package Activator::Config;
use Data::Dumper;
use Activator::Registry;
use Activator::Log qw( :levels );
use Scalar::Util qw( reftype );
use Exception::Class::TryCatch;
use base 'Class::StrongSingleton';
=head1 NAME
C<Activator::Config> - provides a merged configuration to a script
combining command line options, environment variables, and
lib/Activator/Config.pm view on Meta::CPAN
multiple realms if desired.
=cut
sub get_config {
my ( $pkg, $argv, $realm, $project_is_arg ) = @_;
my $self = &new( @_ );
# get_args sets $self->{ARGV}
$self->get_args( $argv );
DEBUG( Data::Dumper->Dump( [ $self->{ARGV} ], [ qw/ ARGV / ] ) );
DEBUG( Data::Dumper->Dump( [ $self->{BAREWORDS} ], [ qw /BAREWORDS/ ] ) );
# make sure we can use ENV vars
my $skip_env = $ENV{ACT_CONFIG_skip_env};
$realm ||=
$self->{ARGV}->{realm} ||
( $skip_env ? undef : $ENV{ACT_CONFIG_realm} ) ||
'default';
if ( ref( $realm ) ) {
lib/Activator/Config.pm view on Meta::CPAN
elsif( $env_opt_realm ne $opt_realm &&
!grep( /$opt_key/, qw( skip_env project
realm conf_path ) ) ) {
WARN( "Skipped invalid environment variable $env_key. Key '$opt_key' for realm '$opt_realm' unchanged");
}
}
}
# forced overrides from config files
my $overrides = $self->{REGISTRY}->get_realm( 'overrides' );
DEBUG( Data::Dumper->Dump( [ $overrides ], [ 'processing overrides' ] ) );
# NOTE: bad (typo) keys could be in overrides. Someday,
# Activator::Registry will allow debug mode so we can
# show this.
if ( exists( $overrides->{ $realm } ) ) {
$self->{REGISTRY}->register_hash( 'right', $overrides->{ $realm }, $realm );
}
# now that realm is set, make sure our $config points to it
$config = $self->{REGISTRY}->get_realm( $realm );
lib/Activator/Config.pm view on Meta::CPAN
$self->_argv_override( $config, $argv );
# inject some env variables that we support
# TODO: make this cross-platform
$config->{HOME} = $ENV{HOME};
$config->{USER} = $ENV{USER};
# feed the realm to itself for any self-defined variables
$self->{REGISTRY}->replace_in_realm( $realm, $config );
DEBUG( 'generated ' . Data::Dumper->Dump( [ $config ], [ qw/ config / ] ) );
}
else {
DEBUG( 'found ' . Data::Dumper->Dump( [ $config ], [ qw/ config / ] ) );
}
return $config;
}
=head2 get_args()
Takes a reference to a list of command line arguments (usually
C<\@ARGV>) and returns an arrayref consisting of an options hash, and
a barewords arrayref. C<$argv_raw> is not changed.
lib/Activator/Config.pm view on Meta::CPAN
}
else {
INFO( "Using ACT_CONFIG_conf_path env var: $conf_path");
}
}
else {
INFO( "Using conf_path argument: $conf_path");
}
my @search_paths = split ':', $conf_path;
DEBUG( 'Searching for conf files in: ' . Data::Dumper->Dump( [ \@search_paths ], [ qw/ search_paths / ] ) );
# Search for these files, create a files lookup.
my $files = { user => { target => "$ENV{USER}.yml" },
realm => { target => "${realm}.yml" },
project => { target => "${project}.yml" },
org => { target => 'org.yml' } };
foreach my $path ( @search_paths ) {
$path =~ s|/$||;
foreach my $which ( keys %$files ) {
lib/Activator/Config.pm view on Meta::CPAN
if ( !exists( $files->{ $which }->{ file } ) ) {
$files->{ $which }->{file} = $file;
} else {
INFO( "Ignoring lower priority config file '$file'" );
}
}
}
}
}
DEBUG ( 'Processing config files: ' . Data::Dumper->Dump( [ $files ], [ qw/ files / ] ) );
# now that we have all the files, import 'em! This is a super long
# winded but safe "left precedence" merge of all files
my ( $user_config, $realm_config, $project_config, $org_config );
try eval {
if ( exists( $files->{user}->{file} ) ) {
$user_yml = YAML::Syck::LoadFile( $files->{user}->{file} );
}
};
lib/Activator/Config.pm view on Meta::CPAN
}
if ( defined( $org_yml ) && exists( $org_yml->{overrides} ) ) {
$self->{REGISTRY}->register_hash( 'left', $org_yml->{overrides}, 'overrides' );
DEBUG('Registered: ' . $files->{org}->{file} . " overrides" );
}
# make sure all is kosher
my $test = $self->{REGISTRY}->get_realm( $realm );
if ( !keys %$test ) {
DEBUG( Data::Dumper->Dump( [ $self->{REGISTRY} ], [ qw/ registry / ] ) );
ERROR( "After processing, '$realm' realm should not be empty, but it is!");
Activator::Exception::Config->throw('realm', 'empty', $realm);
}
}
# Override any options in $config with the values in $argv. Sets non-existent keys.
#
# Arguments:
# $config : hashref to the options for $realm
# $argv : arrayref to command line arguments. All recognized options are removed.
lib/Activator/DB.pm view on Meta::CPAN
package Activator::DB;
use strict;
use warnings;
use Activator::Log qw( :levels );
use Activator::Registry;
use DBI;
use Exception::Class::DBI;
use Exception::Class::TryCatch;
use Data::Dumper;
use Time::HiRes qw( gettimeofday tv_interval );
use Scalar::Util;
use base 'Class::StrongSingleton';
# constructor: implements singleton
sub new {
my ( $pkg, $conn_alias ) = @_;
my $self = bless( {}, $pkg);
lib/Activator/DB.pm view on Meta::CPAN
# est. the actual connection if it's not set
if ( !$conn->{dbh} ) {
try eval {
$self->_debug_connection( 2, "Connecting to alias $self->{cur_alias}" );
$self->_debug_connection( 2, 'Connect Parameters:');
$self->_debug_connection( 2, " dsn => $conn->{dsn}");
$self->_debug_connection( 2, " user => $conn->{user}");
$self->_debug_connection( 2, ' pass => ' . ( $conn->{pass} || ''));
$self->_debug_connection( 2, Data::Dumper->Dump( [ $conn->{attr} ], [ ' attr' ] ) );
try eval {
$conn->{dbh} = DBI->connect( $conn->{dsn},
$conn->{user} || '',
$conn->{pass} || '',
$conn->{attr}
);
};
if ( catch my $e ) {
Activator::Exception::DB->throw( 'dbh',
'connect',
"$e " .
Data::Dumper->Dump( [ $conn ], [ 'connection' ] )
);
}
# TODO: do something more generic with this
# mysql_auto_reconnect now cannot be disconnected
if ( $conn->{dsn} =~ /mysql/i ) {
$conn->{dbh}->{mysql_auto_reconnect} = $self->{config}->{mysql}->{auto_reconnect};
}
elsif ( my $search_path = $conn->{config}->{Pg}->{search_path} ) {
$self->do("SET search_path TO ?", [ $search_path ]);
lib/Activator/DB.pm view on Meta::CPAN
# setup default config
foreach my $key ( keys %{ $conns->{ $alias }->{config} } ) {
if ( exists ( $self->{config}->{ $key } ) ) {
$self->{connections}->{ $alias }->{config}->{ $key } =
$conns->{ $alias }->{config}->{ $key };
} else {
WARN( "Ignoring ${alias}->config->${key}: unsupported config option" );
}
}
$self->_debug_connection( 2, "Initialized connection ".
Data::Dumper->Dump( [ $self->{connections}->{$alias} ],
[ $alias ] ) );
}
$self->_debug_connection( 2, 'Activator::DB initialization successful');
}
# _ping>($conn)
#
# Test a database handle and attempt to reconnect if it is done
#
# Args:
lib/Activator/DB.pm view on Meta::CPAN
}
my $conn = $self->_get_cur_conn();
if ( $args->{debug} ||
$self->{config}->{debug} ||
$conn->{config}->{debug} ) {
local $Log::Log4perl::caller_depth;
$Log::Log4perl::caller_depth += $depth;
my $str = $self->_get_sql( $sql, $bind );
DEBUG( tv_interval( $self->{debug_timer}, [ gettimeofday ] ). " $str".
( $self->{config}->{debug_attr} ? "\n\t" .
Data::Dumper->Dump( [ $conn->{attr} ], [ 'attr' ] ) : '' )
);
}
}
sub _debug_connection {
my ( $self, $depth, $msg, $args ) = @_;
if ( $self->{config}->{debug_connection} ) {
local $Log::Log4perl::caller_depth;
$Log::Log4perl::caller_depth += $depth;
DEBUG( $msg );
lib/Activator/Dictionary.pm view on Meta::CPAN
package Activator::Dictionary;
use strict;
use Activator::DB;
use Activator::Registry;
use Activator::Exception;
use Activator::Log qw( :levels );
use Exception::Class::TryCatch;
use Data::Dumper;
use base 'Class::StrongSingleton';
=head1 NAME
Activator::Dictionary
=head1 SYNOPSIS
Configure your dictionary using Activator::Registry. See
L<CONFIGURATION OVERVIEW> below.
lib/Activator/Emailer.pm view on Meta::CPAN
package Activator::Emailer;
use strict;
use Email::Send;
use MIME::Lite;
use Template;
use Activator::Registry;
use Exception::Class::TryCatch;
use Data::Dumper;
use Hash::Merge;
use Activator::Log qw( :levels );
=head1 NAME
Activator::Emailer - Send emails from anywhere within a project in the same way using role-based configuration.
=head1 SYNOPSIS
Configure defaults with Activator::Registry configuration (See
lib/Activator/Log.pm view on Meta::CPAN
package Activator::Log;
require Exporter;
push @ISA, qw( Exporter );
@EXPORT_OK = qw( FATAL ERROR WARN INFO DEBUG TRACE );
%EXPORT_TAGS = ( levels => [ qw( FATAL ERROR WARN INFO DEBUG TRACE ) ] );
use Log::Log4perl;
use Scalar::Util;
use Data::Dumper;
use Activator::Registry;
use base 'Class::StrongSingleton';
=head1 NAME
Activator::Log - provide a simple wrapper for L<Log::Log4perl> for use
within an Activator project.
=head1 SYNOPSIS
lib/Activator/Options.pm view on Meta::CPAN
package Activator::Options;
use Data::Dumper;
use Activator::Registry;
use Activator::Log qw( :levels );
use Scalar::Util qw( reftype );
use Exception::Class::TryCatch;
use base 'Class::StrongSingleton';
=head1 NAME
THIS MODULE DEPRECATED. USE L<Activator::Config> instead.
lib/Activator/Options.pm view on Meta::CPAN
=cut
sub get_opts {
my ( $pkg, $argv, $realm ) = @_;
my $self = &new( @_ );
my $argx = {};
# get_args sets $self->{ARGV}
$self->get_args( $argv );
DEBUG( Data::Dumper->Dump( [ $self->{ARGV} ], [ qw/ ARGV / ] ) );
DEBUG( Data::Dumper->Dump( [ $self->{BAREWORDS} ], [ qw /BAREWORDS/ ] ) );
# make sure we can use ENV vars
my $skip_env = $ENV{ACT_OPT_skip_env};
$realm ||=
$self->{ARGV}->{realm} ||
( $skip_env ? undef : $ENV{ACT_OPT_realm} ) ||
'default';
# setup or get the merged YAML configuration settings from files
lib/Activator/Registry.pm view on Meta::CPAN
package Activator::Registry;
use YAML::Syck;
use base 'Class::StrongSingleton';
use Activator::Log qw( :levels );
use Data::Dumper;
use Hash::Merge;
use Activator::Exception;
use Exception::Class::TryCatch;
=head1 NAME
Activator::Registry - provide a registry based on YAML file(s)
=head1 SYNOPSIS
lib/Activator/Registry.pm view on Meta::CPAN
TRACE( "No variables to replace in '$target'");
}
return wantarray ? ( $target, $num_replaced ) : $target;
}
# register_hash helpers for when using SAFE_LEFT_PRECEDENCE merging
# TODO (not currently used)
sub die_array_scalar {
die "Can't coerce ARRAY into SCALAR\n" .
Data::Dumper->Dump( [ $_[0], $_[1] ],
[ qw( ARRAY SCALAR ) ] );
}
sub die_hash_scalar {
die "Can't coerce HASH into SCALAR\n" .
Data::Dumper->Dump( [ $_[0], $_[1] ],
[ qw( HASH SCALAR ) ] );
}
sub die_hash_array {
die "Can't coerce HASH into ARRAY\n" .
Data::Dumper->Dump( [ $_[0], $_[1] ],
[ qw( HASH ARRAY ) ] );
}
sub die_scalar_hash {
die "Can't coerce SCALAR into HASH\n" .
Data::Dumper->Dump( [ $_[0], $_[1] ],
[ qw( SCALAR HASH ) ] );
}
sub die_array_hash {
die "Can't coerce ARRAY into HASH\n" .
Data::Dumper->Dump( [ $_[0], $_[1] ],
[ qw( ARRAY HASH ) ] );
}
=head1 FUTURE WORK
=over
=item * Fix warning messages
t/Config-02.t view on Meta::CPAN
#!perl
use warnings;
use strict;
use Test::More tests => 7;
use Activator::Config;
use Activator::Log;
use Data::Dumper;
use IO::Capture::Stderr;
#Activator::Log->level( 'DEBUG' );
$ENV{ACT_CONFIG_project} = 'test';
my $proj_dir = "$ENV{PWD}/t/data/test_project";
my $user_yml = "$ENV{USER}.yml";
system( qq( cp $proj_dir/USER.yml $proj_dir/$user_yml));
@ARGV = (# '--debug', # debug this test: doesn't break tests
#!perl
use warnings;
use strict;
use Test::More;
use Test::Exception;
use Data::Dumper;
use DBI;
BEGIN{
$ENV{ACT_REG_YAML_FILE} ||= "$ENV{PWD}/t/data/DB-test.yml";
}
if ( ! ( $ENV{ACT_DB_TEST_ENGINE} && (
( $ENV{ACT_DB_TEST_ENGINE} eq 'mysql' && $ENV{ACT_DB_TEST_USER} && $ENV{ACT_DB_TEST_PASSWORD} ) ||
( $ENV{ACT_DB_TEST_ENGINE} eq 'Pg' && $ENV{ACT_DB_TEST_USER} ) ) ) ) {
t/Dictionary-default.t view on Meta::CPAN
use strict;
BEGIN{
$ENV{ACT_REG_YAML_FILE} ||= "$ENV{PWD}/t/data/Dictionary-default.yml";
}
use Test::More;
use Test::Exception;
use Activator::Registry;
use Activator::Dictionary;
use Data::Dumper;
use IO::Capture::Stderr;
plan skip_all => 'test requires access to MySQL DB that can connect with \'mysql -u root\'. Set TEST_ACT_DB to enable this test' unless $ENV{TEST_ACT_DB};
my ($dict, $val, $capture, $line);
# test that when the db loads, duplicated column in a different table
# definition warns appropriately
system( "cat $ENV{PWD}/t/data/Dictionary-create-test.sql | mysql -u root");
t/Dictionary-dies.t view on Meta::CPAN
use strict;
BEGIN{
$ENV{ACT_REG_YAML_FILE} ||= "$ENV{PWD}/t/data/Dictionary-dies.yml";
}
use Test::More;
use Test::Exception;
use Activator::Registry;
use Activator::Dictionary;
use Data::Dumper;
plan skip_all => 'test requires access to MySQL DB that can connect with \'mysql -u root\'. Set TEST_ACT_DB to enable this test' unless $ENV{TEST_ACT_DB};
my ($dict, $val);
# test loading from files. Gotta hack the registry to make this work for testing.
my $config = Activator::Registry->get( 'Activator::Dictionary' );
$config->{dict_files} = "$ENV{PWD}/t/data/Dictionary";
# get the english dictionary
t/Emailer.t view on Meta::CPAN
#!perl
use strict;
use warnings;
use Test::More;
use Test::Exception;
use Data::Dumper;
if ( ! $ENV{TEST_ACT_EMAILER_ADDR} ) {
plan skip_all => 'set TEST_ACT_EMAILER_ADDR (a "to" address) to enable this test';
}
else {
plan tests => 1;
}
# DEFINE THIS TO TEST
my $to = $ENV{ACT_EMAILER_TEST_ADDR};
t/Exception.t view on Meta::CPAN
#!/usr/bin/perl -w
use Test::More tests => 8;
use Activator::Exception;
use Exception::Class::TryCatch;
use Data::Dumper;
my $err;
try eval {
Activator::Exception->throw( 'MyObj', 'MyCode' );
};
catch $err;
ok( $err, "Can catch $err");
$err = undef;
t/Options-01.t view on Meta::CPAN
#!perl
use warnings;
use strict;
use Test::More tests => 6;
use Activator::Options;
use Activator::Log qw( :levels );
use Data::Dumper;
use IO::Capture::Stderr;
#Activator::Log->level( 'DEBUG' );
$ENV{ACT_OPT_project} = 'test';
my $proj_dir = "$ENV{PWD}/t/data/test_project";
my $user_yml = "$ENV{USER}.yml";
system( qq( cp $proj_dir/USER.yml $proj_dir/$user_yml));
t/Options-02.t view on Meta::CPAN
#!perl
use warnings;
use strict;
use Test::More tests => 7;
use Activator::Options;
use Activator::Log;
use Data::Dumper;
use IO::Capture::Stderr;
#Activator::Log->level( 'DEBUG' );
$ENV{ACT_OPT_project} = 'test';
my $proj_dir = "$ENV{PWD}/t/data/test_project";
my $user_yml = "$ENV{USER}.yml";
system( qq( cp $proj_dir/USER.yml $proj_dir/$user_yml));
@ARGV = (# '--debug', # debug this test: doesn't break tests
t/Registry-static.t view on Meta::CPAN
#!/usr/bin/perl -w
use Test::More tests => 9;
use Activator::Registry;
use Activator::Log;
use Data::Dumper;
BEGIN {
$ENV{ACT_REG_YAML_FILE} ||= "$ENV{PWD}/t/data/Registry-test.yml";
}
Activator::Log->level('DEBUG');
# basic functionality
my $realm = Activator::Registry->get_realm( 'default');
my $list = Activator::Registry->get( 'list_of_5_letters');