our
$VERSION
=
'1.16.0'
;
@EXPORT
=
qw(create_host get_host delete_host host_entry)
;
sub
host_entry {
my
(
$res_name
,
%option
) =
@_
;
$option
{ensure} ||=
"present"
;
my
$name
=
$res_name
;
if
(
exists
$option
{host} ) {
$name
=
$option
{host};
}
my
$file
=
"/etc/hosts"
;
if
(
exists
$option
{file} ) {
$file
=
$option
{file};
}
Rex::get_current_connection()->{reporter}
->report_resource_start(
type
=>
"host_entry"
,
name
=>
$res_name
);
my
$old_md5
= md5(
$file
);
if
(
$option
{ensure} eq
"present"
) {
&create_host
(
$name
, \
%option
);
}
else
{
&delete_host
(
$name
);
}
my
$new_md5
= md5(
$file
);
if
(
$new_md5
ne
$old_md5
) {
if
(
exists
$option
{on_change} &&
ref
$option
{on_change} eq
"CODE"
) {
$option
{on_change}->(
$name
,
%option
);
}
Rex::get_current_connection()->{reporter}->report(
changed
=> 1,
message
=>
"Resource host_entry changed to $option{ensure}"
);
}
Rex::get_current_connection()->{reporter}
->report_resource_end(
type
=>
"host_entry"
,
name
=>
$res_name
);
}
sub
create_host {
my
(
$host
,
$data
) =
@_
;
if
( !
defined
$data
->{
"ip"
} ) {
Rex::Logger::info(
"You need to set an ip for $host"
);
die
(
"You need to set an ip for $host"
);
}
$data
->{file} ||=
"/etc/hosts"
;
Rex::Logger::debug(
"Creating host $host"
);
my
@cur_host
= get_host(
$host
, {
file
=>
$data
->{file} } );
if
( !
@cur_host
) {
my
$fh
= file_append
$data
->{file};
$fh
->
write
(
$data
->{
"ip"
} .
"\t"
.
$host
);
if
(
exists
$data
->{
"aliases"
} ) {
$fh
->
write
(
" "
.
join
(
" "
, @{
$data
->{
"aliases"
} } ) );
}
$fh
->
write
(
"\n"
);
$fh
->
close
;
}
else
{
if
(
$data
->{
"ip"
} eq
$cur_host
[0]->{
"ip"
}
&&
join
(
" "
, @{
$data
->{
"aliases"
} || [] } ) eq
join
(
" "
, @{
$cur_host
[0]->{
"aliases"
} } ) )
{
Rex::Logger::debug(
"Nothing to update for host $host"
);
return
;
}
Rex::Logger::debug(
"Host already exists. Updating..."
);
delete_host(
$host
,
$data
->{file} );
return
create_host(
@_
);
}
}
sub
delete_host {
my
(
$host
,
$file
) =
@_
;
Rex::Logger::debug(
"Deleting host $host"
);
$file
||=
"/etc/hosts"
;
if
( get_host(
$host
, {
file
=>
$file
} ) ) {
my
$fh
= file_read
$file
;
my
@content
=
$fh
->read_all;
$fh
->
close
;
my
@new_content
=
grep
{ !/\s\Q
$host
\E\b/ }
@content
;
$fh
= file_write
$file
;
$fh
->
write
(
@new_content
);
$fh
->
close
;
}
else
{
Rex::Logger::debug(
"Host does not exists."
);
}
}
sub
get_host {
my
(
$hostname
,
@lines
) =
@_
;
Rex::Logger::debug(
"Getting host ($hostname) information"
);
my
$file
=
"/etc/hosts"
;
my
@content
;
if
(
@lines
&& !
ref
$lines
[0] ) {
@content
=
@lines
;
}
else
{
if
(
ref
$lines
[0] eq
"HASH"
) {
$file
=
$lines
[0]->{file};
}
my
$fh
= file_read
$file
;
@content
=
$fh
->read_all;
$fh
->
close
;
}
my
@hosts
= _parse_hosts(
@content
);
my
@ret
;
for
my
$item
(
@hosts
) {
if
(
$item
->{host} eq
$hostname
) {
push
@ret
,
$item
;
}
else
{
push
@ret
,
$item
if
(
grep
{
$_
eq
$hostname
} @{
$item
->{aliases} } );
}
}
return
@ret
;
}
sub
_parse_hosts {
my
(
@lines
) =
@_
;
my
@ret
;
for
my
$line
(
@lines
) {
chomp
$line
;
next
if
(
$line
=~ m/^
next
if
( !
$line
);
next
if
(
$line
=~ m/^\s*$/ );
my
(
$ip
,
$_host
,
@aliases
) =
split
( /\s+/,
$line
);
push
@ret
,
{
ip
=>
$ip
,
host
=>
$_host
,
aliases
=> \
@aliases
,
};
}
return
@ret
;
}
1;