#
# (c) Jan Gehring <jan.gehring@gmail.com>
#
# vim: set ts=3 sw=3 tw=0:
# vim: set expandtab:
package Rex::Group::Entry::Server;
use strict;
use warnings;
use Rex::Logger;
use Rex::Helper::System;
use Rex::Config;
use Data::Dumper;
use overload
'eq' => sub { shift->is_eq(@_); },
'ne' => sub { shift->is_ne(@_); },
'""' => sub { shift->to_s(@_); };
use attributes;
sub function {
my ($class, $name, $code) = @_;
no strict "refs";
*{ $class . "::" . $name } = $code;
use strict;
}
sub new {
my $that = shift;
my $proto = ref($that) || $that;
my $self = { @_ };
bless($self, $proto);
# be save check if name is already a server ref
if(ref $self->{name} eq __PACKAGE__) {
return $self->{name};
}
# rewrite auth info
if($self->{user}) {
$self->{auth}->{user} = $self->{user};
delete $self->{user};
}
if($self->{password}) {
$self->{auth}->{password} = $self->{password};
delete $self->{password};
}
if($self->{public_key}) {
$self->{auth}->{public_key} = $self->{public_key};
delete $self->{public_key};
}
if($self->{private_key}) {
$self->{auth}->{private_key} = $self->{private_key};
delete $self->{private_key};
}
if($self->{sudo}) {
$self->{auth}->{sudo} = $self->{sudo};
delete $self->{sudo};
}
if($self->{sudo_password}) {
$self->{auth}->{sudo_password} = $self->{sudo_password};
delete $self->{sudo_password};
}
if($self->{auth_type}) {
$self->{auth}->{auth_type} = $self->{auth_type};
delete $self->{auth_type};
}
return $self;
}
sub get_servers {
my ($self) = @_;
return map {
if(ref($_) ne "Rex::Group::Entry::Server") {
$_ = Rex::Group::Entry::Server->new(name => $_, auth => $self->{auth});
}
else {
$_;
}
} $self->evaluate_hostname;
}
sub to_s {
my ($self) = @_;
return $self->{name};
}
sub is_eq {
my ($self, $comp) = @_;
if($comp eq $self->to_s) {
return 1;
}
}
sub is_ne {
my ($self, $comp) = @_;
if($comp ne $self->to_s) {
return 1;
}
}
sub has_auth {
my ($self) = @_;
return exists $self->{auth};
}
sub set_auth {
my ($self, %auth) = @_;
$self->{auth} = \%auth;
}
sub get_auth {
my ($self) = @_;
return $self->{auth};
}
sub get_user {
my ($self) = @_;
if(exists $self->{auth}->{user}) {
return $self->{auth}->{user};
}
if( ! Rex::Config->has_user && Rex::Config->get_ssh_config_username(server => $self->to_s) ) {
Rex::Logger::debug("Checking for a user in .ssh/config");
return Rex::Config->get_ssh_config_username(server => $self->to_s);
}
return Rex::Config->get_user;
}
sub get_password {
my ($self) = @_;
if(exists $self->{auth}->{password}) {
return $self->{auth}->{password};
}
return Rex::Config->get_password;
}
sub get_public_key {
my ($self) = @_;
if(exists $self->{auth}->{public_key} && -f $self->{auth}->{public_key}) {
return $self->{auth}->{public_key};
}
if( ! Rex::Config->has_public_key && Rex::Config->get_ssh_config_public_key(server => $self->to_s) ) {
Rex::Logger::debug("Checking for a public key in .ssh/config");
return Rex::Config->get_ssh_config_public_key(server => $self->to_s);
}
return Rex::Config->get_public_key;
}
sub get_private_key {
my ($self) = @_;
if(exists $self->{auth}->{private_key} && -f $self->{auth}->{public_key}) {
return $self->{auth}->{private_key};
}
if( ! Rex::Config->has_private_key && Rex::Config->get_ssh_config_private_key(server => $self->to_s) ) {
Rex::Logger::debug("Checking for a private key in .ssh/config");
return Rex::Config->get_ssh_config_private_key(server => $self->to_s);
}
return Rex::Config->get_private_key;
}
sub get_auth_type {
my ($self) = @_;
if(exists $self->{auth}->{auth_type} && $self->{auth}->{auth_type}) {
return $self->{auth}->{auth_type};
}
if(exists $self->{auth}->{public_key} && -f $self->{auth}->{public_key}
&& exists $self->{auth}->{private_key} && -f $self->{auth}->{private_key}) {
return "try";
}
elsif(exists $self->{auth}->{user} && $self->{auth}->{user}
&& exists $self->{auth}->{password} && $self->{auth}->{password} ne "") {
return "try";
}
elsif(Rex::Config->get_krb5_auth) {
return "krb5";
}
elsif(Rex::Config->get_password_auth) {
return "pass";
}
elsif(Rex::Config->get_key_auth) {
return "key";
}
return "try";
}
sub get_sudo {
my ($self) = @_;
if(exists $self->{auth}->{sudo}) {
return $self->{auth}->{sudo};
}
return 0;
}
sub get_sudo_password {
my ($self) = @_;
if(exists $self->{auth}->{sudo_password}) {
return $self->{auth}->{sudo_password};
}
Rex::Config->get_sudo_password;
}
sub merge_auth {
my ($self, $other_auth) = @_;
my %new_auth;
my @keys = qw/user password private_key public_key auth_type sudo sudo_password/;
for my $key (@keys) {
my $call = "get_$key";
if(ref($self)->can($call)) {
$new_auth{$key} = $self->$call();
}
else {
$new_auth{$key} = $other_auth->{$key};
}
# other_auth has presedence
if(exists $other_auth->{$key} && Rex::Config->get_use_server_auth() == 0) {
$new_auth{$key} = $other_auth->{$key};
}
}
return %new_auth;
}
sub option {
my ($self, $option) = @_;
if(exists $self->{$option}) {
return $self->{$option};
}
}
sub gather_information {
my ($self) = @_;
my %info = Rex::Helper::System::info();
$self->{__hardware_info__} = \%info;
}
sub AUTOLOAD {
use vars qw($AUTOLOAD);
my $self = shift;
return $self if( $AUTOLOAD =~ m/DESTROY/ );
my ($wanted_data) = ($AUTOLOAD =~ m/::([a-z0-9A-Z]+)$/);
if(scalar(keys %{ $self->{__hardware_info__} }) == 0) {
$self->gather_information;
}
if(exists $self->{__hardware_info__}->{$wanted_data}) {
return $self->{__hardware_info__}->{$wanted_data};
}
if(exists $self->{$wanted_data}) {
return $self->{$wanted_data};
}
return undef;
}
sub evaluate_hostname {
my ($self) = @_;
my @servers = Rex::Commands::evaluate_hostname($self->to_s);
my @multiple_me;
for (@servers) {
push @multiple_me, ref($self)->new(%{ $self });
$multiple_me[-1]->{name} = $_;
}
return @multiple_me;
}
1;