Hi
I've wrapped Perl's Net::SSH::Expect with a small module to reduce the boilerplate code needed to write a new configuration script for use with our HP iLO cards. While on one hand I want this wrapper to be as lean as possible, so non-programmer colleagues can use it, I also want it to be as well-written as possible.
It's used like so:
my $ilo = iLO->new(host => $host, password => $password);
$ilo->login;
$ilo->command("cd /system1");
$ilo->command("set oemhp_server_name=$system_name", 'status=0');
and this is iLO::command()
:
sub command {
my ($self, $cmd, $response) = @_;
$response = 'hpiLO-> ' unless defined($response);
# $self->{ssh} is a Net::SSH::Expect object
croak "Not logged in!\n" unless ($self->{ssh});
$self->{ssh}->send($cmd);
if ($self->{ssh}->waitfor($response, $self->{CMD_TIMEOUT}, '-re')) {
return {
before => $self->{ssh}->before(),
match => $self->{ssh}->match(),
after => $self->{ssh}->after(),
};
} else {
carp "ERROR: '$cmd' response did not match /$response/:\n\n",
$self->{ssh}->before()),
"\n";
return undef;
}
}
I have two related queries. First, how should I deal with responses that don't match the expected response? I guess what I'm doing now is satisfactory -- by returning undef
I signal something broke and my croak()
will output an error (though hardly gracefully). But it feels like a code smell. If Perl had exceptions I'd raise one and let the calling code decide whether or not to ignore it/quit/print a warning, but it doesn't (well, in 5.8). Perhaps I should return some other object (iLO::response
, or something) that carries an error message and the contents of $ilo->before()
(which is just Net::SSH::Expect's before()
)? But if I do that -- and have to wrap every $ilo->command
in a test to catch it -- my scripts are going to be full of boilerplate again.
Secondly, what should I return for success? Again, my hash containing more-or-less the response from Net::SSH::Expect does the job but it doesn't feel 'right' somehow. Although this example's in Perl my code in other languages emits the same familiar smell: I'm never sure how or what to return from a method. What can you tell me?