mvhub-dev team mailing list archive
-
mvhub-dev team
-
Mailing list archive
-
Message #00182
[Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
Lee Goodrich has proposed merging lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub.
Requested reviews:
MVHub devs with commit rights (mvhub-commit)
refactored mv_setup, moving all resusable subroutines to
MVHub/Utils/Setup.pm and then splitting the script into three new ones:
mv_update_development, mv_update_staging, and mv_update_production.
Each script has been custom-tailored to the tasks needed for its
environment, including recreating developer folders, updating the
config files, recreating the database with either production or testing
data, updating what is in /etc, and running the tests.
--
https://code.launchpad.net/~leegoodrich/mvhub/refactor_mv_setup/+merge/25461
Your team MVHub Developers is subscribed to branch lp:mvhub.
=== renamed file 'app-mvhub/project-tools/bin/mv_setup' => 'app-mvhub/project-tools/bin/mv_update_development'
--- app-mvhub/project-tools/bin/mv_setup 2010-04-30 21:05:11 +0000
+++ app-mvhub/project-tools/bin/mv_update_development 2010-05-17 19:10:48 +0000
@@ -1,26 +1,42 @@
#!/usr/bin/perl
-# Purpose: automate setup / updaing of developer setup on brave
+# Purpose: automate setup / updating of developer setup on brave
# after modifiying test with:
-# sudo mv_setup $OTHER_USER_THAT_EXISTS
-# sudo mv_setup $NEW_USER
-# mv_setup
+# sudo mv_dev_update $OTHER_USER_THAT_EXISTS
+# sudo mv_dev_update $NEW_USER
+# mv_dev_update
use strict;
use warnings;
use English qw/-no_match_vars/;
use Carp;
-use DBI;
-use File::Copy qw/move/;
+use Getopt::Long;
use IO::Prompt;
-use Config::Simple;
-use MVHub::Utils::ConfigSimple;
-use MVHub::Utils::DB qw/get_data_source /;
+
+use MVHub::Utils::ConfigSimple qw/ create_config_from /;
+use MVHub::Utils::Setup qw/ add_apache_config
+ add_dns
+ load_test_data_for
+ make_config_files_for
+ make_databases_for
+ make_dirs_from /;
+
+my @ALLOWED_HOSTS = qw/ brave cricket /;
my @WEBSITE_CODES = qw/ mvh nsp /;
{ # main
+ my $interactive = 0;
+ my $usage = 0;
+ my $hostname = `hostname`;
+ chomp $hostname;
+
+ Getopt::Long::GetOptions( 'prompt' => \$interactive,
+ 'help|?' => \$usage )
+ or die "GetOptions failed";
+
+ die usage() if $usage || ( grep /^$hostname$/, @ALLOWED_HOSTS ) == 0;
local $OUTPUT_AUTOFLUSH = 1;
my $USERNAME = get_username_or_die();
@@ -32,305 +48,39 @@
system('clear');
my $base_dir = $cfg->param('BASE.dir');
- my @dirs = get_dirs_with( "$base_dir", $USERNAME );
- make_dirs_from( $USERNAME, \@dirs );
-
- make_databases_for( $USERNAME, @WEBSITE_CODES );
-
- make_config_files_for( $USERNAME, $cfg, @WEBSITE_CODES );
-
+ my @dirs = MVHub::Utils::Setup::get_dirs_with( "$base_dir", $USERNAME );
+
+ my $prompt = "Create $USERNAME directory structure? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_dirs_from( $USERNAME, \@dirs );
+ }
+
+ $prompt = "Update config files for $USERNAME? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_config_files_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
+ $prompt = "DESTROY and reload databases for $USERNAME (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_databases_for( $USERNAME, @WEBSITE_CODES );
+ MVHub::Utils::Setup::load_test_data_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
+ $prompt = "Apply database updates for $USERNAME? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::apply_database_updates_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
if ( defined $ENV{SUDO_USER} ) {
foreach my $prefix (@WEBSITE_CODES) {
- add_dns( $USERNAME, $prefix );
- add_apache_config( $USERNAME, $prefix );
- }
- }
-}
-
-sub add_dns {
- my $username = shift or croak 'missing paramater: $username';
- my $prefix = shift or croak 'missing parameter: $prefix';
-
- my $host = "$prefix.$username";
- my $FILE = '/etc/bind/db.testing123.net';
-
- my $line = sprintf( "%-15s IN A 129.63.96.180\n", $host );
- if ( possible_dup_line( $host, $FILE ) ) {
- warn "$host found in $FILE, skipping append\n";
- return;
- }
-
- append_to_file( $FILE, $line );
-}
-
-sub add_apache_config {
- my $username = shift or croak 'missing paramater: $username';
- my $prefix = shift or croak 'missing parameter: $prefix';
-
- my $FILE = '/etc/apache2/sites-available/mvhub_developer.data';
- my $host = "$prefix.$username.testing123.net";
-
- my $line = sprintf( "Use MVhub %-15s $prefix $host\n", $username );
-
- if ( possible_dup_line( $host, $FILE ) ) {
- warn "$host found in $FILE, skipping append\n";
- return;
- }
-
- append_to_file( $FILE, $line );
-}
-
-sub append_to_file {
- my ( $file, $append_lines ) = @_;
- my $tmp_file = "$file.tmp";
-
- open( IN, $file )
- or die "bad open: $file error: $! \n";
- my @lines = <IN>;
- close(IN) or die "bad close $file error: $!\n";
-
- push @lines, $append_lines;
-
- open( OUT, ">", "$tmp_file" )
- or die "couldn't open $tmp_file.tmp error: $! \n";
- ( print OUT @lines )
- or die "couldn't write to $tmp_file $!\n";
-
- close(OUT) or die "couldn't close $tmp_file $!\n";
- File::Copy::move( $tmp_file, $file )
- or die "couldn't rename $tmp_file to $file\n";
-}
-
-sub add_calculable_values {
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $username = shift or croak 'missing param: $username';
- my $site_code = shift or croak 'missing param: $site_code';
-
- $template_cfg->param( 'DATABASE.database_name', "$username.$site_code" );
- $template_cfg->param( 'DATABASE.database_user', "$username" );
- $template_cfg->param( 'NOTIFICATION.admin_email', "$username\@thecsl.org" );
- $template_cfg->param( 'NOTIFICATION.dev_email', "$username\@thecsl.org" );
- $template_cfg->param( 'SITE.website_name',
- "$site_code.$username.testing123.net" );
- $template_cfg->param( 'SITE.website_code', "$site_code" );
-
- return $template_cfg;
-}
-
-sub add_site_specific_values {
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $username = shift or croak 'missing param: $username';
- my %site_specific_values = %_;
-
- foreach my $key ( keys %site_specific_values ) {
- $template_cfg->param( $key, $site_specific_values{$key} );
- }
- return $template_cfg;
-}
-
-sub add_user_generated_values {
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $user_cfg = shift or croak 'missing param: $user_cfg';
- my @keys = @_;
-
- foreach my $key (@keys) {
- if ( !( $user_cfg->param($key) ) ) {
- prompt("Please enter a value for $key: ");
- $template_cfg->param( $key, $_ );
- }
- }
- return $template_cfg;
-}
-
-sub db_exists {
- my $dbh = shift or croak 'missing param: $dbh';
- my $db_name = shift or croak 'missing param: $db_name';
-
- my $sql = <<"SQL";
-SELECT
- datname
-FROM
- pg_database
-WHERE
- datname = ?
-SQL
-
- my $matching_dbs_aref = $dbh->selectall_arrayref( $sql, {}, ($db_name) );
- return scalar @$matching_dbs_aref;
-
-}
-
-sub db_user_found {
- my $dbh = shift or croak 'missing param: $dbh';
- my $username = shift or croak 'missing param: $username';
-
- my $sql = <<"SQL";
-SELECT
- usename
-FROM
- pg_user
-WHERE
- usename = ?
-SQL
-
- my $matching_db_users_aref =
- $dbh->selectall_arrayref( $sql, {}, ($username) );
- return scalar @$matching_db_users_aref;
-}
-
-sub db_user_has_needed_roles {
- my $dbh = shift or croak 'missing param: $dbh';
- my $username = shift or croak 'missing param: $username';
-
- my $sql = <<"SQL";
-SELECT
- rolname,rolcreaterole,rolcreatedb
-FROM
- pg_roles
-WHERE
- rolname = ?
-SQL
-
- my $role_rows_aref =
- $dbh->selectall_arrayref( $sql, { Slice => {} }, ($username) );
- my $result = $$role_rows_aref[0]{rolcreaterole}
- && $$role_rows_aref[0]{rolcreatedb};
-
- return $result ? 1 : 0;
-}
-
-sub db_user_has_superuser_role {
- my $dbh = shift or croak 'missing param: $dbh';
- my $username = shift or croak 'missing param: $username';
-
- my $sql = <<"SQL";
-SELECT
- rolname,rolsuper
-FROM
- pg_roles
-WHERE
- rolname = ?
-SQL
-
- my $role_rows_aref =
- $dbh->selectall_arrayref( $sql, { Slice => {} }, ($username) );
- return $$role_rows_aref[0]{rolsuper} ? 1 : 0;
-}
-
-sub do_or_die {
- my $cmd = shift or croak 'missing param: $cmd';
- $cmd =~ s/^\s+//;
- my @cmd = split /\s+/, $cmd;
- ( system(@cmd) == 0 )
- or die "$cmd failed ABORTING\n";
-}
-
-sub get_dbh {
- my $config_file = shift or croak "missing param: config_file";
- croak "couldn't read config_file: '$config_file'"
- if not -r $config_file;
-
- my $data_source = MVHub::Utils::DB::get_data_source($config_file);
-
- my $cfg = new Config::Simple($config_file);
- my $database_username = $cfg->param('DATABASE.database_user');
- my $auth = $cfg->param('DATABASE.database_magic_word');
-
- my %attr = (
- 'PrintError' => 1,
- 'RaiseError' => 1,
- 'AutoCommit' => 1,
- 'ShowErrorStatement' => 1,
- );
-
- my $dbh = DBI->connect('dbi:Pg:dbname=template1',$database_username, $auth, \%attr )
- or die "couldn't connect to database";
- return $dbh;
-
-}
-
-sub get_dirs_with {
- my $base_dir = shift or croak 'missing param: $base_dir';
- my $username = shift or croak 'missing param: $username';
- my @dirs = (
- {
- dir => 'conf',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- },
- {
- dir => 'cover_db',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- },
- {
- dir => 'reports',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=r-x',
- },
- {
- dir => 'reports',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- },
- {
- dir => 'source-code',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- },
- {
- dir => 'log/mvh',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- },
- {
- dir => 'log/nsp',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- },
- {
- dir => 'tmp',
- owner => '',
- group => '',
- permissions => 'u=rwx,g=rwsx,o=rx',
- }
- );
- foreach my $dir_href (@dirs) {
- $dir_href->{owner} = $username
- if not $dir_href->{owner};
- $dir_href->{group} = $username
- if not $dir_href->{group};
-
- $dir_href->{dir} = "$base_dir/$username/" . $dir_href->{dir};
- }
- return @dirs;
-}
-
-sub get_site_specific_values {
- my $site_code = shift or croak 'missing param: $site_code';
-
- my %hash_of_site_specific_values = (
- 'mvh' => {
- 'SITE.location' => '"Massachusetts Merrimack Valley"',
- 'SITE.website_description' => 'Merrimack Valley Hub',
- 'NOTIFICATION.team_name' => 'Merrimack Valley Hub Team'
- },
- 'nsp' => {
- 'SITE.location' => '"Massachusetts North Shore"',
- 'SITE.website_description' => 'North Shore Portal',
- 'NOTIFICATION.team_name' => 'North Shore Portal Team'
- }
- );
- return %{ $hash_of_site_specific_values{$site_code} };
-}
-
+ $prompt = "Add $prefix entries for $USERNAME into DNS and Apache? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::add_dns( $USERNAME, $prefix );
+ MVHub::Utils::Setup::add_apache_config( $USERNAME, $prefix );
+ }
+ }
+ }
+}
sub die_if_bad_env_for {
my $username = shift or croak 'missing parameter $username\n';
my $msg = '';
@@ -358,7 +108,7 @@
if ( $username ne $ENV{USER} && $EFFECTIVE_USER_ID != 0 );
$msg .=
-"\ncan't run mv_setup for user root, did you forget a \$user param on command line?\n"
+"\ncan't run mv_dev_update for user root, did you forget a \$user param on command line?\n"
if $username eq 'root';
die $msg if $msg;
@@ -387,223 +137,32 @@
return $username;
}
-sub load_test_data_for {
- my $dbh = shift or croak 'missing param: $dbh';
- my $username = shift or croak 'missing param: $username';
- my $suffix = shift or croak 'missing param: $db_name';
-
- my $cfg =
- MVHub::Utils::ConfigSimple::create_config_from( $ENV{MV_CONFIG_FILE} );
-
- my $path_to_project_tools = $cfg->param('ABSOLUTE_PATH.project_tools_dir');
- my $db_password = $cfg->param('DATABASE.database_magic_word');
-
- my $cmd = "export PGPASSWORD=$db_password ";
- $cmd .= "&& psql -h localhost -U $username -d $username.$suffix ";
- $cmd .= "-f ${path_to_project_tools}/test_${suffix}_db.sql >/dev/null";
-
- ( system($cmd) == 0 )
- or warn "failed to load data for $username.$suffix";
-
-}
-
-sub make_config_files_for {
- my $username = shift;
- my $cfg = shift;
- my @website_codes = @_;
- my @keys_for_user_generated_values = qw/ DATABASE.database_magic_word /;
-
- my $base_dir = $cfg->param('BASE.dir');
- my $template_config_file =
- $cfg->param('ABSOLUTE_PATH.template_conf_dir') . "/template.conf";
- my $template_cfg = new Config::Simple($template_config_file)
- or die "failed to create config object from $template_config_file";
-
- foreach my $site_code (@website_codes) {
-
- my $cfg_file = "$base_dir/$username/conf/$site_code.conf";
- my $user_cfg = new Config::Simple( syntax => 'ini' );
- if ( !-e $cfg_file ) {
- make_empty_config_file_named($cfg_file);
- }
- $user_cfg->read($cfg_file);
-
- print "Editing Config: $cfg_file\n";
- my %site_specific_values = get_site_specific_values($site_code);
-
- $template_cfg = add_site_specific_values( $template_cfg, $username,
- %site_specific_values );
- $template_cfg =
- add_calculable_values( $template_cfg, $username, $site_code );
- $template_cfg = add_user_generated_values( $template_cfg, $user_cfg,
- @keys_for_user_generated_values );
-
- merge_conf_objects( $template_cfg, $user_cfg );
-
- $user_cfg->write("$base_dir/$username/conf/$site_code.conf");
- }
-}
-
-sub make_dbs_for {
- my $dbh = shift or croak 'missing param: $dbh';
- my $username = shift or croak 'missing param: $username';
- my @website_codes = @_;
-
- my $sql;
- my $user_running_cmd =
- defined $ENV{SUDO_USER} ? $ENV{SUDO_USER} : $ENV{USER};
- if ( !db_user_has_needed_roles( $dbh, $user_running_cmd ) ) {
- warn
-"\nSkipping db stuff $user_running_cmd lacks CREATEDB or CREATEROLE\n";
- return;
- }
-
- if ( ( $user_running_cmd ne $username )
- && !db_user_has_superuser_role( $dbh, $user_running_cmd ) )
- {
- my $msg = qq/
- skipping db stuff $user_running_cmd can't drop table owned by $username
- without role SUPERUSER
- /;
- warn $msg;
- return;
- }
-
- if ( !db_user_found( $dbh, $username ) ) {
- $sql = "CREATE USER $username WITH PASSWORD 'test' CREATEDB CREATEROLE";
- $dbh->do($sql);
- }
-
- foreach my $suffix (@website_codes) {
- if ( db_exists( $dbh, "$username.$suffix" ) ) {
- $sql = qq{DROP DATABASE "$username.${suffix}"};
- $dbh->do($sql);
- }
-
- # kludge to avoid 'db being currently being accessed' errs
- sleep 1;
-
- $sql = qq{CREATE DATABASE "$username.${suffix}" OWNER $username ENCODING='SQL_ASCII' };
- $dbh->do($sql);
-
- load_test_data_for( $dbh, $username, $suffix );
- }
- return 1;
-}
-
-sub make_empty_config_file_named {
- my $filename = shift or croak 'missing Param $filename';
-
- open my $out_fh, '>', $filename
- or die "failed to open $filename for writing error:$!\n";
- print $out_fh "#Config file\n [ignore]\n";
- close $out_fh
- or die "failed to close $filename error:$!\n";
- return 1;
-}
-
-sub make_databases_for {
- my $username = shift or croak 'missing parameter: $username';
- my @website_codes = @_ or croak 'mssing parameter: @website_codes';
-
- my $prompt = "DESTROY and reload databases for $username (Y/N):";
- if ( IO::Prompt::prompt( $prompt, -YN ) ) {
-
- die "I refuse to destroy production database data"
- if $username =~ /www-data|production/;
-
- print
- "(re)making databases for $username this may take 50 seconds....\n";
- my $DBH = get_dbh( $ENV{MV_CONFIG_FILE} );
-
- print "...done\n"
- if make_dbs_for( $DBH, $username, @website_codes );
-
- }
-}
-
-sub make_dirs_from {
- my $username = shift or croak 'missing param: $username';
- my $dir_hrefs_href = shift or croak 'missing param: $dir_hrefs_href';
- my @dir_hrefs = @$dir_hrefs_href;
-
- foreach my $dir_href (@dir_hrefs) {
- my $mkdir_cmd = "mkdir -p $dir_href->{dir}";
- my $chown_cmd =
- "chown -R $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
- if ( $dir_href->{dir} =~ /log/ ) {
-
- # root owns log files it creates don't try to change ownership on them
- $chown_cmd =
- "chown $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
- }
- else {
- $chown_cmd =
- "chown -R $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
- }
- my $chmod_cmd = "chmod $dir_href->{permissions} $dir_href->{dir}";
- do_or_die($mkdir_cmd);
- do_or_die($chown_cmd);
- do_or_die($chmod_cmd);
- }
-}
-
-sub merge_conf_objects {
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $user_cfg = shift or croak 'missing param: $user_cfg';
-
- foreach my $key ( $template_cfg->param() ) {
- if ( !( $user_cfg->param($key) ) ) {
- my $value = $template_cfg->param($key);
- $value = defined $value ? $value : 'BAD_MISSING';
- $user_cfg->param( $key, $value );
- }
- }
-
- #remove keys no longer used
- foreach my $key ( $user_cfg->param() ) {
- if ( !defined $template_cfg->param($key) ) {
- $user_cfg->delete($key);
- }
- }
-
- return $user_cfg;
-}
-
sub usage {
return << 'USAGE';
+mv_dev_update - Utility for updating a CSL developer's MVHub environment
+
+Options:
+ --prompt Prompts the user before any action.
+ --help Gets this screen
Usage to update your setup:
# to update your own developer setup
- cdw && mv_setup
+ cdw && mv_dev_update
# to update parts of your developer setup
# (apache & dns) that require root
- cdw && sudo app-mvhub/project-tools/bin/mv_setup $USER
+ cdw && sudo app-mvhub/project-tools/bin/mv_dev_update $USER
Usage to update or partly create a developer setup for somebody else:
# includes apache, & DNS
- sudo app-mvhub/project-tools/bin/mv_setup <username>
+ sudo app-mvhub/project-tools/bin/mv_dev_update <username>
or:
- export NEW_DEV_USER=<username> && mv_setup
- sudo app-mvhub/project-tools/bin/mv_setup
+ export NEW_DEV_USER=<username> && mv_dev_update
+ sudo app-mvhub/project-tools/bin/mv_dev_update
USAGE
}
-
-sub possible_dup_line {
- my $host = shift or croak 'missing parameter: $host';
- my $filename = shift or croak 'missing parameter: $filename';
-
- open my $in_fh, $filename
- or die "failed to open $filename error:$!";
-
- my @contents = <$in_fh>;
- my $regex = qr/$host/;
- return scalar grep { $_ =~ $regex } @contents;
-}
-
=== added file 'app-mvhub/project-tools/bin/mv_update_production'
--- app-mvhub/project-tools/bin/mv_update_production 1970-01-01 00:00:00 +0000
+++ app-mvhub/project-tools/bin/mv_update_production 2010-05-17 19:10:48 +0000
@@ -0,0 +1,147 @@
+#!/usr/bin/perl
+
+# Purpose: automate updating of production environment on parrot
+
+# after modifiying test with:
+# sudo mv_dev_update $OTHER_USER_THAT_EXISTS
+# sudo mv_dev_update $NEW_USER
+# mv_dev_update
+
+use strict;
+use warnings;
+use English qw/-no_match_vars/;
+
+use lib "/var/www/mvhub/www-data/link-to-live-code/lib-mvhub/lib/";
+
+use Carp;
+use Getopt::Long;
+use IO::Prompt;
+
+use MVHub::Utils::ConfigSimple qw/ create_config_from /;
+use MVHub::Utils::Setup qw/ add_apache_config
+ add_dns
+ make_config_files_for
+ make_databases_for
+ make_dirs_from /;
+
+my @ALLOWED_HOSTS = qw/ parrot /;
+my $USERNAME = 'www-data';
+my @WEBSITE_CODES = qw/ mvh nsp /;
+
+$ENV{MV_CONFIG_FILE} = '/var/www/mvhub/www-data/conf/nsp.conf';
+$ENV{SUDO_USER} = 'www-data';
+
+{ # main
+ my $interactive = 0;
+ my $usage = 0;
+ my $hostname = `hostname`;
+ chomp $hostname;
+
+ Getopt::Long::GetOptions( 'prompt' => \$interactive,
+ 'help|?' => \$usage )
+ or die "GetOptions failed";
+
+ die usage() if $usage || $ENV{USER} ne 'root' || ( grep /^$hostname$/, @ALLOWED_HOSTS ) == 0;
+ local $OUTPUT_AUTOFLUSH = 1;
+
+ my $cfg =
+ MVHub::Utils::ConfigSimple::create_config_from( $ENV{MV_CONFIG_FILE} );
+
+ system('clear');
+
+ my $base_dir = $cfg->param('BASE.dir');
+ my @dirs = MVHub::Utils::Setup::get_dirs_with( "$base_dir", $USERNAME );
+
+ my $prompt = "Create $USERNAME directory structure? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_dirs_from( $USERNAME, \@dirs );
+ }
+
+ $prompt = "Update config files for $USERNAME? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_config_files_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
+ $prompt = "Apply database updates for $USERNAME? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::apply_database_updates_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
+ $prompt = "Update contents of /etc? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::update_etc_files( $cfg );
+ MVHub::Utils::Setup::restart_services();
+ }
+
+}
+
+sub die_if_bad_env_for {
+ my $username = shift or croak 'missing parameter $username\n';
+ my $msg = '';
+
+ foreach my $var (qw/PERL5LIB MV_CONFIG_FILE/) {
+ $msg .= "$var not set"
+ if !defined $ENV{$var};
+ }
+
+ my $xtra_msg = <<'HERE';
+ if running with sudo edit /etc/sudoers to include line:
+
+ Defaults env_keep+="PERL5LIB MV_CONFIG_FILE"
+
+ also be sure you ran:
+
+ cdw
+HERE
+
+ if ($msg) {
+ $msg .= $xtra_msg;
+ }
+
+ $msg .= "\nneed to run under sudo if you aren't $username\n"
+ if ( $username ne $ENV{USER} && $EFFECTIVE_USER_ID != 0 );
+
+ $msg .=
+"\ncan't run mv_dev_update for user root, did you forget a \$user param on command line?\n"
+ if $username eq 'root';
+
+ die $msg if $msg;
+ return 1;
+}
+
+sub get_username_or_die {
+ my $username =
+ shift @ARGV
+ || $ENV{NEW_DEV_USER}
+ || ( defined $ENV{MV_CONFIG_FILE} ? $ENV{USER} : undef );
+
+ if ( !$username ) {
+ die "No username defined" . usage();
+ }
+ my @ignore = getpwnam($username);
+
+ if ( !scalar @ignore ) {
+ die "'$username' is not a valid username" . usage();
+ }
+
+ # should have nothing left on command line
+ # at this point
+ die usage() if scalar @ARGV;
+
+ return $username;
+}
+
+sub usage {
+ return << 'USAGE';
+mv_prod_update - Utility for updating the production MVHub environment
+
+Usage: sudo mv_prod_update [options]
+
+Options:
+ --prompt Prompts the user before any action.
+ --help Gets this screen
+
+*** THIS COMMAND MUST BE RUN ON THE PRODUCTION SERVER WITH SUDO ***
+USAGE
+
+}
=== added file 'app-mvhub/project-tools/bin/mv_update_staging'
--- app-mvhub/project-tools/bin/mv_update_staging 1970-01-01 00:00:00 +0000
+++ app-mvhub/project-tools/bin/mv_update_staging 2010-05-17 19:10:48 +0000
@@ -0,0 +1,162 @@
+#!/usr/bin/perl
+
+# Purpose: automate updating of staging environment on penguin
+
+# after modifiying test with:
+# sudo mv_dev_update $OTHER_USER_THAT_EXISTS
+# sudo mv_dev_update $NEW_USER
+# mv_dev_update
+
+use strict;
+use warnings;
+use English qw/-no_match_vars/;
+
+use lib "/var/www/mvhub/www-data/link-to-live-code/lib-mvhub/lib/";
+
+use Carp;
+use Getopt::Long;
+use IO::Prompt;
+
+use MVHub::Utils::ConfigSimple qw/ create_config_from /;
+use MVHub::Utils::Setup qw/ add_apache_config
+ add_dns
+ get_production_data
+ load_production_data
+ make_config_files_for
+ make_databases_for
+ make_dirs_from
+ restart_services
+ update_etc_files /;
+
+my @ALLOWED_HOSTS = qw/ penguin /;
+my $USERNAME = 'www-data';
+my @WEBSITE_CODES = qw/ mvh nsp /;
+
+$ENV{MV_CONFIG_FILE} = '/var/www/mvhub/www-data/conf/nsp.conf';
+$ENV{SUDO_USER} = 'www-data';
+
+{ # main
+ my $interactive = 0;
+ my $usage = 0;
+ my $hostname = `hostname`;
+ chomp $hostname;
+
+ Getopt::Long::GetOptions( 'prompt' => \$interactive,
+ 'help|?' => \$usage )
+ or die "GetOptions failed";
+ die usage() if $usage || $ENV{USER} ne 'root' || ( grep /^$hostname$/, @ALLOWED_HOSTS ) == 0;
+ local $OUTPUT_AUTOFLUSH = 1;
+
+ my $cfg =
+ MVHub::Utils::ConfigSimple::create_config_from( $ENV{MV_CONFIG_FILE} );
+
+ system('clear');
+
+ my $base_dir = $cfg->param('BASE.dir');
+ my @dirs = MVHub::Utils::Setup::get_dirs_with( "$base_dir", $USERNAME );
+
+ my $prompt = "Recreate $USERNAME directory structure? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_dirs_from( $USERNAME, \@dirs );
+ }
+
+ $prompt = "Update config files? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::make_config_files_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ $cfg = MVHub::Utils::ConfigSimple::create_config_from( $ENV{MV_CONFIG_FILE} );
+ }
+
+ $prompt = "Reload databases with recent production data? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::get_production_data( @WEBSITE_CODES );
+ MVHub::Utils::Setup::make_databases_for( $USERNAME, @WEBSITE_CODES );
+ MVHub::Utils::Setup::load_production_data( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
+ $prompt = "Apply database updates for $USERNAME? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::apply_database_updates_for( $USERNAME, $cfg, @WEBSITE_CODES );
+ }
+
+ $prompt = "Update contents of /etc? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::update_etc_files( $cfg );
+ MVHub::Utils::Setup::restart_services();
+ }
+
+ $prompt = "Run tests? (Y/N):";
+ if ( !($interactive) || IO::Prompt::prompt( $prompt, -YN ) ) {
+ MVHub::Utils::Setup::run_tests( $USERNAME, $cfg );
+ }
+}
+
+sub die_if_bad_env_for {
+ my $username = shift or croak 'missing parameter $username\n';
+ my $msg = '';
+
+ foreach my $var (qw/PERL5LIB MV_CONFIG_FILE/) {
+ $msg .= "$var not set"
+ if !defined $ENV{$var};
+ }
+
+ my $xtra_msg = <<'HERE';
+ if running with sudo edit /etc/sudoers to include line:
+
+ Defaults env_keep+="PERL5LIB MV_CONFIG_FILE"
+
+ also be sure you ran:
+
+ cdw
+HERE
+
+ if ($msg) {
+ $msg .= $xtra_msg;
+ }
+
+ $msg .= "\nneed to run under sudo if you aren't $username\n"
+ if ( $username ne $ENV{USER} && $EFFECTIVE_USER_ID != 0 );
+
+ $msg .=
+"\ncan't run mv_dev_update for user root, did you forget a \$user param on command line?\n"
+ if $username eq 'root';
+
+ die $msg if $msg;
+ return 1;
+}
+
+sub get_username_or_die {
+ my $username =
+ shift @ARGV
+ || $ENV{NEW_DEV_USER}
+ || ( defined $ENV{MV_CONFIG_FILE} ? $ENV{USER} : undef );
+
+ if ( !$username ) {
+ die "No username defined" . usage();
+ }
+ my @ignore = getpwnam($username);
+
+ if ( !scalar @ignore ) {
+ die "'$username' is not a valid username" . usage();
+ }
+
+ # should have nothing left on command line
+ # at this point
+ die usage() if scalar @ARGV;
+
+ return $username;
+}
+
+sub usage {
+ return << 'USAGE';
+mv_update_staging - Utility for updating the staging MVHub environment
+
+Usage: sudo mv_update_staging [options]
+
+Options:
+ --prompt Prompts the user before any action.
+ --help Gets this screen
+
+*** THIS COMMAND WILL ONLY RUN ON THE STAGING SERVER WITH SUDO ***
+USAGE
+
+}
=== modified file 'app-mvhub/project-tools/templates/template.conf'
--- app-mvhub/project-tools/templates/template.conf 2010-04-30 20:23:54 +0000
+++ app-mvhub/project-tools/templates/template.conf 2010-05-17 19:10:48 +0000
@@ -110,6 +110,8 @@
project_tools_dir=link-to-live-code/app-mvhub/project-tools/
tmp_dir=tmp/
setup_db_dir=link-to-live-code/app-mvhub/setup/database/sql/
+setup_etc_dir=link-to-live-code/app-mvhub/setup/etc/
+user_conf_dir=conf/
[COOKIES]
# name of cookie used to store
=== modified file 'app-mvhub/setup/database/update_db.pl'
--- app-mvhub/setup/database/update_db.pl 2010-05-03 21:01:56 +0000
+++ app-mvhub/setup/database/update_db.pl 2010-05-17 19:10:48 +0000
@@ -53,7 +53,7 @@
$ENV{PGUSER} = $cfg->param('DATABASE.database_user');
}
-sub get_version {
+sub get_db_version {
my $dbh = shift;
my $version;
=== added file 'lib-mvhub/lib/MVHub/Utils/Setup.pm'
--- lib-mvhub/lib/MVHub/Utils/Setup.pm 1970-01-01 00:00:00 +0000
+++ lib-mvhub/lib/MVHub/Utils/Setup.pm 2010-05-17 19:10:48 +0000
@@ -0,0 +1,674 @@
+package MVHub::Utils::Setup;
+
+use strict;
+use warnings;
+
+use Carp;
+use Config::Simple;
+use DateTime;
+use DBI;
+use IO::Prompt;
+use File::Basename;
+use File::Copy qw/ move /;
+
+use MVHub::Utils::DB qw/ get_data_source /;
+
+our @EXPORT_OK = qw(
+ add_apache_config
+ add_dns
+ get_production_data
+ get_testing_data
+ make_config_files_for
+ make_databases_for
+ make_dirs_from
+ load_production_data
+ load_test_data_for
+ restart_services
+ update_etc_files
+
+);
+
+sub _append_to_file {
+ my ( $file, $append_lines ) = @_;
+ my $tmp_file = "$file.tmp";
+
+ open( IN, $file )
+ or die "bad open: $file error: $! \n";
+ my @lines = <IN>;
+ close(IN) or die "bad close $file error: $!\n";
+
+ push @lines, $append_lines;
+
+ open( OUT, ">", "$tmp_file" )
+ or die "couldn't open $tmp_file.tmp error: $! \n";
+ ( print OUT @lines )
+ or die "couldn't write to $tmp_file $!\n";
+
+ close(OUT) or die "couldn't close $tmp_file $!\n";
+ File::Copy::move( $tmp_file, $file )
+ or die "couldn't rename $tmp_file to $file\n";
+}
+
+sub _add_calculable_values {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $username = shift or croak 'missing param: $username';
+ my $site_code = shift or croak 'missing param: $site_code';
+
+ $template_cfg->param( 'DATABASE.database_name', "$username.$site_code" );
+ $template_cfg->param( 'DATABASE.database_user', "$username" );
+ $template_cfg->param( 'NOTIFICATION.admin_email', "$username\@thecsl.org" );
+ $template_cfg->param( 'NOTIFICATION.dev_email', "$username\@thecsl.org" );
+ $template_cfg->param( 'SITE.website_name',
+ "$site_code.$username.testing123.net" );
+ $template_cfg->param( 'SITE.website_code', "$site_code" );
+
+ return $template_cfg;
+}
+
+sub _add_site_specific_values {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $username = shift or croak 'missing param: $username';
+ my %site_specific_values = @_;
+
+ foreach my $key ( keys %site_specific_values ) {
+ $template_cfg->param( $key, $site_specific_values{$key} );
+ }
+ return $template_cfg;
+}
+
+sub _add_user_generated_values {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $user_cfg = shift or croak 'missing param: $user_cfg';
+ my @keys = @_;
+
+ foreach my $key (@keys) {
+ if ( !( $user_cfg->param($key) ) ) {
+ prompt("Please enter a value for $key: ");
+ $template_cfg->param( $key, $_ );
+ }
+ }
+ return $template_cfg;
+}
+
+sub _db_exists {
+ my $dbh = shift or croak 'missing param: $dbh';
+ my $db_name = shift or croak 'missing param: $db_name';
+
+ my $sql = <<"SQL";
+SELECT
+ datname
+FROM
+ pg_database
+WHERE
+ datname = ?
+SQL
+
+ my $matching_dbs_aref = $dbh->selectall_arrayref( $sql, {}, ($db_name) );
+ return scalar @$matching_dbs_aref;
+
+}
+
+sub _db_user_found {
+ my $dbh = shift or croak 'missing param: $dbh';
+ my $username = shift or croak 'missing param: $username';
+
+ my $sql = <<"SQL";
+SELECT
+ usename
+FROM
+ pg_user
+WHERE
+ usename = ?
+SQL
+
+ my $matching_db_users_aref =
+ $dbh->selectall_arrayref( $sql, {}, ($username) );
+ return scalar @$matching_db_users_aref;
+}
+
+sub _db_user_has_needed_roles {
+ my $dbh = shift or croak 'missing param: $dbh';
+ my $username = shift or croak 'missing param: $username';
+
+ my $sql = <<"SQL";
+SELECT
+ rolname,rolcreaterole,rolcreatedb
+FROM
+ pg_roles
+WHERE
+ rolname = ?
+SQL
+
+ my $role_rows_aref =
+ $dbh->selectall_arrayref( $sql, { Slice => {} }, ($username) );
+ my $result = $$role_rows_aref[0]{rolcreaterole}
+ && $$role_rows_aref[0]{rolcreatedb};
+
+ return $result ? 1 : 0;
+}
+
+sub _db_user_has_superuser_role {
+ my $dbh = shift or croak 'missing param: $dbh';
+ my $username = shift or croak 'missing param: $username';
+
+ my $sql = <<"SQL";
+SELECT
+ rolname,rolsuper
+FROM
+ pg_roles
+WHERE
+ rolname = ?
+SQL
+
+ my $role_rows_aref =
+ $dbh->selectall_arrayref( $sql, { Slice => {} }, ($username) );
+ return $$role_rows_aref[0]{rolsuper} ? 1 : 0;
+}
+
+sub _determine_user_config_filename_from {
+ my $username = shift;
+ my $site_code = shift;
+ my $cfg = shift;
+
+ my $base_dir = $cfg->param('BASE.dir');
+ my $relative_conf_dir = $cfg->param('RELATIVE_PATH.user_conf_dir');
+
+ return "$base_dir/$username/$relative_conf_dir/$site_code.conf";
+}
+
+sub _do_or_die {
+ my $cmd = shift or croak 'missing param: $cmd';
+ $cmd =~ s/^\s+//;
+ my @cmd = split /\s+/, $cmd;
+ ( system(@cmd) == 0 )
+ or die "$cmd failed ABORTING\n";
+}
+
+sub _get_dbh {
+ my $config_file = shift or croak "missing param: config_file";
+ croak "couldn't read config_file: '$config_file'"
+ if not -r $config_file;
+
+ my $cfg = new Config::Simple($config_file);
+ my $database_username = $cfg->param('DATABASE.database_user');
+ my $auth = $cfg->param('DATABASE.database_magic_word');
+ my $host = $cfg->param('DATABASE.database_host');
+ my $port = $cfg->param('DATABASE.database_port');
+
+ my $data_source = "dbi:Pg:dbname=template1;host=$host;port=$port;";
+
+ my %attr = (
+ 'PrintError' => 1,
+ 'RaiseError' => 1,
+ 'AutoCommit' => 1,
+ 'ShowErrorStatement' => 1,
+ );
+
+ my $dbh = DBI->connect($data_source, $database_username, $auth, \%attr )
+ or die "couldn't connect to database";
+ return $dbh;
+
+}
+
+sub _get_site_specific_values {
+ my $site_code = shift or croak 'missing param: $site_code';
+
+ my %hash_of_site_specific_values = (
+ 'mvh' => {
+ 'SITE.location' => '"Massachusetts Merrimack Valley"',
+ 'SITE.website_description' => 'Merrimack Valley Hub',
+ 'NOTIFICATION.team_name' => 'Merrimack Valley Hub Team'
+ },
+ 'nsp' => {
+ 'SITE.location' => '"Massachusetts North Shore"',
+ 'SITE.website_description' => 'North Shore Portal',
+ 'NOTIFICATION.team_name' => 'North Shore Portal Team'
+ }
+ );
+ return %{ $hash_of_site_specific_values{$site_code} };
+}
+
+sub _make_empty_config_file_named {
+ my $filename = shift or croak 'missing Param $filename';
+
+ open my $out_fh, '>', $filename
+ or die "failed to open $filename for writing error:$!\n";
+ print $out_fh "#Config file\n [ignore]\n";
+ close $out_fh
+ or die "failed to close $filename error:$!\n";
+ return 1;
+}
+
+sub _merge_conf_objects {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $user_cfg = shift or croak 'missing param: $user_cfg';
+
+ foreach my $key ( $template_cfg->param() ) {
+ if ( !( $user_cfg->param($key) ) ) {
+ my $value = $template_cfg->param($key);
+ $value = defined $value ? $value : 'BAD_MISSING';
+ $user_cfg->param( $key, $value );
+ }
+ }
+
+ #remove keys no longer used
+ foreach my $key ( $user_cfg->param() ) {
+ if ( !defined $template_cfg->param($key) ) {
+ $user_cfg->delete($key);
+ }
+ }
+
+ return $user_cfg;
+}
+
+sub _possible_dup_line {
+ my $host = shift or croak 'missing parameter: $host';
+ my $filename = shift or croak 'missing parameter: $filename';
+
+ open my $in_fh, $filename
+ or die "failed to open $filename error:$!";
+
+ my @contents = <$in_fh>;
+ my $regex = qr/$host/;
+ return scalar grep { $_ =~ $regex } @contents;
+}
+
+sub _run_scripts {
+ my @scripts = @_;
+
+ foreach my $script (@scripts) {
+ my $filename = File::Basename::basename($script);
+ print "Executing $filename...";
+ my $output = `psql -f $script 2>&1`;
+ if ( $output =~ /COMMIT/ ) {
+ print "SUCCESS\n";
+ }
+ elsif ( $output =~ /ROLLBACK/ ) {
+ print "FAIL\n";
+ print
+ "The following OUTPUT occured while processing $filename:\n";
+ die "$output\n\n****Processing $filename FAILED****\n";
+ }
+ }
+
+}
+
+
+sub _set_db_ENV_vars {
+ my $cfg = shift;
+
+ # so psql stops on error
+ $ENV{ON_ERROR_STOP} = 1;
+
+ $ENV{PGDATABASE} = $cfg->param('DATABASE.database_name');
+ $ENV{PGHOST} = $cfg->param('DATABASE.database_host');
+ $ENV{PGPASSWORD} = $cfg->param('DATABASE.database_magic_word');
+ $ENV{PGUSER} = $cfg->param('DATABASE.database_user');
+}
+
+sub add_dns {
+ my $username = shift or croak 'missing paramater: $username';
+ my $prefix = shift or croak 'missing parameter: $prefix';
+
+ my $host = "$prefix.$username";
+ my $FILE = '/etc/bind/db.testing123.net';
+
+ my $line = sprintf( "%-15s IN A 129.63.96.180\n", $host );
+ if ( _possible_dup_line( $host, $FILE ) ) {
+ warn "$host found in $FILE, skipping append\n";
+ return;
+ }
+
+ _append_to_file( $FILE, $line );
+}
+
+sub add_apache_config {
+ my $username = shift or croak 'missing paramater: $username';
+ my $prefix = shift or croak 'missing parameter: $prefix';
+
+ my $FILE = '/etc/apache2/sites-available/mvhub_developer.data';
+ my $host = "$prefix.$username.testing123.net";
+
+ my $line = sprintf( "Use MVhub %-15s $prefix $host\n", $username );
+
+ if ( _possible_dup_line( $host, $FILE ) ) {
+ warn "$host found in $FILE, skipping append\n";
+ return;
+ }
+
+ _append_to_file( $FILE, $line );
+}
+
+sub apply_database_updates_for {
+ my $username = shift or croak 'missing paramater: $username';
+ my $cfg = shift or croak 'missing paramter: $cfg';
+ my @website_codes = @_;
+
+ foreach my $prefix (@website_codes) {
+ my $update_user_cfg_filename = _determine_user_config_filename_from($username, $prefix, $cfg);
+ my $update_user_cfg = MVHub::Utils::ConfigSimple::create_config_from($update_user_cfg_filename);
+ my $dbh = MVHub::Utils::DB::get_dbh($update_user_cfg_filename);
+
+ my $db_version = get_db_version($dbh);
+ my $scripts_path = $cfg->param("ABSOLUTE_PATH.setup_db_dir");
+ my @db_scripts = get_scripts( version => $db_version, path => $scripts_path );
+
+ if ( scalar @db_scripts ) {
+ print "Applying $prefix database updates...\n";
+ _set_db_ENV_vars($update_user_cfg);
+ _run_scripts(@db_scripts);
+ }
+ else {
+ print "$prefix database up-to-date at Version $db_version.\n";
+ }
+ }
+}
+
+sub get_db_version {
+ my $dbh = shift;
+ my $version;
+
+ my $exist_sql
+ = "SELECT 1 FROM information_schema.tables WHERE table_name='version_log' LIMIT 1";
+ my $table_exists = ( $dbh->selectrow_array($exist_sql) )[0];
+
+ if ($table_exists) {
+ my $sql = "SELECT max(version) FROM version_log;";
+ $version = ( $dbh->selectrow_array($sql) )[0];
+ }
+ else {
+ $version = 0;
+ }
+
+ return $version;
+}
+
+sub get_scripts {
+ my %args = @_;
+
+ my @raw_scripts = glob "$args{path}/*.sql";
+ my @scripts;
+
+ foreach my $script ( sort @raw_scripts ) {
+
+ if ( $script =~ m#\/(\d{3})_[\w\-]+\.sql# ) {
+ my $script_version = int $1;
+
+ if ( $script_version > $args{'version'} ) {
+ push @scripts, $script;
+ }
+ }
+ else {
+ die
+ "ERROR: '$script' does not conform to naming standard: nnn_word_description.sql\n";
+ }
+ }
+ return sort @scripts;
+}
+
+sub get_dirs_with {
+ my $base_dir = shift or croak 'missing param: $base_dir';
+ my $username = shift or croak 'missing param: $username';
+ my @dirs = (
+ {
+ dir => 'conf',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ },
+ {
+ dir => 'cover_db',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ },
+ {
+ dir => 'reports',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=r-x',
+ },
+ {
+ dir => 'reports',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ },
+ {
+ dir => 'source-code',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ },
+ {
+ dir => 'log/mvh',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ },
+ {
+ dir => 'log/nsp',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ },
+ {
+ dir => 'tmp',
+ owner => '',
+ group => '',
+ permissions => 'u=rwx,g=rwsx,o=rx',
+ }
+ );
+ foreach my $dir_href (@dirs) {
+ $dir_href->{owner} = $username
+ if not $dir_href->{owner};
+ $dir_href->{group} = $username
+ if not $dir_href->{group};
+
+ $dir_href->{dir} = "$base_dir/$username/" . $dir_href->{dir};
+ }
+ return @dirs;
+}
+
+sub get_production_data {
+ my @website_codes = @_;
+ my $cmd;
+
+ my $dt = DateTime->now()->subtract( days => 1 );
+ my $ymd = $dt->ymd;
+ my $dow = $dt->day_abbr;
+ my $timestamp = "${ymd}-06_25-${dow}";
+
+ print "Getting recent backup of production data...";
+ foreach my $site_code (@website_codes) {
+ $cmd = "rsync csl-db-02.inside::backup/postgres/";
+ $cmd .= "${timestamp}_${site_code}_production_db.dump ";
+ $cmd .= "/tmp/${site_code}_production_data.dump";
+
+ ( system($cmd) == 0 ) or die "Failed to rsync ${timestamp}_${site_code}_production_db.sql\n";
+ }
+ print "done\n";
+}
+
+sub load_production_data {
+ my $username = shift or croak 'missing param: $username';
+ my $cfg = shift or croak 'missing param: $cfg';
+ my @website_codes = @_;
+
+ my $cmd;
+
+ print "Loading production data...";
+ foreach my $suffix ( @website_codes ) {
+ my $cfg_filename = _determine_user_config_filename_from($username, $suffix, $cfg);
+ my $user_cfg = MVHub::Utils::ConfigSimple::create_config_from($cfg_filename);
+
+ _set_db_ENV_vars($user_cfg);
+
+ $cmd = "pg_restore -O -x -d $username.$suffix /tmp/${suffix}_production_data.dump >/dev/null";
+
+ ( system($cmd) == 0 )
+ or warn "failed to load ${suffix}_production_data.dump";
+ }
+ print "done\n";
+}
+
+sub load_test_data_for {
+ my $username = shift or croak 'missing param: $username';
+ my $cfg = shift or croak 'missing param: $cfg';
+ my @website_codes = @_;
+
+ my $path_to_project_tools = $cfg->param('ABSOLUTE_PATH.project_tools_dir');
+ my $cmd;
+
+ print "Loading test data...";
+ foreach my $suffix ( @website_codes ) {
+ my $cfg_filename = _determine_user_config_filename_from($username, $suffix, $cfg);
+ my $user_cfg = MVHub::Utils::ConfigSimple::create_config_from($cfg_filename);
+
+ _set_db_ENV_vars($user_cfg);
+
+ $cmd = "psql -f ${path_to_project_tools}/test_${suffix}_db.sql >/dev/null";
+
+ ( system($cmd) == 0 )
+ or warn "failed to load data for $username.$suffix";
+ }
+ print "done\n";
+}
+
+sub make_config_files_for {
+ my $username = shift;
+ my $cfg = shift;
+ my @website_codes = @_;
+ my @keys_for_user_generated_values = qw/ DATABASE.database_magic_word /;
+
+ my $template_config_file =
+ $cfg->param('ABSOLUTE_PATH.template_conf_dir') . "/template.conf";
+ my $template_cfg = new Config::Simple($template_config_file)
+ or die "failed to create config object from $template_config_file";
+
+ foreach my $site_code (@website_codes) {
+
+ my $cfg_filename = _determine_user_config_filename_from($username, $site_code, $cfg);
+ my $user_cfg = new Config::Simple( syntax => 'ini' );
+ if ( !-e $cfg_filename ) {
+ _make_empty_config_file_named($cfg_filename);
+ }
+ $user_cfg->read($cfg_filename);
+
+ print "Updating Config: $cfg_filename\n";
+ my %site_specific_values = _get_site_specific_values($site_code);
+
+ $template_cfg = _add_site_specific_values( $template_cfg, $username,
+ %site_specific_values );
+ $template_cfg =
+ _add_calculable_values( $template_cfg, $username, $site_code );
+ $template_cfg = _add_user_generated_values( $template_cfg, $user_cfg,
+ @keys_for_user_generated_values );
+
+ _merge_conf_objects( $template_cfg, $user_cfg );
+
+ $user_cfg->write($cfg_filename);
+ }
+}
+
+sub make_databases_for {
+ my $username = shift or croak 'missing parameter: $username';
+ my @website_codes = @_ or croak 'mssing parameter: @website_codes';
+
+ my $dbh = _get_dbh( $ENV{MV_CONFIG_FILE} );
+ my $sql;
+ my $user_running_cmd =
+ defined $ENV{SUDO_USER} ? $ENV{SUDO_USER} : $ENV{USER};
+
+ print "(re)making databases for $username...";
+
+ if ( !_db_user_has_needed_roles( $dbh, $user_running_cmd ) ) {
+ warn
+"\nSkipping db stuff $user_running_cmd lacks CREATEDB or CREATEROLE\n";
+ return;
+ }
+
+ if ( ( $user_running_cmd ne $username )
+ && !_db_user_has_superuser_role( $dbh, $user_running_cmd ) )
+ {
+ my $msg = qq/
+ skipping db stuff $user_running_cmd can't drop table owned by $username
+ without role SUPERUSER
+ /;
+ warn $msg;
+ return;
+ }
+
+ if ( !_db_user_found( $dbh, $username ) ) {
+ $sql = "CREATE USER $username WITH PASSWORD 'test' CREATEDB CREATEROLE";
+ $dbh->do($sql);
+ }
+
+ foreach my $suffix (@website_codes) {
+ if ( _db_exists( $dbh, "$username.$suffix" ) ) {
+ $sql = qq{DROP DATABASE "$username.${suffix}"};
+ $dbh->do($sql);
+ }
+
+ # kludge to avoid 'db being currently being accessed' errs
+ sleep 1;
+
+ $sql = qq{CREATE DATABASE "$username.${suffix}" OWNER "$username" ENCODING='SQL_ASCII' };
+ $dbh->do($sql);
+
+ }
+ print "done\n";
+}
+
+sub make_dirs_from {
+ my $username = shift or croak 'missing param: $username';
+ my $dir_hrefs_href = shift or croak 'missing param: $dir_hrefs_href';
+ my @dir_hrefs = @$dir_hrefs_href;
+
+ print "Updating $username directory structure...";
+ foreach my $dir_href (@dir_hrefs) {
+ my $mkdir_cmd = "mkdir -p $dir_href->{dir}";
+ my $chown_cmd =
+ "chown -R $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
+ if ( $dir_href->{dir} =~ /log/ ) {
+
+ # root owns log files it creates don't try to change ownership on them
+ $chown_cmd =
+ "chown $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
+ }
+ else {
+ $chown_cmd =
+ "chown -R $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
+ }
+ my $chmod_cmd = "chmod $dir_href->{permissions} $dir_href->{dir}";
+ _do_or_die($mkdir_cmd);
+ _do_or_die($chown_cmd);
+ _do_or_die($chmod_cmd);
+ }
+ print "done\n";
+}
+
+sub restart_services {
+ system('apache2ctl restart');
+ my $is_apache_running = `ps aux | grep 'apache2' | grep -v grep`;
+ die "Apache failed to start" if !($is_apache_running);
+}
+
+sub run_tests {
+ my $username = shift;
+ my $cfg = shift;
+
+ print "Running tests...\n";
+ my $project_tools_path = $cfg->param('ABSOLUTE_PATH.project_tools_dir');
+ my $cmd = "$project_tools_path/bin/mv_su_test $username";
+ ( system($cmd) == 0 ) or die "Failed to run tests\n";
+}
+
+sub update_etc_files {
+ my $cfg = shift;
+ my $etc_path = $cfg->param('ABSOLUTE_PATH.setup_etc_dir');
+ print "Updating contents of /etc...\n";
+ my $cmd = "cp -vur $etc_path /";
+ ( system($cmd) == 0 ) or die "Failed to copy etc files\n";
+}
+
=== modified file 'lib-mvhub/t/conf/all.conf'
--- lib-mvhub/t/conf/all.conf 2010-04-30 20:23:54 +0000
+++ lib-mvhub/t/conf/all.conf 2010-05-17 19:10:48 +0000
@@ -94,6 +94,8 @@
project_tools_dir=link-to-live-code/app-mvhub/project-tools/
tmp_dir=tmp/
setup_db_dir=link-to-live-code/app-mvhub/setup/database/sql/
+setup_etc_dir=link-to-live-code/app-mvhub/setup/etc/
+user_conf_dir=conf/
[COOKIES]
# name of cookie used to store
Follow ups
-
[Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: noreply, 2010-05-21
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-21
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-21
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Lee Goodrich, 2010-05-19
-
Re: [Merge] lp:~leegoodrich/mvhub/refactor_mv_setup into lp:mvhub
From: Dan MacNeil, 2010-05-17