File Coverage

blib/lib/HealthCheck/Diagnostic/SSH.pm
Criterion Covered Total %
statement 59 60 98.3
branch 18 22 81.8
condition 4 7 57.1
subroutine 10 10 100.0
pod 5 5 100.0
total 96 104 92.3


line stmt bran cond sub pod time code
1             package HealthCheck::Diagnostic::SSH;
2              
3 2     2   460380 use strict;
  2         4  
  2         78  
4 2     2   12 use warnings;
  2         11  
  2         116  
5              
6 2     2   458 use parent 'HealthCheck::Diagnostic';
  2         225  
  2         14  
7              
8 2     2   12103 use Net::SSH::Perl ();
  2         170187  
  2         103  
9              
10             # ABSTRACT: Verify SSH connectivity to specified host.
11 2     2   36 use version;
  2         5  
  2         16  
12             our $VERSION = 'v0.1.0'; # VERSION
13              
14             sub new {
15 2     2 1 242020 my ($class, @params) = @_;
16              
17             my %params = @params == 1 && ( ref $params[0] || '' ) eq 'HASH'
18 2 50 33     16 ? %{ $params[0] } : @params;
  0         0  
19              
20 2         20 return $class->SUPER::new(
21             id => 'ssh',
22             label => 'SSH',
23             %params,
24             );
25             }
26              
27             sub check {
28 8     8 1 10260 my ($self, %params) = @_;
29              
30             # Make it so that the diagnostic can be used as an instance or a
31             # class, and the `check` params get preference.
32 8 50       29 if ( ref $self ) {
33             $params{ $_ } = $self->{ $_ }
34 8         34 foreach grep { ! defined $params{ $_ } } keys %$self;
  34         112  
35             }
36              
37             # The host is the only required parameter.
38             return {
39             id => $params{'id'},
40             label => $params{'label'},
41             status => 'UNKNOWN',
42             info => "Missing required input: No host specified",
43 8 100       39 } unless $params{host};
44              
45 7         43 return $self->SUPER::check(%params);
46             }
47              
48             sub run {
49 7     7 1 201 my ($self, %params) = @_;
50              
51             # Get our description of the connection.
52 7         16 my $user = $params{user};
53 7         14 my $name = $params{name};
54 7 100       44 my $target = ( $user ? $user.'@' : '' ).$params{host};
55 7 100       20 my $description = $name ? "$name ($target) SSH" : "$target SSH";
56              
57             # connect to SSH
58 7         13 my $ssh;
59 7         10 local $@;
60 7         12 eval {
61 7         33 local $SIG{__DIE__};
62 7         25 $ssh = $self->ssh_connect( %params );
63             };
64             return {
65 7 100       74 status => 'CRITICAL',
66             info => "Error for $description: $@",
67             } if $@;
68              
69             # if there were no errors, it should've connected
70             return {
71             status => 'OK',
72             info => "Successful connection for $description",
73 5 100       98 } unless $params{command};
74              
75             # run command if exists
76 3         14 my %res = $self->run_command( $ssh, %params );
77             return {
78             status => 'CRITICAL',
79             info => "$description: $res{error}",
80 3 50       13 } if $res{error};
81              
82             return {
83             status => $res{exit_code} == 0 ? 'OK' : 'CRITICAL',
84             info => "$description <$params{command}> exit is $res{exit_code}",
85 3 100       40 $params{return_output} ? ( data => \%res ) : (),
    100          
86             };
87             }
88              
89             sub ssh_connect {
90 7     7 1 25 my ( $self, %params ) = @_;
91              
92 7         16 my $host = $params{host};
93 7         12 my $user = $params{user};
94 7         12 my $password = $params{password};
95             my %ssh_params = (
96             protocol => 2,
97 7   100     29 %{ $params{ssh_args} // {} },
  7         52  
98             );
99              
100 7         42 my $ssh = Net::SSH::Perl->new( $host, %ssh_params );
101 6         76 $ssh->login( $user, $password );
102              
103 5         67 return $ssh;
104             }
105              
106             sub run_command {
107 3     3 1 11 my ( $self, $ssh, %params ) = @_;
108 3         7 my %res;
109              
110 3         8 local $@;
111 3         24 eval {
112 3         13 local $SIG{__DIE__};
113             my ($stdout, $stderr, $exit_code) = $ssh->cmd(
114             $params{command},
115 3   50     24 $params{stdin} // '',
116             );
117 3         28 $res{ stdout } = $stdout;
118 3         7 $res{ stderr } = $stderr;
119 3         12 $res{ exit_code } = $exit_code;
120             };
121 3 50       8 $res{ error } = $@ if $@;
122              
123 3         19 return %res;
124             }
125              
126             1;
127              
128             __END__