App-ClusterSSH

 view release on metacpan or  search on metacpan

lib/App/ClusterSSH/Host.pm  view on Meta::CPAN

package App::ClusterSSH::Host;

use strict;
use warnings;

use version;
our $VERSION = version->new('0.03');

use Carp;
use Net::hostent;

use base qw/ App::ClusterSSH::Base /;

our %ssh_hostname_for;
our %ssh_configs_read;

sub new {
    my ( $class, %args ) = @_;

    if ( !$args{hostname} ) {
        croak(
            App::ClusterSSH::Exception->throw(
                error => $class->loc('hostname is undefined')
            )
        );
    }

    # remove any keys undef values - must be a better way...
    foreach my $remove (qw/ port username geometry /) {
        if ( !$args{$remove} && grep {/^$remove$/} keys(%args) ) {
            delete( $args{$remove} );
        }
    }

    my $self
        = $class->SUPER::new( ssh_config => "$ENV{HOME}/.ssh/config", %args );

    # load in ssh hostname for later use
    if ( !%ssh_hostname_for || !$ssh_configs_read{ $self->{ssh_config} } ) {
        $self->read_ssh_file( $self->{ssh_config} );

        $self->debug( 5, 'Have the following ssh hostnames' );
        $self->debug( 5, '  "', $_, '"' )
            foreach ( sort keys %ssh_hostname_for );
    }

    return $self;
}

sub read_ssh_file($$) {
    my ($self)     = shift;
    my ($filename) = glob(shift);
    $self->debug( 3, 'Reading SSH file: ', $filename );

    $ssh_configs_read{$filename} = 1;

    if ( open( my $ssh_config_fh, '<', $filename ) ) {
        while ( my $line = <$ssh_config_fh> ) {
            chomp $line;

            if ( $line =~ /^\s*include\s+(.+)/i ) {
                $self->read_ssh_file($1);
                next;
            }

            next unless ( $line =~ m/^\s*host\s+(.*)/i );

            # account for multiple declarations of hosts
            $ssh_hostname_for{$_} = 1 foreach ( split( /\s+/, $1 ) );
        }
        close($ssh_config_fh);
    }
    else {
        $self->debug( 3, 'Unable to read ', $filename, ': ', $!, $/ );
    }
}

sub get_hostname {
    my ($self) = @_;
    return $self->{hostname};
}

lib/App/ClusterSSH/Host.pm  view on Meta::CPAN

    }

    # Check for a '/nnnn' port definition
    if ( $host_string =~ s!(?:/(\d+)$)!! ) {
        $port = $1;
    }

    # use number of colons as a possible indicator
    my $colon_count = $host_string =~ tr/://;

    # if there are 7 colons assume its a full IPv6 address
    # if its 8 then assumed full IPv6 address with a port
    # also catch localhost address here
    if ( $colon_count == 7 || $colon_count == 8 || $host_string eq '::1' ) {
        if ( $colon_count == 8 ) {
            $host_string =~ s/(?::(\d+?))$//;
            $port = $1;
        }
        $self->debug(
            5,
            $self->loc(
                'IPv6: u=[_1] h=[_2] p=[_3] g=[_4]',
                $username, $host_string, $port, $geometry,
            ),
        );
        return __PACKAGE__->new(
            parse_string => $parse_string,
            username     => $username,
            hostname     => $host_string,
            port         => $port,
            geometry     => $geometry,
            type         => 'ipv6',
        );
    }
    if (   $colon_count > 1
        && $colon_count < 8 )
    {
        warn 'Ambiguous host string: "', $host_string, '"',   $/;
        warn 'Assuming you meant "[',    $host_string, ']"?', $/;

        $self->debug(
            5,
            $self->loc(
                'Ambiguous IPv6 u=[_1] h=[_2] p=[_3] g=[_4]',
                $username, $host_string, $port, $geometry,
            )
        );

        return __PACKAGE__->new(
            parse_string => $parse_string,
            username     => $username,
            hostname     => $host_string,
            port         => $port,
            geometry     => $geometry,
            type         => 'ipv6',
        );
    }

    # if we got this far, we didnt parse the host_string properly
    croak(
        App::ClusterSSH::Exception->throw(
            error => $self->loc(
                'Unable to parse hostname from "[_1]"', $host_string
            )
        )
    );
}

sub check_ssh_hostname {
    my ( $self, ) = @_;

    $self->debug( 4, 'Checking ssh hosts for hostname ',
        $self->get_hostname );

    if ( $ssh_hostname_for{ $self->get_hostname } ) {
        $self->debug( 5, 'Found' );
        return 1;
    }
    else {
        $self->debug( 5, 'Not found' );
        return 0;
    }
}

use overload (
    q{""} => sub {
        my ($self) = @_;
        return $self->{hostname};
    },
    fallback => 1,
);

1;

=pod

=head1 NAME

ClusterSSH::Host - Object representing a host.

=head1 SYNOPSIS

    use ClusterSSH::Host;

    my $host = ClusterSSH::Host->new({
        hostname => 'hostname',
    });
    my $host = ClusterSSH::Host->parse_host_string('username@hostname:1234');

=head1 DESCRIPTION

Object representing a host.  Include details to contact the host such as
hostname/ipaddress, username and port.

=head1 METHODS

=over 4

=item $host=ClusterSSH::Host->new ({ hostname => 'hostname' })

Create a new host object.  'hostname' is a required arg, 'username' and 



( run in 0.670 second using v1.01-cache-2.11-cpan-39bf76dae61 )