package WebServerRemote 0.000001; use Carp; use Moose; use Data::Dumper; use Modern::Perl; use Params::Validate; use MyWebsite; use namespace::autoclean; with 'MyOpenSSH'; with 'Apache2Info'; sub get_file { validate_pos(@_, 1, 1); my $self = shift; my $file_path = shift; return $self->capture("cat $file_path"); } # get website objects based on domain name sub get_websites { validate_pos(@_, 1, 1); my ($self, $domain) = @_; my @websites = (); # website objects my $config_files = $self->lookup_config_files($domain); # list of config files croak 'No config files found with ' . $domain if !@$config_files; foreach my $file (@$config_files) { my $config = $self->get_file($file); #my @cmds = qw( servername, suexecusergroup, customlog, serveralias ); foreach my $docroot (@{$self->get_docroots_from_string($config)}) { my $vh = $self->get_vh_context($config, 'documentroot', $docroot); my @aliases = (); my $aliases = ''; while (my $alias = $vh->cmd_config('serveralias')) { push @aliases, $alias; } $aliases = join ', ', @aliases; my $suexec = $vh->cmd_config('suexecusergroup') || ''; my $servername = $vh->cmd_config('servername') || ''; my $errorlog = $vh->cmd_config('errorlog') || ''; push @websites, MyWebsite->new ( docroot => $docroot, apache_config_path => $file, domain => $servername, suexecgroup => $suexec, aliases => $aliases, error_log => $errorlog, ssh => $self->ssh->get_user . '@' . $self->ssh->get_host, ); } } return \@websites; } sub check_dir_for_files { validate_pos(@_, 1, 1, 1); my $self = shift; my $dir = shift; my $files = shift; my $listing = $self->capture('ls -1 ' . $dir); my %files = map { $_ => 1 } split /\n/, $listing; my @fail = (); # $files can be a scalar or an array if (ref $files) { push @fail, grep { !exists $files{$_} } @$files; return !@fail; } else { return $files{$files}; } } ########################################## #### package MyOpenSSH 0.000001; use Carp; use Data::Dumper; use Moose::Role; use Modern::Perl; use Net::OpenSSH; use Params::Validate; has 'ssh' => (is => 'rw', isa => 'Net::OpenSSH', required => 1, lazy => 0, handles => qr/[^(capture)]/, ); around BUILDARGS => sub { my $orig = shift; my $class = shift; my %args = ref $_[0] ? %{$_[0]} : @_; croak 'a host must be supplied for ssh: ssh => (\'@\', %opts)' if !%args; my ($host, %opts) = $args{ssh}; return $class->$orig( %args) if ref $host eq 'Net::OpenSSH'; delete $args{ssh}; my $ssh = Net::OpenSSH->new($host, %opts); $ssh->error and croak "could not connect to host: $ssh->error"; return $class->$orig( ssh => $ssh, %args ); }; # wrapper for system method sub exec { validate_pos(@_, 1, 1); my $self = shift; my $cmd = shift; $self->ssh->system($cmd) || carp 'Command failed: ' . $self->ssh->error; } # wrapper for capture method sub capture { validate_pos(@_, 1, 1); my $self = shift; my $cmd = shift; $self->ssh->capture($cmd) || carp 'Command failed: ' . $self->ssh->error; } ########################################### #### package Apache2Info 0.000001; use Carp; use Try::Tiny; use File::Spec; use File::Util; use Moose::Role; use Data::Dumper; use Modern::Perl; use File::Listing; use File::Basename; use Params::Validate; use Apache::ConfigFile; requires 'ssh'; # get document roots of a config file sub get_docroots_from_string { --snip-- } # searches a config file string for a command and returns virtual host config # if a match is found sub get_vh_context { --snip-- } # Apache::ConfigParser requires a path to a file as an argument # so we save contents to a file first and then read it sub _read { --snip-- } # get list of absolute, non-canonical paths to all apache configuration file sub get_enabled_apache_config_filenames { --snip-- } # get a listing of all directories where config files reside sub get_config_file_dirs { --snip-- } # get all docroots sub get_all_docroots { --snip-- } # find the config files for a given domain name sub lookup_config_files { --snip-- ############################################### #### package MyWebsite 0.000001; use Carp; use Moose; use Modern::Perl; use Drupal; use WordPress; extends 'WebServerRemote'; with 'MyOpenSSH'; use namespace::autoclean; has 'db' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'ver' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'type' => (is => 'ro', isa => 'Str', required => 0, lazy => 1, builder => '_set_type'); has 'domain' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'aliases' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'docroot' => (is => 'rw', isa => 'Str', required => 1, lazy => 0 ); has 'db_user' => (is => 'ro', isa => 'Str', required => 0, lazy => 1, default => '', writer => '_set_dbuser', ); has 'db_pass' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'root_dir' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'error_log' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'site_config' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'suexecgroup' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'apache_config' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'site_config_path' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); has 'apache_config_path' => (is => 'rw', isa => 'Str', required => 0, lazy => 1, default => '', ); sub _set_type { my $self = shift; # check for drupal multi site if ($self->check_dir_for_files($self->docroot, ['sites', 'includes', 'modules'])) { $self = Drupal->meta->rebless_instance($self); return 'drupal'; } if ($self->check_dir_for_files($self->docroot, 'wp-config.php')) { $self = WordPress->meta->rebless_instance($self); return 'wordpress'; } if ($self->check_dir_for_files($self->docroot, 'settings.php')) { $self = Drupal->meta->rebless_instance($self); return 'drupal'; } } ##############################################