RSS Git Download  Clone
Raw Blame History
package Local::SSHTunnel;

# adapted from:
# Re: How do you use Net::OpenSSH to query mysql database via ssh tunnel
# https://www.perlmonks.org/?node_id=11106237

use Types::Standard qw(Str); # HashRef ArrayRef  Object
use Data::Printer;
use Net::OpenSSH;
use Local::DB; # path in crontab PERL5LIB
use Moo;

my $LOCAL_PORT = 3307;
my $DB_PORT    = 3306;

has remote_host => ( is => 'ro', required => 1 );
has db_name     => ( is => 'ro', isa => Str ); # optional, for dbix()

has dbix => ( is => 'lazy' );
has ssh  => ( is => 'ro', builder => sub {
    my $ssh = Net::OpenSSH->new( shift->remote_host, master_opts =>
        "-L127.0.0.1:$LOCAL_PORT:localhost:$DB_PORT" );
    die "Couldn't establish SSH connection: ". $ssh->error if $ssh->error;
    return $ssh;
  }
 );

sub _build_dbix {
	my $self = shift;
    # check db_name var has been supplied:
    $self->db_name || die "db_name variable required if calling dbix()";

    my %h = ( dbname => $self->db_name, port => $LOCAL_PORT );
	my $dbix = Local::DB->dbix(\%h); # p $dbix;
	# my $img = $dbix->select('images', 'img_name', { id => 7255 })->value; p $img;
    return $dbix;
    #return { # alternative arrangement to keep $ssh in scope
    #    dbix => $dbix,
    #    ssh  => $ssh, # need to keep this in scope for query to succeed
    #}
}

=begin
my $REMOTE_HOST = 'hmds.org.uk';
my $DB_NAME     = 'exif_data';
my $DB_USERNAME = '***';
my $DB_PASSWORD = '****';

sub new {
    my $class = shift;
    $class = ref $class || $class;

    my $ssh = Net::OpenSSH->new( $REMOTE_HOST, master_opts =>
		"-L127.0.0.1:$LOCAL_PORT:localhost:$DB_PORT" );
    die "Couldn't establish SSH connection: ". $ssh->error if $ssh->error;

    #my $dsn = "DBI:mysql:database=$DB_NAME;host=127.0.0.1;port=$LOCAL_PORT";
    #my $dbh = DBI->connect($dsn, $DB_USERNAME, $DB_PASSWORD);

    my $self = {
        dbh => $dbix,
        ssh => $ssh,
    };
    bless $self, $class;
    return $self;
}

#=begin # for DBI
sub disconnect {
    my ($self) = @_;
    $self->{dbh}->disconnect;
    $self->{ssh}->system('exit');
}

sub DESTROY {
    disconnect();
}
#=begin
sub AUTOLOAD {
    my $self= shift;

    return if $AUTOLOAD =~ /::DESTROY$/;

    $AUTOLOAD =~ s/^.*:://;
    $self->{dbh}->$AUTOLOAD(@_);
}
=cut

1;