Activator

 view release on metacpan or  search on metacpan

Build.PL  view on Meta::CPAN

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,

META.yml  view on Meta::CPAN

  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

README  view on Meta::CPAN

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

t/DB.t  view on Meta::CPAN

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



( run in 0.579 second using v1.01-cache-2.11-cpan-4d50c553e7e )