Hide Show 27 lines of Pod
our
$VERSION
=
'1.16.0'
;
Hide Show 29 lines of Pod
sub
new {
my
$that
=
shift
;
my
$proto
=
ref
(
$that
) ||
$that
;
my
$self
= {
@_
};
bless
(
$self
,
$proto
);
if
( !
exists
$self
->{name} ) {
die
(
"You have to define a task name."
);
}
$self
->{no_ssh} ||= 0;
$self
->{func} ||=
sub
{ };
$self
->{executor} ||= Rex::Interface::Executor->create;
$self
->{opts} ||= {};
$self
->{args} ||= [];
$self
->{connection} =
undef
;
if
( !
exists
$self
->{exit_on_connect_fail} ) {
$self
->{exit_on_connect_fail} = 1;
}
return
$self
;
}
Hide Show 6 lines of Pod
sub
connection {
my
(
$self
) =
@_
;
if
( !
exists
$self
->{connection} || !
$self
->{connection} ) {
$self
->{connection} =
Rex::Interface::Connection->create(
$self
->get_connection_type );
}
$self
->{connection};
}
sub
set_connection {
my
(
$self
,
$conn
) =
@_
;
$self
->{connection} =
$conn
;
}
Hide Show 6 lines of Pod
sub
executor {
my
(
$self
) =
@_
;
$self
->{executor}->set_task(
$self
);
return
$self
->{executor};
}
Hide Show 6 lines of Pod
sub
hidden {
my
(
$self
) =
@_
;
return
$self
->{hidden};
}
Hide Show 6 lines of Pod
sub
server {
my
(
$self
) =
@_
;
my
@server
= @{
$self
->{server} };
my
@ret
= ();
if
(
ref
(
$server
[-1] ) eq
"HASH"
) {
Rex::deprecated(
undef
,
"0.40"
,
"Defining extra credentials within the task creation is deprecated."
,
"Please use set auth => task => 'taskname' instead."
);
my
$data
=
pop
(
@server
);
$self
->set_auth(
"user"
,
$data
->{
'user'
} );
$self
->set_auth(
"password"
,
$data
->{
'password'
} );
if
(
exists
$data
->{
"private_key"
} ) {
$self
->set_auth(
"private_key"
,
$data
->{
"private_key"
} );
$self
->set_auth(
"public_key"
,
$data
->{
"public_key"
} );
}
}
if
(
ref
(
$self
->{server} ) eq
"ARRAY"
&&
scalar
( @{
$self
->{server} } ) > 0 )
{
for
my
$srv
( @{
$self
->{server} } ) {
if
(
ref
(
$srv
) eq
"CODE"
) {
push
(
@ret
,
&$srv
() );
}
else
{
if
(
ref
$srv
&&
$srv
->isa(
"Rex::Group::Entry::Server"
) ) {
push
(
@ret
,
$srv
->get_servers );
}
else
{
push
(
@ret
,
$srv
);
}
}
}
}
elsif
(
ref
(
$self
->{server} ) eq
"CODE"
) {
push
(
@ret
, &{
$self
->{server} }() );
}
else
{
push
(
@ret
, Rex::Group::Entry::Server->new(
name
=>
"<local>"
) );
}
return
[
@ret
];
}
Hide Show 6 lines of Pod
sub
set_server {
my
(
$self
,
@server
) =
@_
;
$self
->{server} = \
@server
;
}
Hide Show 6 lines of Pod
sub
delete_server {
my
(
$self
) =
@_
;
delete
$self
->{current_server};
delete
$self
->{server};
$self
->rethink_connection;
}
Hide Show 6 lines of Pod
sub
current_server {
my
(
$self
) =
@_
;
return
$self
->{current_server}
|| Rex::Group::Entry::Server->new(
name
=>
"<local>"
);
}
Hide Show 6 lines of Pod
sub
desc {
my
(
$self
) =
@_
;
return
$self
->{desc};
}
Hide Show 6 lines of Pod
sub
set_desc {
my
(
$self
,
$desc
) =
@_
;
$self
->{desc} =
$desc
;
}
Hide Show 6 lines of Pod
sub
is_remote {
my
(
$self
) =
@_
;
if
(
exists
$self
->{current_server} ) {
if
(
$self
->{current_server} ne
'<local>'
) {
return
1;
}
}
else
{
if
(
exists
$self
->{server} &&
scalar
( @{
$self
->{server} } ) > 0 ) {
return
1;
}
}
return
0;
}
Hide Show 6 lines of Pod
sub
is_local {
my
(
$self
) =
@_
;
return
$self
->is_remote() == 0 ? 1 : 0;
}
Hide Show 6 lines of Pod
sub
is_http {
my
(
$self
) =
@_
;
return
(
$self
->{
"connection_type"
}
&&
lc
(
$self
->{
"connection_type"
} ) eq
"http"
);
}
Hide Show 6 lines of Pod
sub
is_https {
my
(
$self
) =
@_
;
return
(
$self
->{
"connection_type"
}
&&
lc
(
$self
->{
"connection_type"
} ) eq
"https"
);
}
Hide Show 6 lines of Pod
sub
is_openssh {
my
(
$self
) =
@_
;
return
(
$self
->{
"connection_type"
}
&&
lc
(
$self
->{
"connection_type"
} ) eq
"openssh"
);
}
Hide Show 6 lines of Pod
sub
want_connect {
my
(
$self
) =
@_
;
return
$self
->{no_ssh} == 0 ? 1 : 0;
}
Hide Show 26 lines of Pod
sub
get_connection_type {
my
(
$self
) =
@_
;
if
(
$self
->is_http ) {
return
"HTTP"
;
}
elsif
(
$self
->is_https ) {
return
"HTTPS"
;
}
elsif
(
$self
->is_remote &&
$self
->is_openssh &&
$self
->want_connect ) {
return
"OpenSSH"
;
}
elsif
(
$self
->is_remote &&
$self
->want_connect ) {
return
Rex::Config->get_connection_type();
}
elsif
(
$self
->is_remote ) {
return
"Fake"
;
}
else
{
return
"Local"
;
}
}
Hide Show 6 lines of Pod
sub
modify {
my
(
$self
,
$key
,
$value
) =
@_
;
if
(
ref
(
$self
->{
$key
} ) eq
"ARRAY"
) {
push
( @{
$self
->{
$key
} },
$value
);
}
else
{
$self
->{
$key
} =
$value
;
}
$self
->rethink_connection;
}
Hide Show 6 lines of Pod
sub
rethink_connection {
my
(
$self
) =
@_
;
delete
$self
->{connection};
}
Hide Show 6 lines of Pod
sub
user {
my
(
$self
) =
@_
;
if
(
exists
$self
->{auth} &&
$self
->{auth}->{user} ) {
return
$self
->{auth}->{user};
}
}
Hide Show 6 lines of Pod
sub
set_user {
my
(
$self
,
$user
) =
@_
;
$self
->{auth}->{user} =
$user
;
}
Hide Show 6 lines of Pod
sub
password {
my
(
$self
) =
@_
;
if
(
exists
$self
->{auth} &&
$self
->{auth}->{password} ) {
return
$self
->{auth}->{password};
}
}
Hide Show 6 lines of Pod
sub
set_password {
my
(
$self
,
$password
) =
@_
;
$self
->{auth}->{password} =
$password
;
}
Hide Show 6 lines of Pod
sub
name {
my
(
$self
) =
@_
;
return
$self
->{name};
}
Hide Show 6 lines of Pod
sub
code {
my
(
$self
) =
@_
;
return
$self
->{func};
}
Hide Show 6 lines of Pod
sub
set_code {
my
(
$self
,
$code
) =
@_
;
$self
->{func} =
$code
;
}
Hide Show 6 lines of Pod
sub
run_hook {
my
(
$self
,
$server
,
$hook
,
@more_args
) =
@_
;
my
$old_server
;
for
my
$code
( @{
$self
->{
$hook
} } ) {
if
(
$hook
eq
"after"
) {
$code
->(
$$server
,
(
$self
->{
"__was_authenticated"
} || 0 ),
{
$self
->get_opts },
@more_args
);
}
else
{
$old_server
=
$$server
if
$server
;
$code
->(
$$server
,
$server
, {
$self
->get_opts },
@more_args
);
if
(
$old_server
&&
$old_server
ne
$$server
) {
$self
->{current_server} =
$$server
;
}
}
}
}
Hide Show 9 lines of Pod
sub
set_auth {
my
(
$self
,
$key
,
$value
) =
@_
;
if
(
scalar
(
@_
) > 3 ) {
my
$_d
=
shift
;
$self
->{auth} = {
@_
};
}
else
{
$self
->{auth}->{
$key
} =
$value
;
}
}
Hide Show 7 lines of Pod
sub
merge_auth {
my
(
$self
,
$server
) =
@_
;
my
%auth
=
$server
->merge_auth(
$self
->{auth} );
return
\
%auth
;
}
Hide Show 6 lines of Pod
sub
get_sudo_password {
my
(
$self
) =
@_
;
my
$server
=
$self
->connection->server;
my
%auth
=
$server
->merge_auth(
$self
->{auth} );
return
$auth
{sudo_password};
}
Hide Show 6 lines of Pod
sub
parallelism {
my
(
$self
) =
@_
;
return
$self
->{parallelism};
}
Hide Show 6 lines of Pod
sub
set_parallelism {
my
(
$self
,
$para
) =
@_
;
$self
->{parallelism} =
$para
;
}
Hide Show 6 lines of Pod
sub
connect
{
my
(
$self
,
$server
,
%override
) =
@_
;
if
( !
ref
$server
) {
$server
= Rex::Group::Entry::Server->new(
name
=>
$server
);
}
$self
->{current_server} =
$server
;
$self
->run_hook( \
$server
,
"before"
);
$self
->rethink_connection;
my
$user
=
$self
->user;
my
$auth
=
$self
->merge_auth(
$server
);
if
(
exists
$override
{auth} ) {
$auth
=
$override
{auth};
$user
=
$auth
->{user};
}
my
$rex_int_conf
= Rex::Commands::get(
"rex_internals"
);
Rex::Logger::debug( Dumper(
$rex_int_conf
) );
Rex::Logger::debug(
"Auth-Information inside Task:"
);
for
my
$key
(
keys
%{
$auth
} ) {
my
$data
=
$auth
->{
$key
};
$data
= Rex::Logger::masq(
"%s"
,
$data
)
if
$key
eq
'password'
;
$data
= Rex::Logger::masq(
"%s"
,
$data
)
if
$key
eq
'sudo_password'
;
$data
||=
""
;
Rex::Logger::debug(
"$key => [[$data]]"
);
}
$auth
->{public_key} = resolv_path(
$auth
->{public_key}, 1 )
if
(
$auth
->{public_key} );
$auth
->{private_key} = resolv_path(
$auth
->{private_key}, 1 )
if
(
$auth
->{private_key} );
my
$profiler
= Rex::Profiler->new;
my
%connect_hash
= %{
$auth
};
$connect_hash
{server} =
$server
;
Rex::push_connection(
{
conn
=>
$self
->connection,
ssh
=>
$self
->connection->get_connection_object,
server
=>
$server
,
cache
=> Rex::Interface::Cache->create(),
task
=> [],
profiler
=>
$profiler
,
reporter
=> Rex::Report->create( Rex::Config->get_report_type ),
notify
=> Rex::Notify->new(),
}
);
push
@{ Rex::get_current_connection()->{task} },
$self
;
$profiler
->start(
"connect"
);
eval
{
$self
->connection->
connect
(
%connect_hash
);
1;
} or
do
{
if
( !
defined
Rex::Config->get_fallback_auth ) {
croak $@;
}
};
$profiler
->end(
"connect"
);
if
( !
$self
->connection->is_connected ) {
Rex::pop_connection();
croak(
"Couldn't connect to $server."
);
}
elsif
( !
$self
->connection->is_authenticated ) {
Rex::pop_connection();
my
$message
=
"Couldn't authenticate against $server. It may be caused by one or more of:\n"
;
$message
.=
" - wrong username, password, key or passphrase\n"
;
$message
.=
" - changed remote host key\n"
;
$message
.=
" - root is not permitted to login over SSH\n"
if
(
$connect_hash
{user} eq
'root'
);
if
( !
exists
$override
{auth} ) {
my
$fallback_auth
= Rex::Config->get_fallback_auth;
if
(
ref
$fallback_auth
eq
"ARRAY"
) {
my
$ret_eval
;
for
my
$fallback_a
( @{
$fallback_auth
} ) {
$ret_eval
=
eval
{
$self
->
connect
(
$server
,
auth
=>
$fallback_a
); };
}
return
$ret_eval
if
$ret_eval
;
}
}
croak(
$message
);
}
else
{
Rex::Logger::debug(
"Successfully authenticated on $server."
)
if
(
$self
->connection->get_connection_type ne
"Local"
);
$self
->{
"__was_authenticated"
} = 1;
}
$self
->run_hook( \
$server
,
"around"
);
return
1;
}
Hide Show 6 lines of Pod
sub
disconnect {
my
(
$self
,
$server
) =
@_
;
$self
->run_hook( \
$server
,
"around"
, 1 );
$self
->connection->disconnect;
my
%args
= Rex::Args->getopts;
if
(
defined
$args
{
'd'
} &&
$args
{
'd'
} > 2 ) {
Rex::Commands::profiler()->report;
}
delete
$self
->{connection};
pop
@{ Rex::get_current_connection()->{task} };
Rex::pop_connection();
$self
->run_hook( \
$server
,
"after"
);
}
Hide Show 6 lines of Pod
sub
get_data {
my
(
$self
) =
@_
;
return
{
func
=>
$self
->{func},
server
=>
$self
->{server},
desc
=>
$self
->{desc},
no_ssh
=>
$self
->{no_ssh},
hidden
=>
$self
->{hidden},
auth
=>
$self
->{auth},
before
=>
$self
->{
before
},
after
=>
$self
->{
after
},
around
=>
$self
->{
around
},
name
=>
$self
->{name},
executor
=>
$self
->{executor},
connection_type
=>
$self
->{connection_type},
opts
=>
$self
->{opts},
args
=>
$self
->{args},
};
}
Hide Show 6 lines of Pod
sub
run {
return
pre_40_run(
@_
)
unless
ref
$_
[0];
my
(
$self
,
$server
,
%options
) =
@_
;
$options
{opts} ||= {
$self
->get_opts };
$options
{args} ||= [
$self
->get_args ];
$options
{params} ||=
$options
{opts};
if
( !
ref
$server
) {
$server
= Rex::Group::Entry::Server->new(
name
=>
$server
);
}
if
( !
$_
[1] ) {
return
Rex::TaskList->create()->run(
$self
,
%options
);
}
my
(
$in_transaction
,
$start_time
);
$start_time
=
time
;
if
(
$server
ne
"<func>"
) {
$in_transaction
=
$options
{in_transaction};
eval
{
$self
->
connect
(
$server
) };
if
($@) {
my
$error
= $@;
$self
->{
"__was_authenticated"
} = 0;
$self
->run_hook( \
$server
,
"after"
);
die
$error
;
}
if
( Rex::Args->is_opt(
"c"
) ) {
if
( !Rex::get_cache()->load() ) {
Rex::Logger::debug(
"No cache found, need to collect new data."
);
$server
->gather_information;
}
}
if
( !
$server
->test_perl ) {
Rex::Logger::info(
"There is no perl interpreter found on this system. "
.
"Some commands may not work. Sudo won't work."
,
"warn"
);
sleep
3;
}
}
else
{
$self
->set_connection(
Rex::get_current_connection()->{task}->[-1]->connection )
if
Rex::get_current_connection()->{task}->[-1];
push
@{ Rex::get_current_connection()->{task} },
$self
;
}
my
@ret
;
my
$wantarray
=
wantarray
;
eval
{
$self
->set_opts( %{
$options
{params} } )
if
ref
$options
{params} eq
"HASH"
;
if
(
$wantarray
) {
@ret
=
$self
->executor->
exec
(
$options
{params},
$options
{args} );
}
else
{
$ret
[0] =
$self
->executor->
exec
(
$options
{params},
$options
{args} );
}
my
$notify
= Rex::get_current_connection()->{notify};
$notify
->run_postponed();
} or
do
{
if
($@) {
my
$error
= $@;
Rex::get_current_connection()->{reporter}
->report_resource_failed(
message
=>
$error
);
Rex::get_current_connection()->{reporter}->report_task_execution(
failed
=> 1,
start_time
=>
$start_time
,
end_time
=>
time
,
message
=>
$error
,
);
Rex::get_current_connection()->{reporter}->write_report();
pop
@{ Rex::get_current_connection()->{task} };
die
(
$error
);
}
};
if
(
$server
ne
"<func>"
) {
if
( Rex::Args->is_opt(
"c"
) ) {
Rex::get_cache()->save();
}
Rex::get_current_connection()->{reporter}->report_task_execution(
failed
=> 0,
start_time
=>
$start_time
,
end_time
=>
time
,
);
Rex::get_current_connection()->{reporter}->write_report();
if
(
$in_transaction
) {
$self
->run_hook( \
$server
,
"around"
, 1 );
$self
->run_hook( \
$server
,
"after"
);
}
else
{
$self
->disconnect(
$server
);
}
}
else
{
pop
@{ Rex::get_current_connection()->{task} };
}
if
(
$wantarray
) {
return
@ret
;
}
else
{
return
$ret
[0];
}
}
sub
pre_40_run {
my
(
$class
,
$task_name
,
$server_overwrite
,
$params
) =
@_
;
Rex::deprecated(
"Rex::Task->run()"
,
"0.40"
);
my
$tasklist
= Rex::TaskList->create;
my
$task
=
$tasklist
->get_task(
$task_name
);
$task
->set_server(
$server_overwrite
)
if
$server_overwrite
;
$tasklist
->run(
$task
,
params
=>
$params
);
}
Hide Show 6 lines of Pod
sub
modify_task {
my
$class
=
shift
;
my
$task
=
shift
;
my
$key
=
shift
;
my
$value
=
shift
;
Rex::TaskList->create()->get_task(
$task
)->modify(
$key
=>
$value
);
}
Hide Show 6 lines of Pod
sub
is_task {
my
(
$class
,
$task
) =
@_
;
return
Rex::TaskList->create()->is_task(
$task
);
}
Hide Show 6 lines of Pod
sub
get_tasks {
my
(
$class
,
@tmp
) =
@_
;
return
Rex::TaskList->create()->get_tasks(
@tmp
);
}
Hide Show 6 lines of Pod
sub
get_desc {
my
(
$class
,
@tmp
) =
@_
;
return
Rex::TaskList->create()->get_desc(
@tmp
);
}
Hide Show 6 lines of Pod
sub
exit_on_connect_fail {
my
(
$self
) =
@_
;
return
$self
->{exit_on_connect_fail};
}
Hide Show 6 lines of Pod
sub
set_exit_on_connect_fail {
my
(
$self
,
$exit
) =
@_
;
$self
->{exit_on_connect_fail} =
$exit
;
}
Hide Show 6 lines of Pod
sub
get_args {
my
(
$self
) =
@_
;
@{
$self
->{args} || [] };
}
Hide Show 6 lines of Pod
sub
get_opts {
my
(
$self
) =
@_
;
%{
$self
->{opts} || {} };
}
Hide Show 6 lines of Pod
sub
set_args {
my
(
$self
,
@args
) =
@_
;
$self
->{args} = \
@args
;
}
Hide Show 6 lines of Pod
sub
set_opt {
my
(
$self
,
$key
,
$value
) =
@_
;
$self
->{opts}->{
$key
} =
$value
;
}
Hide Show 6 lines of Pod
sub
set_opts {
my
(
$self
,
%opts
) =
@_
;
$self
->{opts} = \
%opts
;
}
Hide Show 6 lines of Pod
sub
clone {
my
$self
=
shift
;
return
Rex::Task->new( %{
$self
->get_data } );
}
1;